Skip to content
English
  • There are no suggestions because the search field is empty.

05.06 Language and Localization

SimpleRisk supports 39+ languages via Crowdin-managed translation files. Set the system default language for the install, let each user pick their preferred language, and configure date format display. Translations are pulled from Crowdin into the codebase periodically; this article covers what's supported in-product and what to do when a translation gap matters.

Why this matters

For a multi-language organization (a global program, a multinational with non-English-speaking business units, a regulated industry where the regulator's language differs from the business's working language), having the application present in the user's own language matters. Users who can read the form labels and field descriptions submit better risks; users who can read the report labels review reports more carefully. The friction of "translate the screen in my head every time" produces worse outcomes than the cost of translation suggests.

Every piece of text SimpleRisk shows you is looked up by key rather than written into the page, which is what makes the whole UI translatable. The translations live in one file per locale under simplerisk/languages/, and the English file is the canonical list of keys. Every other locale is maintained on Crowdin (https://crowdin.com), with translations contributed by the SimpleRisk community and by SimpleRisk customers.

The honest scope to know up front: language coverage varies by locale. The English source has thousands of keys; some locales have nearly complete coverage, others lag substantially. A user picking a less-translated locale sees mixed English-and-localized output where keys haven't been translated yet. (The shipped locale files carry every key — Crowdin writes the English source text into anything not yet translated — so untranslated strings display in English. There's no runtime fallback beyond that: a key missing from the file entirely renders as nothing at all. That only bites on hand-authored custom language files; see "Override specific strings with a custom language file" below.) For programs that depend on full translation fidelity, the path is to contribute to Crowdin for the missing keys; you can't substitute translations directly in the codebase without losing them on the next Crowdin pull.

The other thing worth knowing: translation updates ship with releases. Crowdin translations are pulled into the SimpleRisk repository periodically (the recurring crowdin_testing PRs in the GitHub history). Each numbered release includes the translations available at the time of the release cut. To get newly-translated keys into your install, upgrade SimpleRisk; you don't pull from Crowdin yourself.

The third thing: only UI text is localized. User-entered content (risk descriptions, mitigation plans, audit findings) is stored as the user typed it. SimpleRisk doesn't auto-translate user content. A French user submitting a risk in French and an English user reviewing the risk see the same French description in both their views. For multi-language programs, settle on a working language for user-entered content (typically English for international consistency, sometimes the regional language for regional teams).

Before you start

Have these in hand:

  • Admin access to the Settings Hub (Settings cog, top-right of any page) → Preferences tile for the system default language and date format.
  • A list of the languages your user base speaks and an awareness of which of those languages have substantial Crowdin coverage (the SimpleRisk community can confirm; or check the size of lang.{locale}.php relative to lang.en.php as a rough proxy).
  • A communication plan for users if you change the system default language. Existing users who haven't set a per-user preference will see the new default; tell them how to switch back if they want.
  • An understanding that the user-entered content language is a separate decision from the UI language. The two don't have to match (a French-speaking user can have UI in French and write risk descriptions in English), but you may want a program convention.

Step-by-step

1. Identify which languages you actually need

The full list of locales SimpleRisk ships with is in simplerisk/languages/. As of the current release, that includes (incomplete list, illustrative):

  • en — English (the source)
  • es — Spanish
  • fr — French
  • de — German
  • it — Italian
  • pt — Portuguese
  • nl — Dutch
  • ja — Japanese
  • ko — Korean
  • zh — Chinese
  • ru — Russian
  • ar — Arabic
  • … and 25+ more.

Check which of these your user base needs. There's no reason to enable everything; the per-user picker shows the locales installed in simplerisk/languages/, but most programs only need 2–5 locales actively.

2. Set the system default language

Settings cog → Settings Hub → Preferences tile → System tab. Find Default Language (default_language in your instance settings). Pick the locale code (e.g., en, fr, de).

The system default applies when:

  • A user hasn't set a per-user language preference.
  • A new user is created and their language isn't specified at creation.
  • The login page is rendered (no user is logged in yet).

For most installs, the system default matches the working language of the headquarters. International deployments often leave it at en and rely on per-user preferences for non-English speakers.

3. Let users pick their per-user language

Each user has a language field on their user record. Users set their own:

  • My Account → Profile → Language dropdown.
  • The picker shows every locale present in simplerisk/languages/.
  • Save; the change takes effect on the next page load.

For new users, an admin can set the language at user creation via Settings cog → Settings Hub → User Management tile → Add UserLanguage. For users who don't pick a preference, the system default applies.

4. Configure the date format

Date display in SimpleRisk is independent of language. Configure it once per install through the date format setting. SimpleRisk applies your chosen format consistently across server-rendered pages and the interactive parts of the UI alike.

Common choices:

  • YYYY-MM-DD — ISO 8601, unambiguous internationally; preferred for any global program.
  • MM/DD/YYYY — US convention.
  • DD/MM/YYYY — European convention.
  • DD.MM.YYYY — German / Central European.

Pick one and stick with it. Mixed date formats across the install (some screens MDY, some DMY) produce confusion in any audit or report review.

5. Test the configuration with non-default users

Verify the per-user picker works:

  1. Create a test user with the language preference set to a non-English locale.
  2. Log in as that user.
  3. Confirm UI strings (form labels, dashboard tile labels, sidebar items) appear in the chosen locale.
  4. Note any strings that appear in English — these are missing translations in that locale's lang.{locale}.php file.

If translation coverage is unacceptable for your locale, contribute to Crowdin (see step 7).

6. Plan for translation gaps

Locales with incomplete translations show a mix of localized and English UI. Common gaps:

  • Recently-added features (the keys are new; translations haven't caught up yet).
  • Specialized terminology (some technical terms are kept in English even in localized contexts).
  • Long-form content (descriptions, help text) that's harder to translate well.

For high-impact gaps that block your users, the path is:

  • Crowdin: contribute the missing translations through https://crowdin.com (the SimpleRisk Crowdin project is publicly accessible; sign up and add translations).
  • After your translations are accepted into the Crowdin source, they ship in the next SimpleRisk release.
  • For urgent in-flight needs (you can't wait for the next release), you can edit simplerisk/languages/{locale}/lang.{locale}.php directly — but this change is overwritten the next time SimpleRisk pulls from Crowdin (typically on each release). Treat the edit as a temporary patch with a planned permanent fix via Crowdin.

7. Contributing to Crowdin

The SimpleRisk Crowdin project accepts community contributions. To contribute:

  1. Create a Crowdin account.
  2. Find the SimpleRisk project (search Crowdin or use the link from SimpleRisk's translation documentation).
  3. Pick the locale you can contribute to.
  4. Translate the missing keys.
  5. Submit; SimpleRisk's release process pulls accepted translations into the codebase.

For organizations using SimpleRisk in a less-translated locale, organizing a one-time translation effort (an internal team contributing for a week) materially improves the locale for everyone using it. SimpleRisk's open-source posture invites this kind of contribution.

8. Avoid hardcoding English in customizations

Anything you add to the install yourself — custom field names, custom risk-catalog entries, custom dropdown values — is stored exactly as you typed it and shows up the same way in every locale. Only SimpleRisk's own built-in text is translated.

For programs deploying to multiple locales:

  • Pick custom-field names that are clear in your primary language; accept they won't auto-translate.
  • For custom field labels that absolutely need to be localized, manage two sets of fields (one per locale) — clunky but accurate.
  • For most programs, English custom-field names are an acceptable compromise (the field name is one element among many localized strings; the rest of the form is localized).

9. Override specific strings with a custom language file

Sometimes you don't want to translate a whole locale — you want to change a handful of strings to match your organization's vocabulary (call it "Sign out" instead of "Logout", or rename "Risk" to your program's preferred term) while leaving everything else in a standard language. SimpleRisk supports this with a custom language under the cu locale code, and you only have to list the strings you actually change.

SimpleRisk ships a template at simplerisk/languages/cu/lang.cu.sample.php. To use it:

  1. Copy the template to lang.cu.php in the same directory (simplerisk/languages/cu/). The template is shipped under a .sample name on purpose — a SimpleRisk upgrade never overwrites your live lang.cu.php.
  2. Set the base language. Edit $lang_base near the top of the file to the locale you want to fall back to ('en' by default; use any installed code such as 'de' or 'fr' — anything except cu itself). Every string you don't override comes from this base.
  3. List only your overrides. In the $lang array, add an entry for each string you want to change — for example:

```php $lang_base = 'en';

$lang = [ 'Logout' => 'Sign out', 'Risk' => 'Threat', ]; ```

Leave the "fallback boilerplate" section below the array untouched; it loads the base language and fills in every key you didn't override. 4. Register the custom language. Add it to SimpleRisk's language table: name = 'cu', full = 'Custom' (the display name shown in the picker), and the next available value id. This is the one manual database step. 5. Select it. Pick Custom from My Account → Profile → Language, or set it as a user's language at user creation.

Because the file fills every un-overridden key from the base language, you do not have to copy the full key list, and you do not have to re-sync it on each SimpleRisk upgrade — new keys added by an upgrade are served from the base language automatically. You only ever maintain your own short list of overrides.

The keys you override must match the English source keys in simplerisk/languages/en/lang.en.php (the array keys, e.g. 'Logout', not the displayed English text). A key that doesn't exist in the base language simply has no effect.

Common pitfalls

A handful of patterns recur with localization.

  • Editing lang.{locale}.php directly without contributing back to Crowdin. Your edits get overwritten on the next SimpleRisk release. Always contribute to Crowdin; treat direct edits as temporary patches.

  • Picking a locale with poor coverage and being surprised at the mixed UI. Check coverage before deploying for a user base that depends on a particular locale. A program rolling out in Hungarian when Hungarian coverage is at 40% will get user complaints.

  • Setting the date format inconsistently (one place uses YYYY-MM-DD, another uses MM/DD/YYYY). The default_date_format setting controls the system-wide display; don't override it in a way that produces inconsistency.

  • Assuming user-entered content is translated. Users entering risk descriptions in their own language produce records that other-language users see verbatim. Plan a working-language convention for user content if your program is multi-language.

  • Forgetting that the login page uses the system default language. If your system default is English and your users are mostly French, the login page is in English even though the in-app UI is French (per user preference). Match the system default to the dominant locale of unauthenticated visitors.

  • Treating language as the same as locale. A user's language setting affects UI strings; the default_date_format is independent. Some installs use English UI but European date formats; some use French UI with US date formats. Configure both deliberately.

  • Adding hardcoded English strings in custom integrations or scripts. Any UI text generated by a custom integration is in whatever language the integration produced it in. If your integration writes a comment to a risk that says "Updated by automated process," that's English regardless of the user's locale. Plan accordingly.

  • Not testing the UI in non-default locales after upgrades. A SimpleRisk upgrade may add new UI keys; locales with lagging translations may suddenly show more English. Spot-check after upgrades.

  • Confusing the language setting with regulatory documentation language. Some industries require regulatory documents in specific languages. SimpleRisk's UI language doesn't determine the language of generated PDF reports for regulators — those reports are generated from user-entered content (in whatever language the user typed) plus templates (in the locale's language). For regulator-facing reports, control the language of the user-entered content directly.

  • Removing locales from the codebase to reduce footprint. Don't. The locale files are small; removing them prevents users from picking those locales but doesn't free meaningful resources. If a locale isn't being used, leave it alone; if a future user needs it, it's already there.

  • Editing the custom language file so it stops falling back. In lang.cu.php, keep the fallback boilerplate at the bottom and don't reassign $lang after it (e.g. a second $lang = [...] below the boilerplate wipes the base fill and you're back to empty strings for un-overridden keys). List your overrides in the array at the top, above the boilerplate, exactly as the .sample shows.

Related