Overview
The String API is how you get language text strings to use in the user interface. It handles internationalisation issues, and will use a number of settings and environment variables to present the best text to every user. Moodle has a mechanism that allows a number of places to be searched (in order) to find language strings. This enables language strings to be packaged with plugins and avoids the step of having to copy the language files over to the language directory when a plugin is installed.
Moodle also provide general string functions like substr, strlen etc. for multibyte safe, string operations. It uses mbstring or iconv for UTF-8 strings and falls back to typo3.
Basic concepts
When it is required to lookup a string, two basic items of information are required.
- The component providing the string.
- The identifier of the string.
Example: The function call get_string('editingquiz', 'mod_quiz') will return "Editing quiz" if the current language is English, or relevant translation of the text. Here the string identifier is "editingquiz" and the string is provided by the "mod_quiz" component (that is the Quiz activity module).
Adding language file to plugin
Language support for plugin(s) is added by creating a lang/en/ subdirectory in the plugin directory and putting the plugin's English string file there. The name of the string file is supposed to follow the plugin's component name, so that it is something like plugintype_pluginname.php.
The default "en" language is the Australian English which is same as the British English when it comes to spelling and grammar. American English is a separate language pack "en_us".
There is no need to include languages other than the default English, as almost all approved plugin strings will be automatically imported into AMOS for translation by the language packs translators.
Adding a string to the language file
Strings are defined via the associative array $string provided by the string file. The array key is the string identifier, the value is the string text in the given language.
$string['editingquiz'] = 'Editing quiz';
$string['editingquiz_help'] = 'Help for editing quiz';
Run-time parameters
Strings can define placeholders like {$a} or {$a->foobar}. These placeholders are replaced with a value passed to the get_string() function call.
// Strings defined in the language file.
$string['greeting'] = 'Dear {$a}';
$string['info'] = 'There are {$a->count} new messages from {$a->from}.';
// Passing values for the placeholders.
echo get_string('greeting', 'tool_example', 'Mr. Anderson');
echo get_string('info', 'tool_example', ['count' => 42, 'from' => 'Mr. Smith']);
Help strings
Help strings are texts that are displayed in the help tooltips. There are certain conventions on how to define them.
Help strings names start with the string name of the setting to which they apply, so that they are kept together in the language file.
- stringname - identifier of the string we provide the help for, may be used as a title of the help popup
- stringname_help - string with the help text
- stringname_link - an optional string naming a path in Moodle Docs, only if required, calculated just like the link in the footer to go to the right language etc, and shown after the help text in the popup as a link with an icon to "More help...". These strings don't usually need to be translated. (They were previously hidden in the AMOS UI then unhidden in 2023. See MDLSITE-7236 for details.)
- stringname_desc - an admin setting description replacing the legacy configstringname
Example:
$string['submissionsize'] = 'Submission size';
$string['submissionsize_help'] = 'Blah blah blah some useful text, optionally using Markdown syntax';
$string['submissionsize_link'] = 'mod/workshop/submission';
$string['submissionsize_desc'] = 'Default value for submission size. This value will be pre-filled and can be blah blah ...';
Help string text should be short and simple - two small paragraphs maximum with no headings, no links, no bold, no tables etc.
Markdown can be used for some basic formatting of strings with the "_help" suffix. It is recommended to stick to paragraphs and lists only. Markdown can only be used for help strings, not for other language strings.
More help links
To display the optional More help... link at the bottom of the help popup, a string with the "_link" suffix must exist beside the relevant "_help" string. These link strings should consist of a short relative path like 'component/thing' (eg. 'mod/folder/view' or 'group/import'). This gets turned into a link to MoodleDocs in the user's language, and for the appropriate Moodle version.
Example:
$string['groupimport_link'] = 'group/import';
will make a link to something like 'https://docs.moodle.org/32/en/group/import' (if you are an English user of Moodle 3.2). This page in turn should be a redirect page to the actual page providing the info. Note the 'https://docs.moodle.org' part comes from $CFG->docroot.
The second option is that you can give an absolute link, if you want, and that will be used unmodified.
$string['patronising_link'] = <nowiki>'http://lmgtfy.com/?q=Moodle+for+dummies';</nowiki>
This case is detected by seeing if the string starts with http:// or https://. This option is useful if the documentation for your plugin is hosted at Github wiki, for example.
The third option is to start the link with %%WWWROOT%%. That is replaced by $CFG->wwwroot. This is useful for contributed plugins that want to keep the help within the plugin.
Words for roles
The following words should be used in the English (en) help strings whenever it is necessary to refer to people with particular roles in a generic sense.
- Participants - all people with a role
- Teachers - people with some sort of a facilitation/editing role
- Students - people primarily there to learn
- Users - people across the site
(Martin Dougiamas 16:13, 20 April 2010 (UTC): I'm not entirely comfortable with this choice even though I just re-confirmed it, as I'd prefer to be using words like facilitator/moderator to subtly and continually promote a less transmissionist pedgagogy and I know many Moodle users would agree. However, I think these terms are far more commonly used in the community and in discussion, and from the point of view that we need to build a consistent system for usability they are less distracting and better for documentation.)
Files
String functions are defined in
- lib/moodlelib.php - locale related functions
- lib/textlib.class.php - general string functions (substr, strlen etc.)
Functions and examples
There are three main functions, used in moodle for getting/displaying the localised string, based on user preferred language.
get_string()
Returns a localised string for current user.
Example for displaying string "This is my plug-in" in any language that supports on your site, then you need to use the following identifier in language file (located in appropriate lang directory)
$string['plugintitle'] = 'This is my plug-in';
If you want to display this string in any supported language, then you would use this function.
echo get_string('plugintitle', 'module_pluginlangfilename');
If you want to substitute value in the language string then use {$a} for substituting value. $a is an object, string or number that can be used within translation strings. The variable has to be $a, and it has to be in single quotes. For example, if you want to display answer number in Drag & drop plugin then add
$string['answerno1'] = 'Answer {$a}'; //Substituting string/integer $string['answerno2'] = 'Answer {$a->name}'; //Substituting object member
in qtype_dragdrop.php (Drag & Drop language file). And call it using
//Get string by substituting integer. get_string('answerno1', 'qtype_dragdrop', $number); //Get string by substituting object member integer $user->number = 10; get_string('answerno2', 'qtype_dragdrop', $user);
In Moodle 2.3 there is a new argument to this function $lazyload. Setting $lazyload to true causes get_string to return a lang_string object rather than the string itself.
$stringobject = get_string('answerno', 'qtype_dragdrop', $number, true);
The fetching of the string is then put off until the string object is first used. The object can be used by calling it's out method or by casting the object to a string, either directly e.g.
(string)$stringobject
or indirectly by using the string within another string or echoing it out e.g.
echo $stringobject;
return "
{$stringobject}
";
Note: using $lazyload and attempting to use the string as an array key will cause a fatal error as objects cannot be used as array keys.
get_strings()
Converts an array of string names to localised strings for a specific plugin. lazy loading is not supported in this function.
$txt = get_strings(array('enable', 'disable', 'up', 'down', 'none'), 'qtype_dragdrop'); echo $txt->up; //Display localised string for up echo $txt->down //Display localised string for down
print_string()
Prints out a translated string by using get_string() function
lang_string class
In Moodle 2.3 a special class (lang_string) is used to create an object representation of a string request. In this case string processing doesn't occur until the object is first used. The class was created especially to aid performance in areas where strings were required to be generated but were not necessarily used. As an example the admin navigation tree when generated uses over 1500 strings, of which normally only 1/3 are ever actually printed at any time. The performance advantage is achieved by not actually processing strings that aren't being used, as such reducing the processing required for the page.
lang_string class can be used in two ways
- Setting $lazyload (fourth argument of the get_string function), to true.
$string = get_string('yes', 'qtype_dragdrop', null, true);
- Direct instantiation
$string = new lang_string('yes', 'qtype_dragdrop', null, 'en');
String manager
Most of function listed above are just handful wrappers for the methods provided by the string manager class. Some strings related functionality is available only via directly calling the manager's methods.
$stringman = get_string_manager();
The factory function get_string_manager() returns singleton instance of core_string_manager_install in early stages of the site installation, or instance of core_string_manager_standard in all normal situations. These managers implement interface core_string_manager. Methods provided by the interface are
- get_string()
- Returns the given component string localised in the given language. Can be used to obtain the translation of the string in the other language than the current user's language.
- string_exists()
- Does the given string actually exist? This is typically checked by a code like
if (get_string_manager()->string_exists('stringidentifier', 'component_name')) {
// Do something.
}
- string_deprecated()
- Has the string been deprecated? See String deprecation for details.
- get_list_of_countries()
- Returns a localised list of all country names, sorted by country keys.
- get_list_of_languages()
- Returns a localised list of languages, sorted by code keys.
- translation_exists()
- Checks if the translation exists for the given language.
- get_list_of_translations()
- Returns localised list of installed language packs.
- get_list_of_currencies()
- Returns localised list of known currencies.
- load_component_strings()
- Loads all strings for one component.
- reset_caches()
- Invalidates all caches, should the manager use some.
- get_revision()
- Returns string revision counter.
Custom string managers
Moodle 2.9 Plugins can provide custom implementation of the string manager. This is supposed to be used in experimental and/or development scenarios only, not in typical production environment. See MDL-49361 for use cases and implementation details. An example of such an implementation can be found at moodle-local_stringman.git repository.
// Custom string manager class can be defined in the main config.php file.
$CFG->customstringmanager = '\local_stringman\dummy_string_manager';
textlib (core_text) class
textlib class provide pool of safe functions to operate on UTF-8 text. textlib provide set of static functions to operate on strings and gets included in setup.php
Moodle 2.6 In Moodle 2.6 the textlib class was renamed to core_text.
asort()
Locale aware sorting, the key associations are kept, values are sorted alphabetically.
code2utf8
Returns the utf8 string corresponding to the unicode value
convert
Converts the text between different encodings. It uses iconv extension with //TRANSLIT parameter, fall back to typo3
encode_mimeheader
Generate a correct base64 encoded header to be used in MIME mail messages.
entities_to_utf8
Converts all the numeric entities &#nnnn; or &#xnnn; to UTF-8
specialtoascii
Converts upper unicode characters to plain ascii, the returned string may contain unconverted unicode characters.
strlen
Multibyte safe strlen() function, uses iconv for utf-8, falls back to typo3.
strpos
Find the position of the first occurrence of a substring in a string. UTF-8 ONLY safe strpos(), uses iconv.
strrpos
Find the position of the last occurrence of a substring in a string. UTF-8 ONLY safe strrpos(), uses iconv.
strtolower
Multibyte safe strtolower() function, uses mbstring, falls back to typo3.
strtotitle
Makes first letter of each word capital - words must be separated by spaces.
strtoupper
Multibyte safe strtoupper() function, uses mbstring, falls back to typo3.
substr
Multibyte safe substr() function, uses iconv for utf-8, falls back to typo3.
trim_utf8_bom
Removes the BOM from unicode string. more info
utf8_to_entities
Converts all Unicode chars > 127 to numeric entities &#nnnn; or &#xnnn;
FAQ
When should I use a lang_string object?
The lang_string object is designed to be used in any situation where a string may not be needed, but needs to be generated. The admin navigation tree is a good example of where lang_string objects should be used. A more practical example would be any class that requires strings that may not be printed (after all classes get renderer by renderers and who knows what they will do ;))
When should I not use a lang_string object?
Don't use lang_strings when you are going to use a string immediately. There is no need as it will be processed immediately and there will be no advantage, and in fact perhaps a negative hit as a class has to be instantiated for a lang_string object, however get_string won't require that.
Limitation of lang_string
lang_string object cannot be used as an array offset. Doing so will result in PHP throwing an error. (You can use it as an object property!)
How to compare strings properties in two object
collatorlib_property_comparison class can be used to compare properties of two objects
Should the colon sign be hard-coded or included in a language string?
The colon sign should not be hard-coded because languages may use a different symbol, or have a space before or after the colon sign. Instead, the colon sign may be included in a language string, though please consider first if it is really necessary. A colon sign in a field label is not recommended. (MDL-12192 is for removing existing hard-coded colon signs.)
// Do NOT hard code any punctuation:
$string['fieldname'] = 'Name';
echo get_string('fieldname', 'mod_foobar') . ': ' . $somevalue;
// Slightly better with no hard coded colon:
$string['fieldname'] = 'Name: ';
echo get_string('fieldname', 'mod_foobar') . $somevalue;
// Better with no assumed word order:
$string['fieldname'] = 'Name: {$a->name}';
echo get_string('fieldname', 'mod_foobar', ['name' => $somevalue]);
Changing or creating a new lang string?
New strings were required in 1.x times when we did not have branches for translations. Since 2.0, for changes in main, structural and/or semantic modification of a string (such as adding or removing {$a} placeholders etc) is acceptable as such strings are highlighted in AMOS as outdated. Of course, if lang pack maintainers do not pay attention to it, mismatch can happen - but this is considered to be the lang pack bug.
When a new string is introduced, the old one should be deprecated or removed so that unused strings do not accumulate.
- A) Basically I see it as (for main only issues):
-
- Any change is allowed (semantic or structural). It does not have sense to keep the old string because there won't be use for it when the new Moodle version is released. So we can forget about the old one 100%. Of course if the string is radically different, then it may have sense to create a new, completely different string (and proceed with next point).
- If for any reason we stop using any string (because a feature is out or because we have decided to create a new different string instead of change existing)), then:
- if the old string is really specific (not suitable for reuse) we can safely proceed to delete it,.
- If the string belongs to a plugin, IMO we can also proceed to delete it (reuse of plugin strings should not be allowed).
- But, if the string is generic (may be reused) and it's not part of a plugin then the string must be deprecated.
- B) And, for issues involving stables, only small semantic changes are allowed. No structural, no deprecation and no deletion. Ever. If still something different must be shown it will be, always, via new string. When applied to main, these changes will also imply the standard old string deprecation. No CPY instruction will be performed between the old and the new strings (safest, easier, consistent behavior, no matter there are some cases where the instruction may be acceptable. Stop overthinking. Now!).
User names placeholders
Some strings may contain placeholders to display the user's name. Common examples include various email templates or welcome messages. Developers may be tempted to use just the user's firstname in such cases, to make the text feel informal and friendlier:
// Do NOT do this.
$string['welcome'] = 'Hello {$a}! Welcome to the course.';
But some cultures or institutions may want the full name or last name to be used, rather than the first name. To enable sites to easily customise such strings and have lastname and alternatename placeholders available, the following pattern should be used.
Let the language strings file for the given component define the default display of the name:
$string['welcome'] = 'Hello {$a->firstname}! Welcome to the course.';
Then in the file making use of the string:
$namefields = [
'fullname' => fullname($USER),
'alternativefullname' => fullname($USER, true),
];
foreach (\core_user\fields::get_name_fields() as $namefield) {
$namefields[$namefield] = $USER->{$namefield};
}
echo get_string('welcome', 'xyz_component', $namefields);
That way, the string can be locally customised and use any combination of the following placeholders as needed: firstnamephonetic, lastnamephonetic, middlename, alternatename, firstname, lastname, fullname and alternativefullname.
// Locally customised variant of the string.
$string['welcome'] = 'Welcome to the course, {$a->fullname}';
See also
- Output_functions
- Core APIs
- AMOS
- The section 'Language strings' in Coding style
- String deprecation
- Improving English language strings