Commit 5577fb23 authored by 神楽坂玲奈's avatar 神楽坂玲奈

i18n

parent 4fd5e106
...@@ -34,10 +34,17 @@ ...@@ -34,10 +34,17 @@
"root": "", "root": "",
"sourceRoot": "src", "sourceRoot": "src",
"prefix": "app", "prefix": "app",
"i18n": {
"sourceLocale": "zh-Hans",
"locales": {
"en-US": "src/locale/messages.en-US.xlf"
}
},
"architect": { "architect": {
"build": { "build": {
"builder": "@angular-builders/custom-webpack:browser", "builder": "@angular-builders/custom-webpack:browser",
"options": { "options": {
"localize": ["zh-Hans"],
"allowedCommonJsDependencies": [ "allowedCommonJsDependencies": [
"glob", "glob",
"aria2", "aria2",
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
"main": "main.js", "main": "main.js",
"description": "萌卡客户端", "description": "萌卡客户端",
"author": "zh99998 <zh99998@gmail.com>", "author": "zh99998 <zh99998@gmail.com>",
"dependencies": {
"@electron/remote": "^1.2.1",
"electron-browser-storage": "^1.0.7",
"electron-is-dev": "^2.0.0",
"electron-updater": "^4.3.9"
},
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "^12.1.1", "@angular-builders/custom-webpack": "^12.1.1",
"@angular/animations": "~12.2.5", "@angular/animations": "~12.2.5",
...@@ -26,41 +32,93 @@ ...@@ -26,41 +32,93 @@
"@angular/platform-browser": "~12.2.5", "@angular/platform-browser": "~12.2.5",
"@angular/platform-browser-dynamic": "~12.2.5", "@angular/platform-browser-dynamic": "~12.2.5",
"@angular/router": "~12.2.5", "@angular/router": "~12.2.5",
"@types/bootstrap": "^5.1.4",
"@types/mousetrap": "^1.6.8",
"@types/node": "^16.4.13",
"bootstrap": "^5.1.0",
"copy-webpack-plugin": "^9.0.1",
"electron": "^13.3.0",
"electron-builder": "^22.11.7",
"mousetrap": "^1.6.5",
"rxjs": "^7.3.0",
"tslib": "^2.3.0",
"typescript": "~4.3.5",
"zone.js": "~0.11.4"
},
"dependencies": {
"@electron/remote": "^1.2.1",
"@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-free": "^5.15.4",
"@types/bootstrap": "^5.1.4",
"@types/ini": "^1.3.30", "@types/ini": "^1.3.30",
"@types/jquery": "^3.5.6", "@types/jquery": "^3.5.6",
"@types/mousetrap": "^1.6.8",
"@types/mustache": "^4.1.2", "@types/mustache": "^4.1.2",
"@types/node": "^16.4.13",
"aria2": "^3.0.1", "aria2": "^3.0.1",
"bootstrap": "^5.1.0",
"candy": "https://github.com/moecube/candy/releases/download/v2.2.0/candy.tar.gz", "candy": "https://github.com/moecube/candy/releases/download/v2.2.0/candy.tar.gz",
"candy-shop": "github:candy-chat/candy-plugins", "candy-shop": "github:candy-chat/candy-plugins",
"electron-is-dev": "^2.0.0", "copy-webpack-plugin": "^9.0.1",
"electron-updater": "^4.3.9", "electron": "^14.0.0",
"electron-builder": "^22.11.7",
"electron-builder-notarize": "^1.2.0",
"exports-loader": "^3.0.0", "exports-loader": "^3.0.0",
"imports-loader": "^3.0.0", "imports-loader": "^3.0.0",
"ini": "^2.0.0", "ini": "^2.0.0",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"jquery-i18n": "github:recurser/jquery-i18n", "jquery-i18n": "github:recurser/jquery-i18n",
"mousetrap": "^1.6.5",
"mustache": "^4.2.0", "mustache": "^4.2.0",
"reconnecting-websocket": "^4.4.0", "reconnecting-websocket": "^4.4.0",
"rxjs": "^7.3.0",
"strophe.js": "^1.4.2", "strophe.js": "^1.4.2",
"strophejs-plugin-caps": "^1.1.3", "strophejs-plugin-caps": "^1.1.3",
"strophejs-plugin-disco": "^0.0.2", "strophejs-plugin-disco": "^0.0.2",
"strophejs-plugin-muc": "^1.1.0", "strophejs-plugin-muc": "^1.1.0",
"strophejs-plugin-roster": "^1.1.0" "strophejs-plugin-roster": "^1.1.0",
"tslib": "^2.3.0",
"typescript": "4.3",
"zone.js": "~0.11.4"
},
"build": {
"productName": "MyCard",
"appId": "com.mycard.mycard",
"publish": [
{
"provider": "generic",
"url": "https://cdn02.moecube.com:444/downloads"
}
],
"asar": false,
"files": [
"main.js",
"dist/mycard"
],
"extraResources": [
"bin"
],
"win": {
"verifyUpdateCodeSignature": false
},
"linux": {
"target": [
{
"target": "AppImage"
}
]
},
"appImage": {
"publish": [
{
"provider": "generic",
"url": "https://cdn02.moecube.com:444/downloads"
}
]
},
"afterSign": "electron-builder-notarize",
"mac": {
"hardenedRuntime": true,
"entitlements": "./node_modules/electron-builder-notarize/entitlements.mac.inherit.plist"
},
"dmg": {
"contents": [
{
"x": 448,
"y": 344,
"type": "link",
"path": "/Applications"
},
{
"x": 192,
"y": 344,
"type": "file"
}
]
}
} }
} }
import { ChangeDetectorRef, Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { ChangeDetectorRef, Component, ElementRef, Inject, Input, LOCALE_ID, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { AppsService } from '../apps.service'; import { AppsService } from '../apps.service';
import { InstallOption } from '../shared/install-option'; import { InstallOption } from '../shared/install-option';
import { SettingsService } from '../settings.service'; import { SettingsService } from '../settings.service';
...@@ -22,7 +22,7 @@ declare const Notification: any; ...@@ -22,7 +22,7 @@ declare const Notification: any;
@Component({ @Component({
selector: 'app-detail', selector: 'app-detail',
templateUrl: 'app-detail.component.html', templateUrl: 'app-detail.component.html',
styleUrls: ['app-detail.component.css'] styleUrls: ['app-detail.component.css'],
}) })
export class AppDetailComponent implements OnInit, OnChanges { export class AppDetailComponent implements OnInit, OnChanges {
@Input() @Input()
...@@ -44,23 +44,32 @@ export class AppDetailComponent implements OnInit, OnChanges { ...@@ -44,23 +44,32 @@ export class AppDetailComponent implements OnInit, OnChanges {
payment = 'alipay'; payment = 'alipay';
creating_order = false; creating_order = false;
constructor(public appsService: AppsService, private settingsService: SettingsService, private downloadService: DownloadService, private ref: ChangeDetectorRef, private el: ElementRef, private loginService: LoginService) { constructor(
public appsService: AppsService,
this.tags = this.settingsService.getLocale().startsWith('zh') ? { private settingsService: SettingsService,
'recommend': '推荐', private downloadService: DownloadService,
'mysterious': '迷之物体', private ref: ChangeDetectorRef,
'touhou': '东方 Project', private el: ElementRef,
'touhou_pc98': '东方旧作', private loginService: LoginService,
'language': '语言包', @Inject(LOCALE_ID) private locale: string
'ygopro': 'YGOPro' ) {
} : { this.tags = locale.startsWith('zh')
'recommend': 'Recommended', ? {
'mysterious': 'Something', recommend: '推荐',
'touhou': 'Touhou Project', mysterious: '迷之物体',
'touhou_pc98': 'Touhou old series', touhou: '东方 Project',
'language': 'Language Pack', touhou_pc98: '东方旧作',
'ygopro': 'YGOPro' language: '语言包',
}; ygopro: 'YGOPro',
}
: {
recommend: 'Recommended',
mysterious: 'Something',
touhou: 'Touhou Project',
touhou_pc98: 'Touhou old series',
language: 'Language Pack',
ygopro: 'YGOPro',
};
} }
async ngOnChanges(changes: SimpleChanges) { async ngOnChanges(changes: SimpleChanges) {
...@@ -108,8 +117,7 @@ export class AppDetailComponent implements OnInit, OnChanges { ...@@ -108,8 +117,7 @@ export class AppDetailComponent implements OnInit, OnChanges {
if (reference.isLanguage()) { if (reference.isLanguage()) {
// 对于语言包,只有在语言包的locales比游戏本身的更加合适的时候才默认勾选 // 对于语言包,只有在语言包的locales比游戏本身的更加合适的时候才默认勾选
// 这里先偷个懒,中文环境勾选中文语言包,非中文环境勾选非中文语言包 // 这里先偷个懒,中文环境勾选中文语言包,非中文环境勾选非中文语言包
this.referencesInstall[reference.id] = this.referencesInstall[reference.id] = reference.locales[0].startsWith('zh') === this.locale.startsWith('zh');
reference.locales[0].startsWith('zh') === this.settingsService.getLocale().startsWith('zh');
} else { } else {
this.referencesInstall[reference.id] = true; this.referencesInstall[reference.id] = true;
} }
...@@ -129,10 +137,8 @@ export class AppDetailComponent implements OnInit, OnChanges { ...@@ -129,10 +137,8 @@ export class AppDetailComponent implements OnInit, OnChanges {
} }
async installMod(mod: App) { async installMod(mod: App) {
let option = new InstallOption(mod, path.dirname(mod.parent!.local!.path)); let option = new InstallOption(mod, path.dirname(mod.parent!.local!.path));
await this.install(mod, option, {}); await this.install(mod, option, {});
} }
async uninstall(app: App) { async uninstall(app: App) {
...@@ -181,7 +187,7 @@ export class AppDetailComponent implements OnInit, OnChanges { ...@@ -181,7 +187,7 @@ export class AppDetailComponent implements OnInit, OnChanges {
this.availableLibraries.splice(index, 1); this.availableLibraries.splice(index, 1);
} }
} else { } else {
this.settingsService.setDefaultLibrary({ path: this.installOption.installLibrary, 'default': true }); this.settingsService.setDefaultLibrary({ path: this.installOption.installLibrary, default: true });
} }
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path; this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
} }
......
This diff is collapsed.
...@@ -25,7 +25,7 @@ window['jQuery'] = $; ...@@ -25,7 +25,7 @@ window['jQuery'] = $;
import Mustache from 'mustache'; import Mustache from 'mustache';
import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Component, ElementRef, Inject, Input, LOCALE_ID, OnChanges, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { LoginService } from '../login/login.service'; import { LoginService } from '../login/login.service';
import { SettingsService } from '../settings.service'; import { SettingsService } from '../settings.service';
import { App } from '../shared/app'; import { App } from '../shared/app';
...@@ -262,7 +262,12 @@ export class CandyComponent implements OnInit, OnChanges { ...@@ -262,7 +262,12 @@ export class CandyComponent implements OnInit, OnChanges {
// ismax_window:Boolean=false; // ismax_window:Boolean=false;
height_default_window: string = '230px'; height_default_window: string = '230px';
constructor(private loginService: LoginService, private settingsService: SettingsService, private element: ElementRef) {} constructor(
private loginService: LoginService,
private settingsService: SettingsService,
private element: ElementRef,
@Inject(LOCALE_ID) private locale: string
) {}
ngOnInit() { ngOnInit() {
this.jid = this.loginService.user.username + '@mycard.moe'; this.jid = this.loginService.user.username + '@mycard.moe';
...@@ -307,7 +312,7 @@ export class CandyComponent implements OnInit, OnChanges { ...@@ -307,7 +312,7 @@ export class CandyComponent implements OnInit, OnChanges {
}, },
view: { view: {
assets: 'candy/res/', // copy-webpack-plugin assets: 'candy/res/', // copy-webpack-plugin
language: this.settingsService.getLocale().startsWith('zh') ? 'cn' : 'en', language: this.locale.startsWith('zh') ? 'cn' : 'en',
enableXHTML: true, enableXHTML: true,
}, },
}); });
......
/** /**
* Created by zh99998 on 16/9/2. * Created by zh99998 on 16/9/2.
*/ */
import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, ElementRef, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core';
import { AppsService } from '../apps.service'; import { AppsService } from '../apps.service';
import { LoginService } from '../login/login.service'; import { LoginService } from '../login/login.service';
import { App, Category } from '../shared/app'; import { App, Category } from '../shared/app';
...@@ -16,10 +16,9 @@ const ReconnectingWebSocket = require('reconnecting-websocket'); ...@@ -16,10 +16,9 @@ const ReconnectingWebSocket = require('reconnecting-websocket');
@Component({ @Component({
selector: 'lobby', selector: 'lobby',
templateUrl: 'lobby.component.html', templateUrl: 'lobby.component.html',
styleUrls: ['lobby.component.css'] styleUrls: ['lobby.component.css'],
}) })
export class LobbyComponent implements OnInit { export class LobbyComponent implements OnInit {
currentApp: App; currentApp: App;
resizing: HTMLElement | undefined; resizing: HTMLElement | undefined;
offset: number; offset: number;
...@@ -29,9 +28,13 @@ export class LobbyComponent implements OnInit { ...@@ -29,9 +28,13 @@ export class LobbyComponent implements OnInit {
//private messages: WebSocket; //private messages: WebSocket;
constructor(private appsService: AppsService, private loginService: LoginService, constructor(
private settingsService: SettingsService, private ref: ChangeDetectorRef) { private appsService: AppsService,
} private loginService: LoginService,
private settingsService: SettingsService,
private ref: ChangeDetectorRef,
@Inject(LOCALE_ID) private locale: string
) {}
get grouped_apps(): any { get grouped_apps(): any {
// @ts-ignore // @ts-ignore
...@@ -51,7 +54,6 @@ export class LobbyComponent implements OnInit { ...@@ -51,7 +54,6 @@ export class LobbyComponent implements OnInit {
} else { } else {
tags = ['runtime']; tags = ['runtime'];
} }
} }
for (const tag of tags) { for (const tag of tags) {
if (!result[tag]) { if (!result[tag]) {
...@@ -80,7 +82,7 @@ export class LobbyComponent implements OnInit { ...@@ -80,7 +82,7 @@ export class LobbyComponent implements OnInit {
} }
} }
// 特化个 YGOPRO 国际服聊天室。其他的暂时没需求。 // 特化个 YGOPRO 国际服聊天室。其他的暂时没需求。
if (!this.settingsService.getLocale().startsWith('zh')) { if (!this.locale.startsWith('zh')) {
this.apps.get('ygopro')!.conference = 'ygopro-international'; this.apps.get('ygopro')!.conference = 'ygopro-international';
} }
this.ref.detectChanges(); this.ref.detectChanges();
...@@ -96,7 +98,6 @@ export class LobbyComponent implements OnInit { ...@@ -96,7 +98,6 @@ export class LobbyComponent implements OnInit {
this.currentApp = this.apps.get(this.currentApp.id)!; this.currentApp = this.apps.get(this.currentApp.id)!;
}; */ }; */
// $(this.search.nativeElement).typeahead(<any>{ // $(this.search.nativeElement).typeahead(<any>{
// minLength: 1, // minLength: 1,
// highlight: true // highlight: true
......
...@@ -77,9 +77,9 @@ ...@@ -77,9 +77,9 @@
<div class='form-group row'> <div class='form-group row'>
<label class='col-sm-2 col-form-label' for='locale' i18n>语言</label> <label class='col-sm-2 col-form-label' for='locale' i18n>语言</label>
<div class='col-sm-10'> <div class='col-sm-10'>
<select [(ngModel)]='locale' class='form-control' id='locale' name='locale'> <select [(ngModel)]='localeNew' class='form-control' id='locale' name='locale'>
<option value='en-US'>English</option> <option value='en-US'>English</option>
<option value='zh-CN'>简体中文</option> <option value='zh-Hans'>简体中文</option>
</select> </select>
</div> </div>
</div> </div>
......
import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, ElementRef, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core';
import { shell } from 'electron'; import { shell } from 'electron';
import * as remote from '@electron/remote'; import * as remote from '@electron/remote';
import $ from 'jquery'; import $ from 'jquery';
...@@ -32,7 +32,7 @@ export class MyCardComponent implements OnInit { ...@@ -32,7 +32,7 @@ export class MyCardComponent implements OnInit {
update_downloaded: ElementRef; update_downloaded: ElementRef;
update_elements: Map<string, ElementRef>; update_elements: Map<string, ElementRef>;
locale: string; localeNew: string = this.locale;
resizing: HTMLElement | null; resizing: HTMLElement | null;
...@@ -73,7 +73,11 @@ export class MyCardComponent implements OnInit { ...@@ -73,7 +73,11 @@ export class MyCardComponent implements OnInit {
// }); // });
} }
constructor(public loginService: LoginService, private ref: ChangeDetectorRef, private settingsService: SettingsService) { constructor(
public loginService: LoginService,
private ref: ChangeDetectorRef,
@Inject(LOCALE_ID) public locale: string
) {
// renderer.listenGlobal('window', 'message', (event) => { // renderer.listenGlobal('window', 'message', (event) => {
// console.log(event); // console.log(event);
// // Do something with 'event' // // Do something with 'event'
...@@ -98,8 +102,6 @@ export class MyCardComponent implements OnInit { ...@@ -98,8 +102,6 @@ export class MyCardComponent implements OnInit {
autoUpdater.on('update-downloaded', (event) => { autoUpdater.on('update-downloaded', (event) => {
this.set_update_status('update-downloaded'); this.set_update_status('update-downloaded');
}); });
this.locale = this.settingsService.getLocale();
} }
update_retry() { update_retry() {
...@@ -128,8 +130,8 @@ export class MyCardComponent implements OnInit { ...@@ -128,8 +130,8 @@ export class MyCardComponent implements OnInit {
} }
submit() { submit() {
if (this.locale !== this.settingsService.getLocale()) { if (this.localeNew !== this.locale) {
localStorage.setItem(SettingsService.SETTING_LOCALE, this.locale); localStorage.setItem(SettingsService.SETTING_LOCALE, this.localeNew);
remote.app.relaunch(); remote.app.relaunch();
remote.app.quit(); remote.app.quit();
} }
......
/** /**
* Created by weijian on 2016/10/24. * Created by weijian on 2016/10/24.
*/ */
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import path from 'path'; import path from 'path';
import { app } from '@electron/remote'; import {app} from '@electron/remote';
export interface Library { export interface Library {
'default': boolean; 'default': boolean;
...@@ -23,12 +23,8 @@ export class SettingsService { ...@@ -23,12 +23,8 @@ export class SettingsService {
} }
]; ];
static SETTING_LOCALE = 'locale'; static SETTING_LOCALE = 'locale';
static defaultLocale = app.getLocale();
locale: string;
libraries: Library[]; libraries: Library[];
getLibraries() { getLibraries() {
if (!this.libraries) { if (!this.libraries) {
let data = localStorage.getItem(SettingsService.SETTING_LIBRARY); let data = localStorage.getItem(SettingsService.SETTING_LIBRARY);
...@@ -51,7 +47,7 @@ export class SettingsService { ...@@ -51,7 +47,7 @@ export class SettingsService {
l.default = false; l.default = false;
}); });
} }
libraries.push({ 'default': isDefault, path: libraryPath }); libraries.push({'default': isDefault, path: libraryPath});
this.libraries = libraries; this.libraries = libraries;
localStorage.setItem(SettingsService.SETTING_LIBRARY, JSON.stringify(libraries)); localStorage.setItem(SettingsService.SETTING_LIBRARY, JSON.stringify(libraries));
} }
...@@ -76,22 +72,4 @@ export class SettingsService { ...@@ -76,22 +72,4 @@ export class SettingsService {
throw('no default library found'); throw('no default library found');
} }
} }
getLocale(): string {
if (!this.locale) {
let locale = localStorage.getItem(SettingsService.SETTING_LOCALE);
if (!locale) {
this.locale = SettingsService.defaultLocale;
localStorage.setItem(SettingsService.SETTING_LOCALE, SettingsService.defaultLocale);
} else {
this.locale = locale;
}
}
return this.locale;
}
setLocale(locale: string) {
this.locale = locale;
localStorage.setItem(SettingsService.SETTING_LOCALE, locale);
}
} }
...@@ -108,7 +108,7 @@ export class App { ...@@ -108,7 +108,7 @@ export class App {
static getQuerySuffix(platform: string, locale: string, arch: string) { static getQuerySuffix(platform: string, locale: string, arch: string) {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.set('platform', platform); params.set('platform', platform);
params.set('locale', locale); params.set('locale', locale === 'zh-Hans' ? 'zh-CN' : 'zh-Hans');
params.set('arch', arch); params.set('arch', arch);
return params.toString(); return params.toString();
} }
......
import {LOCALE_ID, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
import * as remote from '@electron/remote';
export async function getTranslationProviders (): Promise<Object[]> {
let locale = localStorage.getItem('locale');
if (!locale) {
locale = remote.app.getLocale();
localStorage.setItem('locale', locale);
}
const noProviders: Object[] = [];
if (!locale || locale === 'zh-CN') {
return noProviders;
}
const translationFile = `./locale/messages.${locale}.xlf`;
try {
let translations = await getTranslationsWithSystemJs(translationFile);
return [
{provide: TRANSLATIONS, useValue: translations},
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
{provide: LOCALE_ID, useValue: locale}
];
} catch (error) {
return noProviders;
}
}
declare const System: any;
function getTranslationsWithSystemJs (file: string) {
return System.import(file + '!text'); // relies on text plugin
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment