Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language option #585

Merged
merged 6 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions bin/postbuildClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default class Postbuild {

commonBuild() {
this.handleManifest();
this.localeFiles();
}

edgeLegacyBuild() {
Expand All @@ -33,10 +32,6 @@ export default class Postbuild {
fse.copyFileSync('./store/edge/src/contentScriptsAPIBridge.js', './dist/contentScriptsAPIBridge.js');
}

localeFiles() {
fse.copySync('./locales', './dist/locales');
}

updateManifestVersion() {
if (this.manifest.version != this.buildData.version) this.manifest.version = this.buildData.version;
}
Expand Down
23 changes: 23 additions & 0 deletions development.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ For all scripts, please see `package.json`.
- npm run prebuild
- npm run clean:build
- node bin/clean.js --build
- npm run build:translations
- node bin/buildTranslations.js
- node bin/prebuild.js --$npm_config_target
- NOTE: $npm_config_target will be blank (`--`)
- webpack --config bin/webpack.dev.js
Expand All @@ -89,6 +91,8 @@ For all scripts, please see `package.json`.
- npm run prebuild
- npm run clean:build
- node bin/clean.js --build
- npm run build:translations
- node bin/buildTranslations.js
- node bin/prebuild.js --$npm_config_target
- npm run build
- webpack --config bin/webpack.dev.js
Expand All @@ -104,6 +108,8 @@ For all scripts, please see `package.json`.
- npm run prerelease:build
- npm run clean:build
- node bin/clean.js --build
- npm run build:translations
- node bin/buildTranslations.js
- node bin/prebuild.js --release --$npm_config_target
- webpack --config bin/webpack.prod.js
- npm run build:static
Expand All @@ -120,6 +126,8 @@ For all scripts, please see `package.json`.
- npm run prerelease:build
- npm run clean:build
- node bin/clean.js --build
- npm run build:translations
- node bin/buildTranslations.js
- node bin/prebuild.js --release --$npm_config_target
- webpack --config bin/webpack.prod.js
- npm run build:static
Expand All @@ -128,3 +136,18 @@ For all scripts, please see `package.json`.
- node bin/postbuild.js
- npm run package
- npx addons-linter ./dist

## Localization

Adding support for a new language can be done by creating a new locale folder (`locales/{lang}`) with a file for each namespace. To update an existing translation, modify the existing file in the same location.

Translations will automatically be compiled at build time (part of the `prebuild` script), but can be run manually as well with `npm run build:translations`. The compiled translations are stored in `src/script/translations.js`.

To use the translations, use the `Translation` class (`src/script/translation.ts`). When creating a new instance, pass in the desired namespace(s) (you should almost always include the `'common'` namespace). Once you have the translation instance you can simply call `translation.t()` with the desired key, such as `common:app.name`.

### Namespaces

- **Background**: Tranlations for context menu entries and the update notification
- **Common**: Common translations shared across the app
- **Options**: Translations for the extension's Option page
- **Popup**: Translations for the extension's Popup page
4 changes: 2 additions & 2 deletions locales/en/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@
"censorPreserveLast": "Preserve the last letter",
"defaultSubstitution": "Default Substitution",
"defaultWordMatchMethod": "$t(options:headers.matchMethod)",
"defaultWordMatchRepeated": "$t(common:labels.matchRepeatedCharacters)",
"defaultWordMatchRepeated": "$t(options:labels.matchRepeatedCharacters)",
"defaultWordMatchSeparators": "Match separator characters",
"showContextMenu": "Show context menu",
"showCounter": "Show number of filtered words",
Expand Down Expand Up @@ -318,7 +318,7 @@
},
"tableHeaders": {
"summaryTotal": "Total",
"summaryWords": "$t(common:names.word)"
"summaryWord": "$t(common:names.word)"
},
"validations": {
"lessUsedWordsInvalid": "Enter a positive whole number."
Expand Down
3 changes: 2 additions & 1 deletion src/script/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ export default class Background {

static async contextMenuSetup() {
await this.contextMenuRemoveAll();
const translation = new this.Translation(['common', 'background']);

const requiredConfig = {
contextMenu: this.Config._defaults.contextMenu,
language: this.Config._defaults.language,
password: this.Config._defaults.password,
};
const config = await this.Config.getSyncStorage(requiredConfig) as Partial<WebConfig>;
const translation = new this.Translation(['common', 'background'], config.language);

if (config.contextMenu) {
if (!config.password) {
Expand Down
10 changes: 7 additions & 3 deletions src/script/optionPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ export default class OptionPage {
this.prefersDarkScheme = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)').matches : false;
this.setHelpVersion();
this.filter = new this.Class.Filter;
this.translation = new this.Class.Translation;
this.t = this.translation.t;
this.applyTranslation();
}

applyDarkTheme(allElements = true) {
Expand Down Expand Up @@ -952,6 +949,8 @@ export default class OptionPage {

async init(refreshTheme = false) {
await this.initializeCfg();
this.initializeTranslations();
this.applyTranslation();
logger.setLevel(this.cfg.loggingLevel);
this.applyTheme(refreshTheme);
if (!this.auth) this.auth = new this.Class.OptionAuth(this, this.cfg.password);
Expand Down Expand Up @@ -981,6 +980,11 @@ export default class OptionPage {
this.cfg = await this.Class.Config.load();
}

initializeTranslations() {
this.translation = new this.Class.Translation(['common', 'options'], this.cfg.language);
this.t = this.translation.t;
}

isStorageError(error: Error): boolean {
if (error.message) {
const chromeQuotaError = '[QUOTA_BYTES quota exceeded]';
Expand Down
5 changes: 3 additions & 2 deletions src/script/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default class Popup {
'domains',
'enabledDomainsOnly',
'filterMethod',
'language',
'loggingLevel',
'password',
'wordlistId',
Expand Down Expand Up @@ -281,10 +282,10 @@ export default class Popup {
}

async initializePopup() {
this.translation = new this.Class.Translation(['common', 'popup']);
this.applyTranslation();
await this.Class.load(this);
this.applyTheme();
this.translation = new this.Class.Translation(['common', 'popup'], this.cfg.language);
this.applyTranslation();
this.populateOptions(true);
}

Expand Down
4 changes: 3 additions & 1 deletion src/script/webConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class WebConfig extends Config {
domains: { [site: string]: DomainCfg };
enabledDomainsOnly: boolean;
enabledFramesOnly: boolean;
language: string;
password: string;
showUpdateNotification: boolean;
syncLargeKeys: boolean;
Expand All @@ -35,6 +36,7 @@ export default class WebConfig extends Config {
domains: {},
enabledDomainsOnly: false,
enabledFramesOnly: false,
language: 'en',
password: null,
showUpdateNotification: false,
syncLargeKeys: true,
Expand Down Expand Up @@ -350,7 +352,7 @@ export default class WebConfig extends Config {
localizeDefaults() {
if (!this._defaultsLoaded || !this._defaultsLoaded.length) return;

const translation = new Translation('common');
const translation = new Translation('common', this.language);

if (this._defaultsLoaded.includes('defaultSubstitution')) {
const options = { defaultValue: this.Class._defaults.defaultSubstitution };
Expand Down