Skip to content

Commit

Permalink
feat(extension): multilang support (#89)
Browse files Browse the repository at this point in the history
* feat: validate locales script

* feat: popup translation

* feat: options translation
  • Loading branch information
GabenGar authored Dec 10, 2024
1 parent 7814ac8 commit c042ac7
Show file tree
Hide file tree
Showing 23 changed files with 492 additions and 1,654 deletions.
4 changes: 4 additions & 0 deletions apps/extension/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
{
"fileMatch": ["src/manifest-chrome.json"],
"url": "./src/manifest-chrome.schema.json"
},
{
"fileMatch": ["src/_locales/*/messages.json"],
"url": "./src/_locales.schema.json"
}
]
}
4 changes: 3 additions & 1 deletion apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
"build": "webpack --config webpack.prod.js && web-ext build --no-config-discovery --config=web-ext-config.mjs",
"dev": "node scripts/dev.mjs",
"lint": "web-ext lint --output=json --pretty",
"validate": "node scripts/validate.mjs",
"open-analyzer": "opener http://127.0.0.1:8888/"
},
"imports": {
"#popup/*": "./src/popup/*/index.ts",
"#options/*": "./src/options/*/index.ts"
"#options/*": "./src/options/*/index.ts",
"#*": "./src/*/index.ts"
},
"repository": {
"type": "git",
Expand Down
73 changes: 73 additions & 0 deletions apps/extension/scripts/validate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @ts-check

import { readdir, readFile } from "node:fs/promises";
import path from "node:path";
import { cwd } from "node:process";

const localesPath = path.join(cwd(), "src", "_locales");

validate();

async function validate() {
/**
* @type {(import("node:fs").Dirent)[]}
*/
let localesDir;

try {
localesDir = await readdir(localesPath, {
encoding: "utf8",
recursive: true,
withFileTypes: true,
});
} catch (error) {
// @ts-expect-error
throw new Error(`Failed to read locales folder "${localesPath}".`, {
cause: error,
});
}

/**
* @type {Map<string, Set<string>>}
*/
const messageKeys = new Map();
const localeFiles = localesDir.filter((dirEntry) => {
return dirEntry.isFile();
});

for await (const dirEntry of localeFiles) {
const locale = dirEntry.path;

/**
* @type {string}
*/
let contents;

try {
const entryPath = path.join(dirEntry.path, dirEntry.name);
contents = await readFile(entryPath, { encoding: "utf8" });
} catch (error) {
// @ts-expect-error
throw new Error(`Failed to read locale file "${dirEntry.path}".`, {
cause: error,
});
}

/**
* @type {Record<string, never>}
*/
const messageData = JSON.parse(contents);

const messages = Object.keys(messageData);

messageKeys.set(locale, new Set(messages));
}

const counts = new Set(
[...messageKeys.values()].map((messages) => messages.size)
);

if (counts.size !== 1) {
throw new Error("Not all languages are equally supported.");
}
}
43 changes: 43 additions & 0 deletions apps/extension/src/_locales.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"$id": "locale-messages",
"title": "LocaleMessages",
"type": "object",
"additionalProperties": {
"anyOf": [
{
"type": "object",
"additionalProperties": false,
"required": ["message"],
"properties": {
"message": { "type": "string" },
"description": { "type": "string" },
"placeholders": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": ["content"],
"properties": {
"content": {
"type": "string"
},
"example": {
"type": "string"
}
}
}
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["message"],
"properties": {
"message": { "type": "string" },
"description": { "type": "string" }
}
}
]
}
}
Loading

0 comments on commit c042ac7

Please sign in to comment.