Skip to content

Commit

Permalink
Little i18n refractoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Chocobozzz committed Jun 6, 2018
1 parent 7ce44a7 commit 74b7c6d
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 54 deletions.
18 changes: 9 additions & 9 deletions client/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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 ]
Expand Down
20 changes: 11 additions & 9 deletions client/src/app/core/server/server.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -72,8 +72,8 @@ export class ServerService {
private http: HttpClient,
@Inject(LOCALE_ID) private localeId: string
) {
this.loadConfigLocally()
this.loadServerLocale()
this.loadConfigLocally()
}

loadConfig () {
Expand Down Expand Up @@ -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())
}

Expand Down
12 changes: 12 additions & 0 deletions client/src/app/shared/i18n/i18n-utils.ts
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 2 additions & 2 deletions client/src/app/shared/video/video.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 2 additions & 1 deletion client/src/app/videos/+video-watch/video-watch.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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
}

Expand Down
10 changes: 6 additions & 4 deletions client/src/assets/player/peertube-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions client/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
4 changes: 2 additions & 2 deletions scripts/i18n/xliff2json.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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[] = []
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`))
}
Expand Down
22 changes: 9 additions & 13 deletions server/controllers/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down
35 changes: 23 additions & 12 deletions shared/models/i18n/i18n.ts
Original file line number Diff line number Diff line change
@@ -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('-', '_')
}

0 comments on commit 74b7c6d

Please sign in to comment.