Little i18n refractoring

pull/632/head
Chocobozzz 2018-06-06 17:37:13 +02:00
parent 7ce44a74a3
commit 74b7c6d48e
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
10 changed files with 81 additions and 54 deletions

View File

@ -16,8 +16,8 @@ import { MenuComponent } from './menu'
import { SharedModule } from './shared'
import { SignupModule } from './signup'
import { VideosModule } from './videos'
import { buildFileLocale, getDefaultLocale } from '../../../shared/models/i18n'
import { environment } from '../environments/environment'
import { buildFileLocale, getCompleteLocale, getDefaultLocale, isDefaultLocale } from '../../../shared/models/i18n'
import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
export function metaFactory (serverService: ServerService): MetaLoader {
return new MetaStaticLoader({
@ -67,17 +67,17 @@ export function metaFactory (serverService: ServerService): MetaLoader {
{
provide: TRANSLATIONS,
useFactory: (locale) => {
// On dev mode, test locales
if (environment.production === false && window.location.search === '?lang=fr') {
return require(`raw-loader!../locale/target/angular_fr.xml`)
// On dev mode, test localization
if (isOnDevLocale()) {
locale = getDevLocale()
return require(`raw-loader!../locale/target/angular_${locale}.xml`)
}
const fileLocale = buildFileLocale(locale)
// Default locale, nothing to translate
const defaultFileLocale = buildFileLocale(getDefaultLocale())
if (fileLocale === defaultFileLocale) return ''
const completeLocale = getCompleteLocale(locale)
if (isDefaultLocale(completeLocale)) return ''
const fileLocale = buildFileLocale(locale)
return require(`raw-loader!../locale/target/angular_${fileLocale}.xml`)
},
deps: [ LOCALE_ID ]

View File

@ -2,13 +2,13 @@ import { map, share, switchMap, tap } from 'rxjs/operators'
import { HttpClient } from '@angular/common/http'
import { Inject, Injectable, LOCALE_ID } from '@angular/core'
import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
import { Observable, ReplaySubject } from 'rxjs'
import { ServerConfig } from '../../../../../shared'
import { Observable, ReplaySubject, of } from 'rxjs'
import { getCompleteLocale, ServerConfig } from '../../../../../shared'
import { About } from '../../../../../shared/models/server/about.model'
import { environment } from '../../../environments/environment'
import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos'
import { buildFileLocale, getDefaultLocale } from '../../../../../shared/models/i18n'
import { peertubeTranslate } from '@app/shared/i18n/i18n-utils'
import { isDefaultLocale } from '../../../../../shared/models/i18n'
import { getDevLocale, isOnDevLocale, peertubeTranslate } from '@app/shared/i18n/i18n-utils'
@Injectable()
export class ServerService {
@ -72,8 +72,8 @@ export class ServerService {
private http: HttpClient,
@Inject(LOCALE_ID) private localeId: string
) {
this.loadConfigLocally()
this.loadServerLocale()
this.loadConfigLocally()
}
loadConfig () {
@ -163,14 +163,16 @@ export class ServerService {
}
private loadServerLocale () {
const fileLocale = buildFileLocale(environment.production === true ? this.localeId : 'fr')
const completeLocale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId)
// Default locale, nothing to translate
const defaultFileLocale = buildFileLocale(getDefaultLocale())
if (fileLocale === defaultFileLocale) return {}
if (isDefaultLocale(completeLocale)) {
this.localeObservable = of({}).pipe(share())
return
}
this.localeObservable = this.http
.get(ServerService.BASE_LOCALE_URL + fileLocale + '/server.json')
.get(ServerService.BASE_LOCALE_URL + completeLocale + '/server.json')
.pipe(share())
}

View File

@ -1,7 +1,19 @@
import { environment } from '../../../environments/environment'
function peertubeTranslate (str: string, translations: { [ id: string ]: string }) {
return translations[str] ? translations[str] : str
}
function isOnDevLocale () {
return environment.production === false && window.location.search === '?lang=fr'
}
function getDevLocale () {
return 'fr'
}
export {
getDevLocale,
isOnDevLocale,
peertubeTranslate
}

View File

@ -46,8 +46,8 @@ export class VideoService {
return this.serverService.localeObservable
.pipe(
switchMap(translations => {
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid)
.pipe(map(videoHash => ({ videoHash, translations })))
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid)
.pipe(map(videoHash => ({ videoHash, translations })))
}),
map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)),
catchError(res => this.restExtractor.handleError(res))

View File

@ -25,6 +25,7 @@ import { getVideojsOptions, loadLocale, addContextMenu } from '../../../assets/p
import { ServerService } from '@app/core'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { environment } from '../../../environments/environment'
import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
@Component({
selector: 'my-video-watch',
@ -377,7 +378,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
})
if (this.videojsLocaleLoaded === false) {
await loadLocale(environment.apiUrl, videojs, environment.production === true ? this.localeId : 'fr')
await loadLocale(environment.apiUrl, videojs, isOnDevLocale() ? getDevLocale() : this.localeId)
this.videojsLocaleLoaded = true
}

View File

@ -12,7 +12,7 @@ import './peertube-videojs-plugin'
import './peertube-load-progress-bar'
import { videojsUntyped } from './peertube-videojs-typings'
import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils'
import { is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
import { getCompleteLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
@ -141,11 +141,13 @@ function addContextMenu (player: any, videoEmbedUrl: string) {
}
function loadLocale (serverUrl: string, videojs: any, locale: string) {
if (!is18nLocale(locale) || isDefaultLocale(locale)) return undefined
const completeLocale = getCompleteLocale(locale)
return fetch(serverUrl + '/client/locales/' + locale + '/player.json')
if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return Promise.resolve(undefined)
return fetch(serverUrl + '/client/locales/' + completeLocale + '/player.json')
.then(res => res.json())
.then(json => videojs.addLanguage(locale, json))
.then(json => videojs.addLanguage(completeLocale, json))
}
export {

View File

@ -5,14 +5,17 @@ import { AppModule } from './app/app.module'
import { environment } from './environments/environment'
import { hmrBootstrap } from './hmr'
import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
let providers = []
if (environment.production) {
enableProdMode()
}
if (environment.production === false && window.location.search === '?lang=fr') {
const translations = require(`raw-loader!./locale/target/angular_fr.xml`)
// Template translation, should be in the bootstrap step
if (isOnDevLocale()) {
const locale = getDevLocale()
const translations = require(`raw-loader!./locale/target/angular_${locale}.xml`)
providers = [
{ provide: TRANSLATIONS, useValue: translations },

View File

@ -1,7 +1,7 @@
import * as xliff12ToJs from 'xliff/xliff12ToJs'
import { unlink, readFileSync, writeFile } from 'fs'
import { join } from 'path'
import { buildFileLocale, I18N_LOCALES, isDefaultLocale } from '../../shared/models/i18n/i18n'
import { buildFileLocale, I18N_LOCALES, isDefaultLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
import { eachSeries } from 'async'
const sources: string[] = []
@ -9,7 +9,7 @@ const availableLocales = Object.keys(I18N_LOCALES)
.filter(l => isDefaultLocale(l) === false)
.map(l => buildFileLocale(l))
for (const file of [ 'server', 'player' ]) {
for (const file of LOCALE_FILES) {
for (const locale of availableLocales) {
sources.push(join(__dirname, '../../../client/src/locale/target/', `${file}_${locale}.xml`))
}

View File

@ -3,18 +3,12 @@ import * as express from 'express'
import { join } from 'path'
import * as validator from 'validator'
import { escapeHTML, readFileBufferPromise, root } from '../helpers/core-utils'
import {
ACCEPT_HEADERS,
CONFIG,
EMBED_SIZE,
OPENGRAPH_AND_OEMBED_COMMENT,
STATIC_MAX_AGE,
STATIC_PATHS
} from '../initializers'
import { ACCEPT_HEADERS, CONFIG, EMBED_SIZE, OPENGRAPH_AND_OEMBED_COMMENT, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers'
import { asyncMiddleware } from '../middlewares'
import { VideoModel } from '../models/video/video'
import { VideoPrivacy } from '../../shared/models/videos'
import { I18N_LOCALES, is18nLocale, getDefaultLocale } from '../../shared/models'
import { buildFileLocale, getCompleteLocale, getDefaultLocale, is18nLocale } from '../../shared/models'
import { LOCALE_FILES } from '../../shared/models/i18n/i18n'
const clientsRouter = express.Router()
@ -51,8 +45,10 @@ clientsRouter.use('/client/locales/:locale/:file.json', function (req, res) {
const locale = req.params.locale
const file = req.params.file
if (is18nLocale(locale) && [ 'player', 'server' ].indexOf(file) !== -1) {
return res.sendFile(join(__dirname, `../../../client/dist/locale/${file}_${locale}.json`))
if (is18nLocale(locale) && LOCALE_FILES.indexOf(file) !== -1) {
const completeLocale = getCompleteLocale(locale)
const completeFileLocale = buildFileLocale(completeLocale)
return res.sendFile(join(__dirname, `../../../client/dist/locale/${file}_${completeFileLocale}.json`))
}
return res.sendStatus(404)
@ -88,12 +84,12 @@ function getIndexPath (req: express.Request, paramLang?: string) {
if (paramLang && is18nLocale(paramLang)) {
lang = paramLang
} else {
// lang = req.acceptsLanguages(Object.keys(I18N_LOCALES)) || getDefaultLocale()
// lang = req.acceptsLanguages(POSSIBLE_LOCALES) || getDefaultLocale()
// Disable auto language for now
lang = getDefaultLocale()
}
return join(__dirname, '../../../client/dist/' + lang + '/index.html')
return join(__dirname, '../../../client/dist/' + buildFileLocale(lang) + '/index.html')
}
function addOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) {

View File

@ -1,34 +1,45 @@
export const LOCALE_FILES = [ 'player', 'server' ]
export const I18N_LOCALES = {
'en-US': 'English (US)',
fr: 'French'
}
const I18N_LOCALE_ALIAS = {
'en': 'en-US'
}
export const POSSIBLE_LOCALES = Object.keys(I18N_LOCALES)
.concat(Object.keys(I18N_LOCALE_ALIAS))
const possiblePaths = POSSIBLE_LOCALES.map(l => '/' + l)
export function getDefaultLocale () {
return 'en-US'
}
export function isDefaultLocale (locale: string) {
return locale === getDefaultLocale()
return getCompleteLocale(locale) === getCompleteLocale(getDefaultLocale())
}
const possiblePaths = Object.keys(I18N_LOCALES).map(l => '/' + l)
export function is18nPath (path: string) {
return possiblePaths.indexOf(path) !== -1
}
const possibleLanguages = Object.keys(I18N_LOCALES)
export function is18nLocale (locale: string) {
return possibleLanguages.indexOf(locale) !== -1
return POSSIBLE_LOCALES.indexOf(locale) !== -1
}
export function getCompleteLocale (locale: string) {
if (!locale) return locale
if (I18N_LOCALE_ALIAS[locale]) return I18N_LOCALE_ALIAS[locale]
return locale
}
// Only use in dev mode, so relax
// In production, the locale always match with a I18N_LANGUAGES key
export function buildFileLocale (locale: string) {
if (!is18nLocale(locale)) {
// Some working examples for development purpose
if (locale.split('-')[ 0 ] === 'en') return 'en_US'
else if (locale === 'fr') return 'fr'
}
const completeLocale = getCompleteLocale(locale)
return locale.replace('-', '_')
return completeLocale.replace('-', '_')
}