翻訳ファイルをランタイムで読み込み
This commit is contained in:
parent
ec4d5857d8
commit
84b488a912
6 changed files with 46 additions and 33 deletions
15
gulpfile.ts
15
gulpfile.ts
|
@ -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/**/*',
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
{
|
||||
"globals": {
|
||||
"_DEV_": false,
|
||||
"_LANG_": false,
|
||||
"_LANGS_": false,
|
||||
"_LOCALE_": false,
|
||||
"_VERSION_": false,
|
||||
"_ENV_": false,
|
||||
"_PERF_PREFIX_": false,
|
||||
|
|
2
src/client/@types/global.d.ts
vendored
2
src/client/@types/global.d.ts
vendored
|
@ -1,6 +1,4 @@
|
|||
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');
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/**
|
||||
* BOOT LOADER
|
||||
* サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。
|
||||
* - バージョンやユーザーの言語に基づいて適切なメインスクリプトを読み込む。
|
||||
* - 翻訳ファイルをフェッチする。
|
||||
* - バージョンに基づいて適切なメインスクリプトを読み込む。
|
||||
* - キャッシュされたコンパイル済みテーマを適用する。
|
||||
* - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。
|
||||
* テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。
|
||||
|
@ -10,27 +11,34 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔
|
||||
{
|
||||
//#region Script
|
||||
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
|
||||
(async () => {
|
||||
const v = localStorage.getItem('v') || VERSION;
|
||||
|
||||
//#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);
|
||||
//#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';
|
||||
// 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'
|
||||
}));
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue