Skip to content

Commit

Permalink
refactor: add multilingua support
Browse files Browse the repository at this point in the history
  • Loading branch information
MaikoTan committed Aug 21, 2021
1 parent a7578e3 commit 60e4121
Show file tree
Hide file tree
Showing 17 changed files with 2,135 additions and 200 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ dist/
syntaxes/*.json
!syntaxes/tmLanguage.schema.json
!syntaxes/language-configuration.json

# i18n
package.nls.*.json
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "npm: watch",
// "preLaunchTask": "npm: watch",
},
{
"name": "Extension Tests",
Expand Down
7 changes: 3 additions & 4 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
"group": "build",
"label": "npm: watch",
"detail": "tsc --watch"
}
]
}
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ Timeline highlighting is incomplete.

Need more snippets in other files.

## Multi-language support

This extension supports multi-language.

If you want to add a new language, or contribute to the existing ones,
please visit [our project on Crowdin](https://crowdin.com/project/cactbot-highlight).

## Contributing

See: [CONTRIBUTING.md](CONTRIBUTING.md)
91 changes: 91 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const del = require("del");
const es = require("event-stream");
const gulp = require("gulp");
const filter = require("gulp-filter");
const ts = require("gulp-typescript");
const jsYaml = require("js-yaml");
const typescript = require("typescript");
const vsce = require("vsce");
const nls = require("vscode-nls-dev");

const tsProject = ts.createProject("./tsconfig.json", { typescript });

const languages = [
{ folderName: "ja-JP", id: "ja" },
{ folderName: "zh-CN", id: "zh-cn" },
{ folderName: "zh-TW", id: "zh-tw" },
];

const cleanTask = function() {
return del(["dist/**", "package.nls.*.json", "cactbot-highlight*.vsix"]);
};

const convertYaml = function() {
return gulp.src(["syntaxes/timeline.tmLanguage.yaml"])
.pipe(es.map(function(file, cb) {
if (file.isNull()) {
// pass along
return cb(null, file);
}
if (file.isStream()) {
return cb(new Error("Streaming not supported"));
}

const content = file.contents.toString("utf8");
try {
const json = jsYaml.load(content);
const result = JSON.stringify(json, null, 2);
file.contents = Buffer.from(result);
file.path = file.path.replace(/\.yaml$/, ".json");
cb(null, file);
} catch (e) {
console.log(e);
return cb(null, file);
}
}))
.pipe(gulp.dest("syntaxes/"));
};

gulp.task("port-i18n", function() {
return tsProject.src()
.pipe(tsProject()).js
.pipe(nls.createMetaDataFiles())
// Filter down to only the files we need
.pipe(filter(["**/*.nls.json", "**/*.nls.metadata.json"]))

// Consoldate them into nls.metadata.json, which the xlf is built from.
.pipe(nls.bundleMetaDataFiles("maikotan.cactbot-highlight", "."))

// filter down to just the resulting metadata files
.pipe(filter(["**/nls.metadata.header.json", "**/nls.metadata.json"]))

// Add package.nls.json, used to localized package.json
.pipe(gulp.src(["package.nls.json"]))
.pipe(nls.createXlfFiles("cactbot-highlight", "cactbot-highlight"))
.pipe(gulp.dest("../crowdin-i18n"));
});

const addI18nTask = function() {
return gulp.src(["package.nls.json"])
.pipe(nls.createAdditionalLanguageFiles(languages, "i18n"))
.pipe(gulp.dest("."));
};

const compile = () => {
return tsProject.src()
.pipe(tsProject()).js
.pipe(nls.rewriteLocalizeCalls())
.pipe(nls.createAdditionalLanguageFiles(languages, "i18n", "dist"))
.pipe(gulp.dest("./dist"));
};

const vscePackageTask = () => {
return vsce.createVSIX();
};

gulp.task("clean", cleanTask);

gulp.task("build", gulp.series(convertYaml, compile, addI18nTask));

gulp.task("package", gulp.series(convertYaml, compile, addI18nTask, vscePackageTask));
27 changes: 23 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
"license": "MIT",
"main": "./dist/extension.js",
"scripts": {
"convert": "js-yaml syntaxes/timeline.tmLanguage.yaml > syntaxes/timeline.tmLanguage.json",
"compile": "yarn run convert && tsc",
"build": "gulp build",
"lint": "eslint src --ext ts",
"watch": "tsc --watch",
"clean": "gulp clean",
"pretest": "yarn run compile && yarn run lint",
"test": "node ./out/test/runTest.js",
"package": "vsce package"
"package": "gulp package"
},
"engines": {
"vscode": "^1.49.0"
Expand Down Expand Up @@ -58,7 +58,7 @@
"ko",
null
],
"description": "Set default locale for timelines. If this property is set, a prompt would not shown."
"description": "%config.cactbot.defaultLocale.description%"
}
}
},
Expand Down Expand Up @@ -87,12 +87,15 @@
"commands": [
{
"command": "cactbot.timeline.incDecTime",
"title": "%command.cactbot.timeline.incDecTime%"
},
{
"command": "cactbot.timeline.setTime",
"title": "%command.cactbot.timeline.setTime%"
},
{
"command": "cactbot.timeline.translate",
"title": "%command.cactbot.timeline.translate%"
}
],
"menus": {
Expand All @@ -114,18 +117,27 @@
"@babel/cli": "^7.12.7",
"@types/babel__core": "^7.1.12",
"@types/glob": "^7.1.3",
"@types/gulp": "^4.0.9",
"@types/js-yaml": "^4.0.2",
"@types/mocha": "^8.0.0",
"@types/node": "^12.11.7",
"@types/vscode": "^1.49.0",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"del": "^6.0.0",
"eslint": "^7.9.0",
"event-stream": "^4.0.1",
"glob": "^7.1.6",
"gulp": "^4.0.2",
"gulp-cli": "^2.3.0",
"gulp-filter": "^7.0.0",
"gulp-typescript": "^6.0.0-alpha.1",
"js-yaml": "^3.14.0",
"mocha": "^8.1.3",
"prettier": "^2.3.2",
"ts-node": "^10.1.0",
"vsce": "^1.88.0",
"vscode-nls-dev": "^3.3.2",
"vscode-test": "^1.4.0"
},
"dependencies": {
Expand All @@ -135,5 +147,12 @@
"@babel/types": "^7.13.0",
"typescript": "^4.0.2",
"vscode-nls": "^5.0.0"
},
"prettier": {
"printWidth": 120,
"singleQuote": false,
"trailingComma": "all",
"useTabs": false,
"tabWidth": 2
}
}
6 changes: 6 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"config.cactbot.defaultLocale.description": "Set a default language for timelines translating. If you don't want to be asked which language do you want to translate to every time, you can set this property to your prefer language.",
"command.cactbot.timeline.incDecTime": "Increase/Decrease Time of Selection",
"command.cactbot.timeline.setTime": "Set Time of Selection",
"command.cactbot.timeline.translate": "Translate Current Timeline"
}
27 changes: 11 additions & 16 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@
// Import the module and reference it with the alias vscode in your code below
import { commands, workspace, ExtensionContext } from "vscode";

import {
adjustTimeByNumber,
adjustTimeToNumber,
translatedTimelineProvider,
translateTimeline,
} from "./timeline";
import { incDecTime, setTime, translatedTimelineProvider, translateTimeline } from "./timeline";

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: ExtensionContext): void {
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
context.subscriptions.push(commands.registerCommand("cactbot.timeline.incDecTime", () => incDecTime()));
context.subscriptions.push(commands.registerCommand("cactbot.timeline.setTime", () => setTime()));

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
context.subscriptions.push(commands.registerCommand("cactbot.timeline.incDecTime", () => adjustTimeByNumber()));
context.subscriptions.push(commands.registerCommand("cactbot.timeline.setTime", () => adjustTimeToNumber()));

// register translate timeline
context.subscriptions.push(workspace.registerTextDocumentContentProvider("cactbot-timeline", translatedTimelineProvider));
context.subscriptions.push(commands.registerCommand("cactbot.timeline.translate", () => translateTimeline()));

// register translate timeline
context.subscriptions.push(
workspace.registerTextDocumentContentProvider("cactbot-timeline", translatedTimelineProvider),
);
context.subscriptions.push(commands.registerCommand("cactbot.timeline.translate", () => translateTimeline()));
}

// this method is called when your extension is deactivated
Expand Down
2 changes: 1 addition & 1 deletion src/models/common_replacement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const commonReplacement: CommonReplacement = {
cn: "--东--",
ko: "--동쪽--",
},
"Enrage": {
Enrage: {
de: "Finalangriff",
fr: "Enrage",
ja: "時間切れ",
Expand Down
6 changes: 5 additions & 1 deletion src/models/trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export interface OutputStrings {

type TriggerFunction<T> = (data: unknown, matches?: RegExpMatchArray) => T;

type TriggerFunctionWithOutput<T> = (data: unknown, matches?: RegExpMatchArray, output?: { [x: string]: () => Locale }) => T;
type TriggerFunctionWithOutput<T> = (
data: unknown,
matches?: RegExpMatchArray,
output?: { [x: string]: () => Locale },
) => T;

export interface Replacement {
[s: string]: string;
Expand Down
26 changes: 13 additions & 13 deletions src/test/runTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import * as path from "path";
import { runTests } from "vscode-test";

async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, "../../");
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, "../../");

// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, "./suite/index");
// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, "./suite/index");

// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error("Failed to run tests");
process.exit(1);
}
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.error("Failed to run tests");
process.exit(1);
}
}

main();
10 changes: 5 additions & 5 deletions src/test/suite/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import * as vscode from "vscode";
// import * as myExtension from '../../extension';

suite("Extension Test Suite", () => {
vscode.window.showInformationMessage("Start all tests.");
vscode.window.showInformationMessage("Start all tests.");

test("Sample test", () => {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
test("Sample test", () => {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});
Loading

0 comments on commit 60e4121

Please sign in to comment.