Generate Globally Unique Keys as Translations

Plugin source location: <serge_root>/lib/Serge/Engine/Plugin/keys_language.pm

Plugin always attaches itself to the following callback phases:

Plugin must be attached through the configuration file to exactly one of the following phases:

and optionally, to the following phase:

This plugin allows you to generate resource files with unique MD5-hash keys as 'translations'. Keys are generated based on the initial seed string (provided in plugin settings), database namespace, relative file path, and source string key, and are stable across multiple localization cycle runs. The same auto-generated keys can be exposed in string comments (hints) on your translation server, or exported into an external database or static file from Serge database.

Unique string keys can be treated as global identifiers across multiple products, platforms or assets. Having them in localized resource files allows to easily map them to internal in-product string keys, which are not guaranteed to be globally unique.

Having an ability to globally address strings can enable some advanced string handling techniques:

  • A/B copy testing: connect to an external A/B framework to get string variants for the given unique key
  • Dynamic and in-context translation preview: in internal instrumented builds, get localizations dynamically from a translation server and allow the user to navigate to a string on a translation server by selecting a string in the client.
  • Dynamic translation delivery: use additional instrumentation in a production environment to push strings down to client applications.
  • Localization quality feedback: use additional instrumentation in a production environment to allow users report translation issues by selecting a specific string in the client application.

Example

Imagine you have the following source file:

resources/en/strings.ini
ok_btn_caption=OK cancel_btn_caption=Cancel upgrade_btn_caption=Upgrade ...

Then the auto-generated localized file for the special keys language will look like this:

resources/keys/strings.ini
ok_btn_caption=f602a38e53fb52d8cdba3b639b6e4de8 cancel_btn_caption=60bcde5cd1555ce0bae8e0c87b2f651e upgrade_btn_caption=12e954946cfc4a74632d1e6727d54bae ...

With that, you can get a global key of the string by getting its 'translation' for the keys language. Consider the following example code:

Source pseudo-code
// An instrumented translation lookup function function getTranslation(localKey, language) { // get the global string key by querying // the 'keys' language in bundled resources let globalKey = getTranslationFromResources(localKey, 'keys'); // get dynamic translation for the given global key // and target user locale from e.g. remote server return getLiveTranslation(globalKey, language); }

If you call the function above to get the translation for a local key named ok_btn_caption and target user locale de as follows: getTranslation('ok_btn_caption', 'de'), it will, in turn, load the up-to-date translation for the given locale from the remote server by the global f602a38e53fb52d8cdba3b639b6e4de8 key.

The example above is provided only to help you visualize the concept. Fetching each string independently from a translation server is not the best idea. The main point here is that your client-side code and your server-side infrastructure can consistently address all the localized strings.

Usage

example-project.serge