When I was first trying to localize my extension I couldn’t find any localized extensions to mimic, so it took a little trial and error to figure out how to connect the pieces (mostly json was being finicky). I thought I’d post a link to my extension under this subject in case it helps anyone else who is just starting out:
Translate In Place | Nova Extensions
In addition to being a localization example, I used Translate in Place to localize Translate in Place so if you’re thinking about localizing your extension then it can help with that initial translation (until someone fluent in the language can hopefully submit any corrections).
A couple of things I’m finding useful:
1.) Instead of using the English version of the text as the key:
nova.localize(“The quick brown fox jumped”);
I use a descriptive index string instead:
nova.localize(“_sample_text”);
and include a translation file for English as well (en.lproj/strings.json
). The extension code contains no user-facing strings, only localization keys.
I find this is:
- much easier to read in the code,
- you only ever have to change each language in one place (not change the English version in every translation file as well), and
- less likely to mis-match the keys.
Note that if someone is using a language you haven’t created a localization for, Nova will default to English (it won’t just show them the localization index key). (*Edit:* See thread below – only if English is in the user’s list of alternate languages)
2.) I start all my localization keys with _ to make it easier to see this is an index key, not the expected output text (makes them easier to spot in the interface when the translation isn’t mapped correctly). AND it helps avoid conflicts / accidental-translations with point 3.
3.) Translate in Place has a handy localization function _l()
that takes a variable number of parameters in addition to the initial key so that it’s easy to build compound localized strings.
e.g., If we have these strings defined:
"_err.general": “This is a general error of type ‘%@1’ because you entered ‘%@2’ into the dialog.”
"_err_type.syntax": “Syntax Error”
and one makes the call:
_l(‘_err.general’, ‘_err_type.syntax’, user_entered_text );
the resulting string would be:
“This is a general error of type ‘Syntax Error’ because you entered ‘foobar’ into the dialog.”
Please steal the function if it would be useful to you.
This extension also makes use of the enum-resolve callback to build the language menus since the alphabetical order for languages changes for each language (e.g., English, Anglais, Ingles), so if you’re wondering what using an enum-resolve callback looks like, you can check it out as an example for that as well.
Hope it helps!