Skip to content
Snippets Groups Projects
Commit 84b488a9 authored by syuilo's avatar syuilo
Browse files

翻訳ファイルをランタイムで読み込み

parent ec4d5857
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@
* Gulp tasks
*/
import * as fs from 'fs';
import * as gulp from 'gulp';
import * as ts from 'gulp-typescript';
import * as rimraf from 'rimraf';
......@@ -31,6 +32,18 @@ gulp.task('build:copy:fonts', () =>
gulp.src('./node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/client/assets/fonts/'))
);
gulp.task('build:copy:locales', cb => {
fs.mkdirSync('./built/client/assets/locales', { recursive: true });
const v = { '_version_': meta.version };
for (const [lang, locale] of Object.entries(locales)) {
fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8');
}
cb();
});
gulp.task('build:client:script', () => {
return gulp.src(['./src/server/web/boot.js'])
.pipe(replace('VERSION', JSON.stringify(meta.version)))
......@@ -47,7 +60,7 @@ gulp.task('build:client:style', () => {
.pipe(gulp.dest('./built/server/web/'));
});
gulp.task('build:copy', gulp.parallel('build:copy:views', 'build:client:script', 'build:client:style', 'build:copy:fonts', () =>
gulp.task('build:copy', gulp.parallel('build:copy:locales', 'build:copy:views', 'build:client:script', 'build:client:style', 'build:copy:fonts', () =>
gulp.src([
'./src/emojilist.json',
'./src/server/web/views/**/*',
......
{
"globals": {
"_DEV_": false,
"_LANG_": false,
"_LANGS_": false,
"_LOCALE_": false,
"_VERSION_": false,
"_ENV_": false,
"_PERF_PREFIX_": false,
......
declare const _LANG_: string;
declare const _LANGS_: string[][];
declare const _LOCALE_: Record<string, any>;
declare const _VERSION_: string;
declare const _ENV_: string;
declare const _DEV_: boolean;
......
......@@ -6,9 +6,9 @@ export const hostname = address.hostname;
export const url = address.origin;
export const apiUrl = url + '/api';
export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + '/streaming';
export const lang = _LANG_;
export const lang = localStorage.getItem('lang');
export const langs = _LANGS_;
export const locale = _LOCALE_; // TODO: code splittingするため、翻訳ファイルを分割したうえでwebpackのimport alias使って読み込むようにしたい
export const locale = JSON.parse(localStorage.getItem('locale'));
export const version = _VERSION_;
export const instanceName = siteName === 'Misskey' ? host : siteName;
export const ui = localStorage.getItem('ui');
......
/**
* BOOT LOADER
* サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。
* - バージョンやユーザーの言語に基づいて適切なメインスクリプトを読み込む。
* - 翻訳ファイルをフェッチする。
* - バージョンに基づいて適切なメインスクリプトを読み込む。
* - キャッシュされたコンパイル済みテーマを適用する。
* - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。
* テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。
......@@ -10,27 +11,34 @@
'use strict';
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔
{
//#region Script
//#region Detect language
const supportedLangs = LANGS;
let lang = localStorage.getItem('lang');
if (lang == null || !supportedLangs.includes(lang)) {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
// Fallback
if (lang == null) lang = 'en-US';
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
(async () => {
const v = localStorage.getItem('v') || VERSION;
//#region Detect language & fetch translations
if (localStorage.hasOwnProperty('locale')) {
// TODO: 非同期でlocaleの更新処理をする
} else {
const supportedLangs = LANGS;
let lang = localStorage.getItem('lang');
if (lang == null || !supportedLangs.includes(lang)) {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
// Fallback
if (lang == null) lang = 'en-US';
}
}
const res = await fetch(`/assets/locales/${lang}.${v}.json`);
const json = await res.json();
localStorage.setItem('locale', JSON.stringify(json));
}
//#endregion
const ver = localStorage.getItem('v') || VERSION;
//#region Script
const salt = localStorage.getItem('salt')
? `?salt=${localStorage.getItem('salt')}`
: '';
......@@ -38,7 +46,7 @@
const head = document.getElementsByTagName('head')[0];
const script = document.createElement('script');
script.setAttribute('src', `/assets/app.${ver}.${lang}.js${salt}`);
script.setAttribute('src', `/assets/app.${v}.js${salt}`);
script.setAttribute('async', 'true');
script.setAttribute('defer', 'true');
head.appendChild(script);
......@@ -56,7 +64,7 @@
const meta = await res.json();
if (meta.version != ver) {
if (meta.version != v) {
localStorage.setItem('v', meta.version);
alert(
'Misskeyの新しいバージョンがあります。ページを再度読み込みします。' +
......@@ -113,4 +121,4 @@
location.reload();
}
}
})();
......@@ -33,9 +33,7 @@ const postcss = {
},
};
module.exports = Object.keys(isProduction ? locales : {
'ja-JP': locales['ja-JP']
}).map(lang => ({
module.exports = {
entry: {
app: './src/client/init.ts',
sw: './src/client/sw/sw.ts'
......@@ -133,9 +131,7 @@ module.exports = Object.keys(isProduction ? locales : {
new webpack.ProgressPlugin({}),
new webpack.DefinePlugin({
_VERSION_: JSON.stringify(meta.version),
_LANG_: JSON.stringify(lang),
_LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]: [string, any]) => [k, v._lang_])),
_LOCALE_: JSON.stringify(locales[lang]),
_ENV_: JSON.stringify(process.env.NODE_ENV),
_DEV_: process.env.NODE_ENV !== 'production',
_PERF_PREFIX_: JSON.stringify('Misskey:'),
......@@ -153,7 +149,7 @@ module.exports = Object.keys(isProduction ? locales : {
],
output: {
path: __dirname + '/built/client/assets',
filename: `[name].${meta.version}.${lang}.js`,
filename: `[name].${meta.version}.js`,
publicPath: `/assets/`
},
resolve: {
......@@ -173,4 +169,4 @@ module.exports = Object.keys(isProduction ? locales : {
},
devtool: false, //'source-map',
mode: isProduction ? 'production' : 'development'
}));
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment