doc/i18n.md
Canvas LMS uses a internationalization (i18n) system that handles translations for both backend (Ruby) and frontend (JavaScript) code.
The i18n system in Canvas LMS is built on:
The system supports translations in:
Main translation files are located in several places:
config/locales/generated/en.yml: Contains all extracted strings from source codeconfig/locales/generated/en-js.json: Frontend-specific translationsconfig/locales/generated/en-js-index.json: Used to generate JS modules for runtimeconfig/locales/locales.yml: Configuration file defining available localespublic/javascripts/translations/: Contains compiled JavaScript translation bundles used at runtimeconfig/locales/*.yml: Language-specific translation files (e.g., hy.yml for Armenian)
Some packages (e.g. canvas-media, canvas-rce) are published separately on npm. These packages handle translations differently:
@instructure/translations Package
packages/translations/Individual Package Setup Example using canvas-media:
// scripts/installTranslations.js
const {getTranslationList, readTranslationFile} = require('@instructure/translations')
installTranslations.js to:
Automated Updates
commitTranslations.sh to:
import {useScope as createI18nScope} from '@canvas/i18n'
const I18n = createI18nScope('ComponentName')
// Usage
I18n.t('string to translate')
t('string to translate')
The RCE package (packages/canvas-rce) uses format-message instead of i18nliner for translations:
import formatMessage from 'format-message'
formatMessage('string to translate')
To extract translatable strings from the codebase:
bundle exec rake canvas:compile_assets i18n:extract
This command:
config/locales/generated/i18n:check: Validates translation calls in Ruby and JS codei18n:extract: Extracts strings from source code into YAMLi18n:generate: Creates runtime translation filesi18n:export: Prepares files for translatorsi18n:import: Imports new translationsi18n:generate_js: Generates JavaScript translation filesi18n:generate_lolz: Generates LOLZ pseudo-translations (useful for testing)i18n:lock: Locks specific translation keysCanvas includes a special "LOLZ" locale for testing and development:
rake i18n:generate_lolzconfig/locales/lolz.ymlLocales are configured in config/locales/locales.yml:
Use Scopes
Avoid String Concatenation
I18n.t('Welcome %{name}', { name: userName })Keep Translations Updated
i18n:extract when adding new stringsi18n:checkWhen writing tests that involve translations:
Don't Mock Unless Necessary
jest.mock('@canvas/i18n')Test User Experience
Missing Translations
i18n:extract to ensure all strings are capturedRuntime Errors
For new standalone packages (similar to Canvas RCE or Canvas Meteor), consider using i18next instead of format-message.
gems/i18n_tasks/lib/tasks/i18n.rake