Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-76666

setlocale() problems with locale strings longer than 255 characters

    XMLWordPrintable

Details

    Description

      This was detected @ moodle-plugin-ci #193, read it long for details.

      Summary

      1. When setlocale(LC_ALL, 0) is called, it returns the current locales PHP is using (relying completely on each OS setlocale facilities). The returned values can be:
        1. If all the categories (LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES) are the same, it just returns one locale (example: "en_AU.UTF-8").
        2. If there are differences, then it returns the details for all categories (example: LC_CTYPE=en_AU.UTF-8;LC_NUMERIC=C;LC_TIME=en_AU.UTF-8;LC_COLLATE=en_AU.UTF-8;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER =en_AU.UTF-8").
        3. The above is valid for both linux and windows (in the case of windows the locales just will look different, like "English_Australia.1252", for example).
        4. In Macs (that are BSD), the returned information is always of the form "en_AU.UTF-8/en_AU.UTF-8/C/C/en_AU.UTF-8/C" (aka, 6 elements separated by slashes. Each element is one of the LC categories mentioned above).
      2. It seems that some recent linux versions (Ubuntu 20.04 and up, for example), have added more categories to the standard 6 mentioned above. For example: LC_PAPER, LCNAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION). PHP isn't aware of them, AFAIK, see the setlocale() docs
      3. No matter of that, in those systems, the information returned is noticeably longer. For example: "LC_CTYPE=en_AU.UTF-8;LC_NUMERIC=C.UTF-8;LC_TIME=en_AU.UTF-8;LC_COLLATE=en_AU.UTF-8;LC_MONETARY=C.UTF-8;LC_MESSAGES=C.UTF-8;LC_PAPER=en_AU.UTF-8;LC_NAME=en_AU.UTF-8;LC_ADDRESS=en_AU.UTF-8;LC_TELEPHONE=en_AU.UTF-8;LC_MEASUREMENT=en_AU.UTF-8;LC_IDENTIFICATION=en_AU.UTF-8"
      4. In various places of Moodle codebase we are doing:

        $original = setlocale(LC_ALL, 0); // Get current locale.
        // Do something with locales...
        ...
        setlocale(LC_ALL, $original); // Restore the original locale.
        

      5. When the $original string (that can be of different length, as explained above) is > 255 chars. A warning (or exception) happens when we try to set the original locale back, with message:

        setlocale(): Specified locale name is too long 
        

      Goal

      This issue is about to find all the places (local_langimport and others) where we are playing with setlocale(LC_ALL, 0) to fetch the current locales and trying to restore to it later.

      In all them, if the length is > 255, we'll have to proceed to split the long string and set the categories one by one (or convert to array, that is also acceptable).

      Ciao

      Attachments

        Activity

          People

            stronk7 Eloy Lafuente (stronk7)
            stronk7 Eloy Lafuente (stronk7)
            Sara Arjona (@sarjona) Sara Arjona (@sarjona)
            Paul Holden Paul Holden
            CiBoT CiBoT
            Adrian Greeve, David Woloszyn, Huong Nguyen, Jake Dallimore, Meirza, Michael Hawkins, Raquel Ortega, Safat Shahin, Stevani Andolo, David Woloszyn, Huong Nguyen, Jake Dallimore, Meirza, Michael Hawkins, Raquel Ortega, Safat Shahin, Stevani Andolo
            Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              16/Jan/23

              Time Tracking

                Estimated:
                Original Estimate - 0 minutes
                0m
                Remaining:
                Remaining Estimate - 0 minutes
                0m
                Logged:
                Time Spent - 1 day, 1 hour, 50 minutes
                1d 1h 50m