Merge branch 'master' into l10n_master
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -10,3 +10,4 @@ npm-debug.log | |||||||
| run.bat | run.bat | ||||||
| api-docs.json | api-docs.json | ||||||
| package-lock.json | package-lock.json | ||||||
|  | yarn.lock | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ ultimately sophisticated new type of mini-blog based SNS. | |||||||
| * Real time contents | * Real time contents | ||||||
| * ActivityPub compatible | * ActivityPub compatible | ||||||
|  |  | ||||||
| and more! You can touch with your own eyes at https://misskey.xyz/. | and more! You can touch with your own eyes at [misskey.xyz](https://misskey.xyz). | ||||||
|  |  | ||||||
| :package: Create your instance | :package: Create your instance | ||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| @@ -36,7 +36,9 @@ please see [Setup and installation guide](./docs/setup.en.md). | |||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| **[PR](https://github.com/syuilo/misskey/pulls)s welcome!** | **[PR](https://github.com/syuilo/misskey/pulls)s welcome!** | ||||||
|  |  | ||||||
| If you want to translate Misskey, please see [Translation guide](./docs/translate.en.md). | If you want to... | ||||||
|  | * i18n ... please see [Translation guide](./docs/translate.en.md). | ||||||
|  | * l10n ... please visit https://crowdin.com/project/misskey | ||||||
|  |  | ||||||
| :heart: Backers & Sponsors | :heart: Backers & Sponsors | ||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								crowdin.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								crowdin.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | files: | ||||||
|  |   - source: /locales/ja.yml | ||||||
|  |     translation: /locales/%two_letters_code%.yml | ||||||
| @@ -19,7 +19,7 @@ common: | |||||||
|     wednesday: "W" |     wednesday: "W" | ||||||
|     thursday: "T" |     thursday: "T" | ||||||
|     friday: "F" |     friday: "F" | ||||||
|     saturday: "土" |     saturday: "S" | ||||||
|   reactions: |   reactions: | ||||||
|     like: "Like" |     like: "Like" | ||||||
|     love: "Love" |     love: "Love" | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ common: | |||||||
|     wednesday: "M" |     wednesday: "M" | ||||||
|     thursday: "J" |     thursday: "J" | ||||||
|     friday: "V" |     friday: "V" | ||||||
|     saturday: "土" |     saturday: "S" | ||||||
|   reactions: |   reactions: | ||||||
|     like: "Aime" |     like: "Aime" | ||||||
|     love: "Adore" |     love: "Adore" | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ const langs = { | |||||||
| 	'en': loadLang('en'), | 	'en': loadLang('en'), | ||||||
| 	'fr': loadLang('fr'), | 	'fr': loadLang('fr'), | ||||||
| 	'ja': native, | 	'ja': native, | ||||||
|  'pl': loadLang('pl') | 	'pl': loadLang('pl') | ||||||
| }; | }; | ||||||
|  |  | ||||||
| Object.entries(langs).map(([, locale]) => { | Object.entries(langs).map(([, locale]) => { | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ common: | |||||||
|     wednesday: "水" |     wednesday: "水" | ||||||
|     thursday: "木" |     thursday: "木" | ||||||
|     friday: "金" |     friday: "金" | ||||||
|     satruday: "土" |     saturday: "土" | ||||||
|  |  | ||||||
|   reactions: |   reactions: | ||||||
|     like: "いいね" |     like: "いいね" | ||||||
| @@ -366,6 +366,12 @@ desktop/views/components/settings.profile.vue: | |||||||
|   birthday: "誕生日" |   birthday: "誕生日" | ||||||
|   save: "保存" |   save: "保存" | ||||||
|  |  | ||||||
|  | desktop/views/components/timeline.vue: | ||||||
|  |   home: "ホーム" | ||||||
|  |   local: "ローカル" | ||||||
|  |   global: "グローバル" | ||||||
|  |   list: "リスト" | ||||||
|  |  | ||||||
| desktop/views/components/ui.header.account.vue: | desktop/views/components/ui.header.account.vue: | ||||||
|   profile: "プロフィール" |   profile: "プロフィール" | ||||||
|   drive: "ドライブ" |   drive: "ドライブ" | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ common: | |||||||
|     wednesday: "Ś" |     wednesday: "Ś" | ||||||
|     thursday: "C" |     thursday: "C" | ||||||
|     friday: "P" |     friday: "P" | ||||||
|     saturday: "土" |     saturday: "S" | ||||||
|   reactions: |   reactions: | ||||||
|     like: "Lubię" |     like: "Lubię" | ||||||
|     love: "Kocham" |     love: "Kocham" | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import locale from '../../locales'; | |||||||
| export default class Replacer { | export default class Replacer { | ||||||
| 	private lang: string; | 	private lang: string; | ||||||
|  |  | ||||||
| 	public pattern = /%i18n:([a-z0-9_\-@\.\!]+?)%/g; | 	public pattern = /%i18n:([a-z0-9_\-\.\/\|\!]+?)%/g; | ||||||
|  |  | ||||||
| 	constructor(lang: string) { | 	constructor(lang: string) { | ||||||
| 		this.lang = lang; | 		this.lang = lang; | ||||||
| @@ -53,23 +53,20 @@ export default class Replacer { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public replacement(ctx, match, key) { | 	public replacement(match, key) { | ||||||
| 		const client = '/src/client/app/'; | 		let path = null; | ||||||
| 		let name = null; |  | ||||||
|  |  | ||||||
| 		const shouldEscape = key[0] == '!'; | 		const shouldEscape = key[0] == '!'; | ||||||
| 		if (shouldEscape) { | 		if (shouldEscape) { | ||||||
| 			key = key.substr(1); | 			key = key.substr(1); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (key[0] == '@') { | 		if (key.indexOf('|') != -1) { | ||||||
| 			name = ctx.src.substr(ctx.src.indexOf(client) + client.length); | 			path = key.split('|')[0]; | ||||||
| 			key = key.substr(1); | 			key = key.split('|')[1]; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (ctx && ctx.lang) this.lang = ctx.lang; | 		const txt = this.get(path, key); | ||||||
|  |  | ||||||
| 		const txt = this.get(name, key); |  | ||||||
|  |  | ||||||
| 		return shouldEscape | 		return shouldEscape | ||||||
| 			? txt.replace(/'/g, '\\x27').replace(/"/g, '\\x22') | 			? txt.replace(/'/g, '\\x27').replace(/"/g, '\\x22') | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ export default Vue.extend({ | |||||||
| 				'%i18n:!common.weekday-short.wednesday%', | 				'%i18n:!common.weekday-short.wednesday%', | ||||||
| 				'%i18n:!common.weekday-short.thursday%', | 				'%i18n:!common.weekday-short.thursday%', | ||||||
| 				'%i18n:!common.weekday-short.friday%', | 				'%i18n:!common.weekday-short.friday%', | ||||||
| 				'%i18n:!common.weekday-short.satruday%' | 				'%i18n:!common.weekday-short.saturday%' | ||||||
| 			] | 			] | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
| @@ -1,11 +1,11 @@ | |||||||
| <template> | <template> | ||||||
| <div class="mk-timeline"> | <div class="mk-timeline"> | ||||||
| 	<header> | 	<header> | ||||||
| 		<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% ホーム</span> | 		<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> | ||||||
| 		<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% ローカル</span> | 		<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> | ||||||
| 		<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% グローバル</span> | 		<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> | ||||||
| 		<span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span> | 		<span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span> | ||||||
| 		<button @click="chooseList" title="リスト">%fa:list%</button> | 		<button @click="chooseList" title="%i18n:@list%">%fa:list%</button> | ||||||
| 	</header> | 	</header> | ||||||
| 	<x-core v-if="src == 'home'" ref="tl" key="home" src="home"/> | 	<x-core v-if="src == 'home'" ref="tl" key="home" src="home"/> | ||||||
| 	<x-core v-if="src == 'local'" ref="tl" key="local" src="local"/> | 	<x-core v-if="src == 'local'" ref="tl" key="local" src="local"/> | ||||||
|   | |||||||
| @@ -87,6 +87,7 @@ export interface ILocalUser extends IUserBase { | |||||||
|  |  | ||||||
| export interface IRemoteUser extends IUserBase { | export interface IRemoteUser extends IUserBase { | ||||||
| 	inbox: string; | 	inbox: string; | ||||||
|  | 	endpoints: string[]; | ||||||
| 	uri: string; | 	uri: string; | ||||||
| 	url?: string; | 	url?: string; | ||||||
| 	publicKey: { | 	publicKey: { | ||||||
| @@ -114,7 +115,7 @@ export function validatePassword(password: string): boolean { | |||||||
| } | } | ||||||
|  |  | ||||||
| export function isValidName(name?: string): boolean { | export function isValidName(name?: string): boolean { | ||||||
| 	return name === null || (typeof name == 'string' && name.length < 30 && name.trim() != ''); | 	return name === null || (typeof name == 'string' && name.length < 50 && name.trim() != ''); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function isValidDescription(description: string): boolean { | export function isValidDescription(description: string): boolean { | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ export default async (job: kue.Job, done): Promise<void> => { | |||||||
| 			done(); | 			done(); | ||||||
| 		} else { | 		} else { | ||||||
| 			console.warn(`deliver failed: ${res.statusMessage}`); | 			console.warn(`deliver failed: ${res.statusMessage}`); | ||||||
| 			done(res); | 			done(res.statusMessage); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -49,6 +49,7 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs | |||||||
| 		object == null || | 		object == null || | ||||||
| 		object.type !== 'Person' || | 		object.type !== 'Person' || | ||||||
| 		typeof object.preferredUsername !== 'string' || | 		typeof object.preferredUsername !== 'string' || | ||||||
|  | 		typeof object.inbox !== 'string' || | ||||||
| 		!validateUsername(object.preferredUsername) || | 		!validateUsername(object.preferredUsername) || | ||||||
| 		!isValidName(object.name == '' ? null : object.name) | 		!isValidName(object.name == '' ? null : object.name) | ||||||
| 	) { | 	) { | ||||||
| @@ -100,6 +101,7 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs | |||||||
| 				publicKeyPem: person.publicKey.publicKeyPem | 				publicKeyPem: person.publicKey.publicKeyPem | ||||||
| 			}, | 			}, | ||||||
| 			inbox: person.inbox, | 			inbox: person.inbox, | ||||||
|  | 			endpoints: person.endpoints, | ||||||
| 			uri: person.id, | 			uri: person.id, | ||||||
| 			url: person.url | 			url: person.url | ||||||
| 		}) as IRemoteUser; | 		}) as IRemoteUser; | ||||||
| @@ -207,7 +209,8 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver) | |||||||
| 			followingCount, | 			followingCount, | ||||||
| 			notesCount, | 			notesCount, | ||||||
| 			name: person.name, | 			name: person.name, | ||||||
| 			url: person.url | 			url: person.url, | ||||||
|  | 			endpoints: person.endpoints | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ export interface IPerson extends IObject { | |||||||
| 	followers: any; | 	followers: any; | ||||||
| 	following: any; | 	following: any; | ||||||
| 	outbox: any; | 	outbox: any; | ||||||
|  | 	endpoints: string[]; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const isCollection = (object: IObject): object is ICollection => | export const isCollection = (object: IObject): object is ICollection => | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import { lib as emojilib } from 'emojilib'; | import { lib as emojilib } from 'emojilib'; | ||||||
| import { JSDOM } from 'jsdom'; | import { JSDOM } from 'jsdom'; | ||||||
|  | import config from '../config'; | ||||||
|  |  | ||||||
| const handlers = { | const handlers = { | ||||||
| 	bold({ document }, { bold }) { | 	bold({ document }, { bold }) { | ||||||
| @@ -43,7 +44,7 @@ const handlers = { | |||||||
|  |  | ||||||
| 	mention({ document }, { content }) { | 	mention({ document }, { content }) { | ||||||
| 		const a = document.createElement('a'); | 		const a = document.createElement('a'); | ||||||
| 		a.href = '/' + content; | 		a.href = `${config.url}/${content}`; | ||||||
| 		a.textContent = content; | 		a.textContent = content; | ||||||
| 		document.body.appendChild(a); | 		document.body.appendChild(a); | ||||||
| 	}, | 	}, | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ const WebpackOnBuildPlugin = require('on-build-webpack'); | |||||||
| const ProgressBarPlugin = require('progress-bar-webpack-plugin'); | const ProgressBarPlugin = require('progress-bar-webpack-plugin'); | ||||||
|  |  | ||||||
| import I18nReplacer from './src/build/i18n'; | import I18nReplacer from './src/build/i18n'; | ||||||
|  | import { pattern as i18nPattern, replacement as i18nReplacement } from './webpack/i18n'; | ||||||
| import { pattern as faPattern, replacement as faReplacement } from './src/build/fa'; | import { pattern as faPattern, replacement as faReplacement } from './src/build/fa'; | ||||||
| const constants = require('./src/const.json'); | const constants = require('./src/const.json'); | ||||||
| import config from './src/config'; | import config from './src/config'; | ||||||
| @@ -37,183 +38,154 @@ global['collapseSpacesReplacement'] = html => { | |||||||
| global['base64replacement'] = (_, key) => { | global['base64replacement'] = (_, key) => { | ||||||
| 	return fs.readFileSync(__dirname + '/src/client/' + key, 'base64'); | 	return fs.readFileSync(__dirname + '/src/client/' + key, 'base64'); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | global['i18nReplacement'] = i18nReplacement; | ||||||
|  |  | ||||||
| //#endregion | //#endregion | ||||||
|  |  | ||||||
| const langs = Object.keys(locales); | const langs = Object.keys(locales); | ||||||
|  |  | ||||||
| // 無圧縮スクリプトを用意するのは重いので一時的に無効化 | const isProduction = process.env.NODE_ENV == 'production'; | ||||||
| //const entries = process.env.NODE_ENV == 'production' |  | ||||||
| //	? langs.map(l => [l, false]).concat(langs.map(l => [l, true])) |  | ||||||
| //	: langs.map(l => [l, false]); |  | ||||||
| const entries = process.env.NODE_ENV == 'production' |  | ||||||
| 	? langs.map(l => [l, true]) |  | ||||||
| 	: langs.map(l => [l, false]); |  | ||||||
|  |  | ||||||
| module.exports = entries.map(x => { | // Entries | ||||||
| 	const [lang, isProduction] = x; | const entry = { | ||||||
|  | 	desktop: './src/client/app/desktop/script.ts', | ||||||
|  | 	mobile: './src/client/app/mobile/script.ts', | ||||||
|  | 	//stats: './src/client/app/stats/script.ts', | ||||||
|  | 	//status: './src/client/app/status/script.ts', | ||||||
|  | 	dev: './src/client/app/dev/script.ts', | ||||||
|  | 	auth: './src/client/app/auth/script.ts', | ||||||
|  | 	sw: './src/client/app/sw.js' | ||||||
|  | }; | ||||||
|  |  | ||||||
| 	// Chunk name | const output = { | ||||||
| 	const name = lang; | 	path: __dirname + '/built/client/assets', | ||||||
|  | 	filename: `[name].${version}.-.${isProduction ? 'min' : 'raw'}.js` | ||||||
|  | }; | ||||||
|  |  | ||||||
| 	// Entries | //#region Define consts | ||||||
| 	const entry = { | const consts = { | ||||||
| 		desktop: './src/client/app/desktop/script.ts', | 	_RECAPTCHA_SITEKEY_: config.recaptcha.site_key, | ||||||
| 		mobile: './src/client/app/mobile/script.ts', | 	_SW_PUBLICKEY_: config.sw ? config.sw.public_key : null, | ||||||
| 		//ch: './src/client/app/ch/script.ts', | 	_THEME_COLOR_: constants.themeColor, | ||||||
| 		//stats: './src/client/app/stats/script.ts', | 	_COPYRIGHT_: constants.copyright, | ||||||
| 		//status: './src/client/app/status/script.ts', | 	_VERSION_: version, | ||||||
| 		dev: './src/client/app/dev/script.ts', | 	_CODENAME_: codename, | ||||||
| 		auth: './src/client/app/auth/script.ts', | 	_STATUS_URL_: config.status_url, | ||||||
| 		sw: './src/client/app/sw.js' | 	_STATS_URL_: config.stats_url, | ||||||
| 	}; | 	_DOCS_URL_: config.docs_url, | ||||||
|  | 	_API_URL_: config.api_url, | ||||||
|  | 	_WS_URL_: config.ws_url, | ||||||
|  | 	_DEV_URL_: config.dev_url, | ||||||
|  | 	_LANG_: '%lang%', | ||||||
|  | 	_HOST_: config.host, | ||||||
|  | 	_HOSTNAME_: config.hostname, | ||||||
|  | 	_URL_: config.url, | ||||||
|  | 	_LICENSE_: licenseHtml, | ||||||
|  | 	_GOOGLE_MAPS_API_KEY_: config.google_maps_api_key | ||||||
|  | }; | ||||||
|  |  | ||||||
| 	const output = { | const _consts = {}; | ||||||
| 		path: __dirname + '/built/client/assets', |  | ||||||
| 		filename: `[name].${version}.${lang}.${isProduction ? 'min' : 'raw'}.js` |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	const i18nReplacer = new I18nReplacer(lang as string); | Object.keys(consts).forEach(key => { | ||||||
| 	global['i18nReplacement'] = i18nReplacer.replacement; | 	_consts[key] = JSON.stringify(consts[key]); | ||||||
|  | }); | ||||||
|  | //#endregion | ||||||
|  |  | ||||||
| 	//#region Define consts | const plugins = [ | ||||||
| 	const consts = { | 	//new HardSourceWebpackPlugin(), | ||||||
| 		_RECAPTCHA_SITEKEY_: config.recaptcha.site_key, | 	new ProgressBarPlugin({ | ||||||
| 		_SW_PUBLICKEY_: config.sw ? config.sw.public_key : null, | 		format: chalk`  {cyan.bold yes we can} {bold [}:bar{bold ]} {green.bold :percent} {gray (:current/:total)} :elapseds`, | ||||||
| 		_THEME_COLOR_: constants.themeColor, | 		clear: false | ||||||
| 		_COPYRIGHT_: constants.copyright, | 	}), | ||||||
| 		_VERSION_: version, | 	new webpack.DefinePlugin(_consts), | ||||||
| 		_CODENAME_: codename, | 	new webpack.DefinePlugin({ | ||||||
| 		_STATUS_URL_: config.status_url, | 		'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development') | ||||||
| 		_STATS_URL_: config.stats_url, | 	}), | ||||||
| 		_DOCS_URL_: config.docs_url, | 	new WebpackOnBuildPlugin(stats => { | ||||||
| 		_API_URL_: config.api_url, | 		fs.writeFileSync('./built/client/meta.json', JSON.stringify({ | ||||||
| 		_WS_URL_: config.ws_url, | 			version | ||||||
| 		_DEV_URL_: config.dev_url, | 		}), 'utf-8'); | ||||||
| 		_LANG_: lang, |  | ||||||
| 		_HOST_: config.host, |  | ||||||
| 		_HOSTNAME_: config.hostname, |  | ||||||
| 		_URL_: config.url, |  | ||||||
| 		_LICENSE_: licenseHtml, |  | ||||||
| 		_GOOGLE_MAPS_API_KEY_: config.google_maps_api_key |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	const _consts = {}; | 		//#region i18n | ||||||
|  | 		langs.forEach(lang => { | ||||||
|  | 			Object.keys(entry).forEach(file => { | ||||||
|  | 				let src = fs.readFileSync(`${__dirname}/built/client/assets/${file}.${version}.-.${isProduction ? 'min' : 'raw'}.js`, 'utf8'); | ||||||
|  |  | ||||||
| 	Object.keys(consts).forEach(key => { | 				const i18nReplacer = new I18nReplacer(lang); | ||||||
| 		_consts[key] = JSON.stringify(consts[key]); |  | ||||||
| 	}); |  | ||||||
| 	//#endregion |  | ||||||
|  |  | ||||||
| 	const plugins = [ | 				src = src.replace(i18nReplacer.pattern, i18nReplacer.replacement); | ||||||
| 		//new HardSourceWebpackPlugin(), | 				src = src.replace('%lang%', lang); | ||||||
| 		new ProgressBarPlugin({ |  | ||||||
| 			format: chalk`  {cyan.bold yes we can} {bold [}:bar{bold ]} {green.bold :percent} {gray (:current/:total)} :elapseds`, |  | ||||||
| 			clear: false |  | ||||||
| 		}), |  | ||||||
| 		new webpack.DefinePlugin(_consts), |  | ||||||
| 		new webpack.DefinePlugin({ |  | ||||||
| 			'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development') |  | ||||||
| 		}), |  | ||||||
| 		new WebpackOnBuildPlugin(stats => { |  | ||||||
| 			fs.writeFileSync('./built/client/meta.json', JSON.stringify({ |  | ||||||
| 				version |  | ||||||
| 			}), 'utf-8'); |  | ||||||
| 		}), |  | ||||||
| 		new VueLoaderPlugin() |  | ||||||
| 	]; |  | ||||||
|  |  | ||||||
| 	if (isProduction) { | 				fs.writeFileSync(`${__dirname}/built/client/assets/${file}.${version}.${lang}.${isProduction ? 'min' : 'raw'}.js`, src, 'utf8'); | ||||||
| 		plugins.push(new webpack.optimize.ModuleConcatenationPlugin()); | 			}); | ||||||
| 	} | 		}); | ||||||
|  | 		//#endregion | ||||||
|  | 	}), | ||||||
|  | 	new VueLoaderPlugin() | ||||||
|  | ]; | ||||||
|  |  | ||||||
| 	return { | if (isProduction) { | ||||||
| 		name, | 	plugins.push(new webpack.optimize.ModuleConcatenationPlugin()); | ||||||
| 		entry, | } | ||||||
| 		module: { |  | ||||||
| 			rules: [{ | module.exports = { | ||||||
| 				test: /\.vue$/, | 	entry, | ||||||
| 				exclude: /node_modules/, | 	module: { | ||||||
| 				use: [{ | 		rules: [{ | ||||||
| 					loader: 'vue-loader', | 			test: /\.vue$/, | ||||||
| 					options: { | 			exclude: /node_modules/, | ||||||
| 						cssSourceMap: false, | 			use: [{ | ||||||
| 						compilerOptions: { | 				loader: 'vue-loader', | ||||||
| 							preserveWhitespace: false | 				options: { | ||||||
| 						} | 					cssSourceMap: false, | ||||||
|  | 					compilerOptions: { | ||||||
|  | 						preserveWhitespace: false | ||||||
| 					} | 					} | ||||||
| 				}, { | 				} | ||||||
| 					loader: 'replace', |  | ||||||
| 					query: { |  | ||||||
| 						search: /%base64:(.+?)%/g.toString(), |  | ||||||
| 						replace: 'base64replacement' |  | ||||||
| 					} |  | ||||||
| 				}, { |  | ||||||
| 					loader: 'replace', |  | ||||||
| 					query: { |  | ||||||
| 						search: i18nReplacer.pattern.toString(), |  | ||||||
| 						replace: 'i18nReplacement', |  | ||||||
| 						i18n: true, |  | ||||||
| 						lang |  | ||||||
| 					} |  | ||||||
| 				}, { |  | ||||||
| 					loader: 'replace', |  | ||||||
| 					query: { |  | ||||||
| 						search: faPattern.toString(), |  | ||||||
| 						replace: 'faReplacement' |  | ||||||
| 					} |  | ||||||
| 				}, { |  | ||||||
| 					loader: 'replace', |  | ||||||
| 					query: { |  | ||||||
| 						search: /^<template>([\s\S]+?)\r?\n<\/template>/.toString(), |  | ||||||
| 						replace: 'collapseSpacesReplacement' |  | ||||||
| 					} |  | ||||||
| 				}] |  | ||||||
| 			}, { | 			}, { | ||||||
| 				test: /\.styl(us)?$/, | 				loader: 'replace', | ||||||
| 				exclude: /node_modules/, | 				query: { | ||||||
| 				oneOf: [{ | 					search: /%base64:(.+?)%/g.toString(), | ||||||
| 					resourceQuery: /module/, | 					replace: 'base64replacement' | ||||||
| 					use: [{ | 				} | ||||||
| 						loader: 'vue-style-loader' |  | ||||||
| 					}, { |  | ||||||
| 						loader: 'css-loader', |  | ||||||
| 						options: { |  | ||||||
| 							modules: true, |  | ||||||
| 							minimize: true |  | ||||||
| 						} |  | ||||||
| 					}, { |  | ||||||
| 						loader: 'stylus-loader' |  | ||||||
| 					}] |  | ||||||
| 				}, { |  | ||||||
| 					use: [{ |  | ||||||
| 						loader: 'vue-style-loader' |  | ||||||
| 					}, { |  | ||||||
| 						loader: 'css-loader', |  | ||||||
| 						options: { |  | ||||||
| 							minimize: true |  | ||||||
| 						} |  | ||||||
| 					}, { |  | ||||||
| 						loader: 'stylus-loader' |  | ||||||
| 					}] |  | ||||||
| 				}] |  | ||||||
| 			}, { | 			}, { | ||||||
| 				test: /\.scss$/, | 				loader: 'replace', | ||||||
| 				exclude: /node_modules/, | 				query: { | ||||||
|  | 					search: i18nPattern.toString(), | ||||||
|  | 					replace: 'i18nReplacement', | ||||||
|  | 					i18n: true | ||||||
|  | 				} | ||||||
|  | 			}, { | ||||||
|  | 				loader: 'replace', | ||||||
|  | 				query: { | ||||||
|  | 					search: faPattern.toString(), | ||||||
|  | 					replace: 'faReplacement' | ||||||
|  | 				} | ||||||
|  | 			}, { | ||||||
|  | 				loader: 'replace', | ||||||
|  | 				query: { | ||||||
|  | 					search: /^<template>([\s\S]+?)\r?\n<\/template>/.toString(), | ||||||
|  | 					replace: 'collapseSpacesReplacement' | ||||||
|  | 				} | ||||||
|  | 			}] | ||||||
|  | 		}, { | ||||||
|  | 			test: /\.styl(us)?$/, | ||||||
|  | 			exclude: /node_modules/, | ||||||
|  | 			oneOf: [{ | ||||||
|  | 				resourceQuery: /module/, | ||||||
| 				use: [{ | 				use: [{ | ||||||
| 					loader: 'style-loader' | 					loader: 'vue-style-loader' | ||||||
| 				}, { | 				}, { | ||||||
| 					loader: 'css-loader', | 					loader: 'css-loader', | ||||||
| 					options: { | 					options: { | ||||||
|  | 						modules: true, | ||||||
| 						minimize: true | 						minimize: true | ||||||
| 					} | 					} | ||||||
| 				}, { | 				}, { | ||||||
| 					loader: 'sass-loader', | 					loader: 'stylus-loader' | ||||||
| 					options: { |  | ||||||
| 						importer: jsonImporter, |  | ||||||
| 					} |  | ||||||
| 				}] | 				}] | ||||||
| 			}, { | 			}, { | ||||||
| 				test: /\.css$/, |  | ||||||
| 				use: [{ | 				use: [{ | ||||||
| 					loader: 'vue-style-loader' | 					loader: 'vue-style-loader' | ||||||
| 				}, { | 				}, { | ||||||
| @@ -221,52 +193,79 @@ module.exports = entries.map(x => { | |||||||
| 					options: { | 					options: { | ||||||
| 						minimize: true | 						minimize: true | ||||||
| 					} | 					} | ||||||
| 				}] |  | ||||||
| 			}, { |  | ||||||
| 				test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, |  | ||||||
| 				loader: 'url-loader' |  | ||||||
| 			}, { |  | ||||||
| 				test: /\.ts$/, |  | ||||||
| 				exclude: /node_modules/, |  | ||||||
| 				use: [{ |  | ||||||
| 					loader: 'ts-loader', |  | ||||||
| 					options: { |  | ||||||
| 						happyPackMode: true, |  | ||||||
| 						configFile: __dirname + '/src/client/app/tsconfig.json', |  | ||||||
| 						appendTsSuffixTo: [/\.vue$/] |  | ||||||
| 					} |  | ||||||
| 				}, { | 				}, { | ||||||
| 					loader: 'replace', | 					loader: 'stylus-loader' | ||||||
| 					query: { |  | ||||||
| 						search: i18nReplacer.pattern.toString(), |  | ||||||
| 						replace: 'i18nReplacement', |  | ||||||
| 						i18n: true, |  | ||||||
| 						lang |  | ||||||
| 					} |  | ||||||
| 				}, { |  | ||||||
| 					loader: 'replace', |  | ||||||
| 					query: { |  | ||||||
| 						search: faPattern.toString(), |  | ||||||
| 						replace: 'faReplacement' |  | ||||||
| 					} |  | ||||||
| 				}] | 				}] | ||||||
| 			}] | 			}] | ||||||
| 		}, | 		}, { | ||||||
| 		plugins, | 			test: /\.scss$/, | ||||||
| 		output, | 			exclude: /node_modules/, | ||||||
| 		resolve: { | 			use: [{ | ||||||
| 			extensions: [ | 				loader: 'style-loader' | ||||||
| 				'.js', '.ts', '.json' | 			}, { | ||||||
| 			], | 				loader: 'css-loader', | ||||||
| 			alias: { | 				options: { | ||||||
| 				'const.styl': __dirname + '/src/client/const.styl' | 					minimize: true | ||||||
| 			} | 				} | ||||||
| 		}, | 			}, { | ||||||
| 		resolveLoader: { | 				loader: 'sass-loader', | ||||||
| 			modules: ['node_modules', './webpack/loaders'] | 				options: { | ||||||
| 		}, | 					importer: jsonImporter, | ||||||
| 		cache: true, | 				} | ||||||
| 		devtool: false, //'source-map', | 			}] | ||||||
| 		mode: isProduction ? 'production' : 'development' | 		}, { | ||||||
| 	}; | 			test: /\.css$/, | ||||||
| }); | 			use: [{ | ||||||
|  | 				loader: 'vue-style-loader' | ||||||
|  | 			}, { | ||||||
|  | 				loader: 'css-loader', | ||||||
|  | 				options: { | ||||||
|  | 					minimize: true | ||||||
|  | 				} | ||||||
|  | 			}] | ||||||
|  | 		}, { | ||||||
|  | 			test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/, | ||||||
|  | 			loader: 'url-loader' | ||||||
|  | 		}, { | ||||||
|  | 			test: /\.ts$/, | ||||||
|  | 			exclude: /node_modules/, | ||||||
|  | 			use: [{ | ||||||
|  | 				loader: 'ts-loader', | ||||||
|  | 				options: { | ||||||
|  | 					happyPackMode: true, | ||||||
|  | 					configFile: __dirname + '/src/client/app/tsconfig.json', | ||||||
|  | 					appendTsSuffixTo: [/\.vue$/] | ||||||
|  | 				} | ||||||
|  | 			}, { | ||||||
|  | 				loader: 'replace', | ||||||
|  | 				query: { | ||||||
|  | 					search: i18nPattern.toString(), | ||||||
|  | 					replace: 'i18nReplacement', | ||||||
|  | 					i18n: true | ||||||
|  | 				} | ||||||
|  | 			}, { | ||||||
|  | 				loader: 'replace', | ||||||
|  | 				query: { | ||||||
|  | 					search: faPattern.toString(), | ||||||
|  | 					replace: 'faReplacement' | ||||||
|  | 				} | ||||||
|  | 			}] | ||||||
|  | 		}] | ||||||
|  | 	}, | ||||||
|  | 	plugins, | ||||||
|  | 	output, | ||||||
|  | 	resolve: { | ||||||
|  | 		extensions: [ | ||||||
|  | 			'.js', '.ts', '.json' | ||||||
|  | 		], | ||||||
|  | 		alias: { | ||||||
|  | 			'const.styl': __dirname + '/src/client/const.styl' | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	resolveLoader: { | ||||||
|  | 		modules: ['node_modules', './webpack/loaders'] | ||||||
|  | 	}, | ||||||
|  | 	cache: true, | ||||||
|  | 	devtool: false, //'source-map', | ||||||
|  | 	mode: isProduction ? 'production' : 'development' | ||||||
|  | }; | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								webpack/i18n.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								webpack/i18n.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | /** | ||||||
|  |  * Replace i18n texts | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | export const pattern = /%i18n:([a-z0-9_\-@\.\!]+?)%/g; | ||||||
|  |  | ||||||
|  | export const replacement = (ctx, match, key) => { | ||||||
|  | 	const client = '/src/client/app/'; | ||||||
|  | 	let name = null; | ||||||
|  |  | ||||||
|  | 	const shouldEscape = key[0] == '!'; | ||||||
|  | 	if (shouldEscape) { | ||||||
|  | 		key = key.substr(1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (key[0] == '@') { | ||||||
|  | 		name = ctx.src.substr(ctx.src.indexOf(client) + client.length); | ||||||
|  | 		key = key.substr(1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const path = name ? `${name}|${key}` : key; | ||||||
|  |  | ||||||
|  | 	return shouldEscape ? `%i18n:!${path}%` : `%i18n:${path}%`; | ||||||
|  | }; | ||||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo