Comply w/ coding style
This commit is contained in:
parent
c361e1e31a
commit
18368fefaa
|
@ -5,8 +5,14 @@ debian/
|
|||
libs/
|
||||
node_modules/
|
||||
|
||||
# The following are checked by ESLint which supersedes JSHint.
|
||||
# The following are checked by ESLint with the maximum configuration which
|
||||
# supersedes JSHint.
|
||||
flow-typed/
|
||||
react/
|
||||
|
||||
# The following are checked by ESLint with the minimum configuration which does
|
||||
# not supersede JSHint but take advantage of advanced language features such as
|
||||
# Facebook Flow which are not supported by JSHint.
|
||||
modules/translation/translation.js
|
||||
|
||||
analytics.js
|
||||
|
|
|
@ -39,44 +39,44 @@
|
|||
"videoMute": "Start or stop your camera"
|
||||
},
|
||||
"welcomepage":{
|
||||
"go": "GO",
|
||||
"join": "JOIN",
|
||||
"roomname": "Enter room name",
|
||||
"roomnamePlaceHolder": "room name",
|
||||
"disable": "Don't show this page again",
|
||||
"feature1": {
|
||||
"title": "Simple to use",
|
||||
"content": "No downloads required. __app__ works directly within your browser. Simply share your conference URL with others to get started."
|
||||
"content": "No downloads required. __app__ works directly within your browser. Simply share your conference URL with others to get started.",
|
||||
"title": "Simple to use"
|
||||
},
|
||||
"feature2": {
|
||||
"title": "Low bandwidth",
|
||||
"content": "Multi-party video conferences work with as little as 128Kbps. Screen-sharing and audio-only conferences are possible with far less."
|
||||
"content": "Multi-party video conferences work with as little as 128Kbps. Screen-sharing and audio-only conferences are possible with far less.",
|
||||
"title": "Low bandwidth"
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Open source",
|
||||
"content": "__app__ is licensed under the Apache License. You are free to download, use, modify, and share it as per this license."
|
||||
"content": "__app__ is licensed under the Apache License. You are free to download, use, modify, and share it as per this license.",
|
||||
"title": "Open source"
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Unlimited users",
|
||||
"content": "There are no artificial restrictions on the number of users or conference participants. Server power and bandwidth are the only limiting factors."
|
||||
"content": "There are no artificial restrictions on the number of users or conference participants. Server power and bandwidth are the only limiting factors.",
|
||||
"title": "Unlimited users"
|
||||
},
|
||||
"feature5": {
|
||||
"title": "Screen sharing",
|
||||
"content": "It's easy to share your screen with others. __app__ is ideal for on-line presentations, lectures, and tech support sessions."
|
||||
"content": "It's easy to share your screen with others. __app__ is ideal for on-line presentations, lectures, and tech support sessions.",
|
||||
"title": "Screen sharing"
|
||||
},
|
||||
"feature6": {
|
||||
"title": "Secure rooms",
|
||||
"content": "Need some privacy? __app__ conference rooms can be secured with a password in order to exclude unwanted guests and prevent interruptions."
|
||||
"content": "Need some privacy? __app__ conference rooms can be secured with a password in order to exclude unwanted guests and prevent interruptions.",
|
||||
"title": "Secure rooms"
|
||||
},
|
||||
"feature7": {
|
||||
"title": "Shared notes",
|
||||
"content": "__app__ features Etherpad, a real-time collaborative text editor that's great for meeting minutes, writing articles, and more."
|
||||
"content": "__app__ features Etherpad, a real-time collaborative text editor that's great for meeting minutes, writing articles, and more.",
|
||||
"title": "Shared notes"
|
||||
},
|
||||
"feature8": {
|
||||
"title": "Usage statistics",
|
||||
"content": "Learn about your users through easy integration with Piwik, Google Analytics, and other usage monitoring and statistics systems."
|
||||
"content": "Learn about your users through easy integration with Piwik, Google Analytics, and other usage monitoring and statistics systems.",
|
||||
"title": "Usage statistics"
|
||||
},
|
||||
"go": "GO",
|
||||
"join": "JOIN",
|
||||
"privacy": "Privacy",
|
||||
"roomname": "Enter room name",
|
||||
"roomnamePlaceHolder": "room name",
|
||||
"sendFeedback": "Send feedback",
|
||||
"terms": "Terms"
|
||||
},
|
||||
|
@ -115,14 +115,12 @@
|
|||
"profile": "Edit your profile",
|
||||
"raiseHand": "Raise / Lower your hand"
|
||||
},
|
||||
"unsupportedPage": {
|
||||
"onlySupportedBy": "This application is currently only supported by",
|
||||
"download": "DOWNLOAD",
|
||||
"joinConversation": "Join the conversation",
|
||||
"startConference": "Start a conference",
|
||||
"joinConversationMobile": "You need <strong>__app__</strong> to join a conversation on your mobile",
|
||||
"unsupportedBrowser": {
|
||||
"appInstalled": "or if you already have it<br /><strong>then</strong>",
|
||||
"appNotInstalled": "You need <strong>__app__</strong> to join a conversation on your mobile",
|
||||
"downloadApp": "Download the App",
|
||||
"availableApp": "or if you already have it<br /><strong>then</strong>"
|
||||
"joinConversation": "Join the conversation",
|
||||
"startConference": "Start a conference"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Open / close chat",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/* global $, APP, AJS, interfaceConfig, JitsiMeetJS */
|
||||
|
||||
import { LANGUAGES } from "../../../../react/features/base/i18n";
|
||||
|
||||
import UIUtil from "../../util/UIUtil";
|
||||
import UIEvents from "../../../../service/UI/UIEvents";
|
||||
import languages from "../../../../service/translation/languages";
|
||||
import Settings from '../../../settings/Settings';
|
||||
|
||||
const sidePanelsContainerId = 'sideToolbarContainer';
|
||||
|
@ -145,7 +146,7 @@ export default {
|
|||
let selectInput;
|
||||
|
||||
selectEl.html(generateLanguagesOptions(
|
||||
languages.getLanguages(),
|
||||
LANGUAGES,
|
||||
APP.translation.getCurrentLanguage()
|
||||
));
|
||||
initSelect2(selectEl, () => {
|
||||
|
|
|
@ -1,46 +1,56 @@
|
|||
/* global $ */
|
||||
import { i18n, DEFAULT_LANG } from '../../react/features/base/translation';
|
||||
/* @flow */
|
||||
|
||||
import jqueryI18next from 'jquery-i18next';
|
||||
|
||||
function initCompleted() {
|
||||
$("[data-i18n]").localize();
|
||||
import { DEFAULT_LANGUAGE, i18next } from '../../react/features/base/i18n';
|
||||
|
||||
declare var $: Function;
|
||||
|
||||
/**
|
||||
* Notifies that the {@link i18next} instance has finished its initialization.
|
||||
*
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function _onI18nInitialized() {
|
||||
$('[data-i18n]').localize();
|
||||
}
|
||||
|
||||
class Translation {
|
||||
init () {
|
||||
if (i18n.isInitialized)
|
||||
initCompleted();
|
||||
else
|
||||
i18n.on('initialized', initCompleted);
|
||||
|
||||
jqueryI18next.init(i18n, $, {useOptionsAttr: true});
|
||||
addLanguageChangedListener(listener: Function) {
|
||||
i18next.on('languageChanged', listener);
|
||||
}
|
||||
|
||||
setLanguage (lang) {
|
||||
if(!lang)
|
||||
lang = DEFAULT_LANG;
|
||||
i18n.setLng(lang, {}, initCompleted);
|
||||
}
|
||||
generateTranslationHTML(key: string, options: Object) {
|
||||
const optAttr
|
||||
= options ? ` data-i18n-options='${JSON.stringify(options)}'` : '';
|
||||
|
||||
getCurrentLanguage () {
|
||||
return i18n.lng();
|
||||
}
|
||||
// XXX i18next expects undefined if options are missing.
|
||||
const text = i18next.t(key, options ? options : undefined);
|
||||
|
||||
translateElement (selector, options) {
|
||||
// i18next expects undefined if options are missing, check if its null
|
||||
selector.localize(
|
||||
options === null ? undefined : options);
|
||||
}
|
||||
|
||||
generateTranslationHTML (key, options) {
|
||||
let optAttr = options
|
||||
? ` data-i18n-options='${JSON.stringify(options)}'` : "";
|
||||
let text = i18n.t(key, options === null ? undefined : options);
|
||||
return `<span data-i18n="${key}"${optAttr}>${text}</span>`;
|
||||
}
|
||||
|
||||
addLanguageChangedListener(listener) {
|
||||
i18n.on('languageChanged', listener);
|
||||
getCurrentLanguage() {
|
||||
return i18next.lng();
|
||||
}
|
||||
|
||||
init() {
|
||||
if (i18next.isInitialized)
|
||||
_onI18nInitialized();
|
||||
else
|
||||
i18next.on('initialized', _onI18nInitialized);
|
||||
|
||||
jqueryI18next.init(i18next, $, { useOptionsAttr: true });
|
||||
}
|
||||
|
||||
setLanguage(language: string = DEFAULT_LANGUAGE) {
|
||||
i18next.setLng(language, {}, _onI18nInitialized);
|
||||
}
|
||||
|
||||
translateElement(selector: Object, options: Object) {
|
||||
// XXX i18next expects undefined if options are missing.
|
||||
selector.localize(options ? options : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"react-native-background-timer": "1.0.0",
|
||||
"react-native-immersive": "0.0.4",
|
||||
"react-native-keep-awake": "^2.0.2",
|
||||
"react-native-locale-detector": "1.0.1 ",
|
||||
"react-native-locale-detector": "1.0.1",
|
||||
"react-native-prompt": "^1.0.0",
|
||||
"react-native-vector-icons": "^4.0.0",
|
||||
"react-native-webrtc": "jitsi/react-native-webrtc",
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/* global APP */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Provider } from 'react-redux';
|
||||
import { compose, createStore } from 'redux';
|
||||
import Thunk from 'redux-thunk';
|
||||
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { i18n } from '../../base/translation';
|
||||
|
||||
import { i18next } from '../../base/i18n';
|
||||
import {
|
||||
localParticipantJoined,
|
||||
localParticipantLeft
|
||||
|
@ -137,7 +136,7 @@ export class AbstractApp extends Component {
|
|||
|
||||
if (route) {
|
||||
return (
|
||||
<I18nextProvider i18n = { i18n }>
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Provider store = { this._getStore() }>
|
||||
{
|
||||
this._createElement(route.component)
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
/* global config */
|
||||
/* @flow */
|
||||
|
||||
declare var config: Object;
|
||||
|
||||
/**
|
||||
* Custom language detection, just returns the config property if any.
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Name of the language detector.
|
||||
* Does not support caching.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
name: 'configLanguageDetector',
|
||||
cacheUserLanguage: Function.prototype,
|
||||
|
||||
/**
|
||||
* The actual lookup.
|
||||
* Looks the language up in the config.
|
||||
*
|
||||
* @returns {string} The default language if any.
|
||||
*/
|
||||
|
@ -19,7 +23,7 @@ export default {
|
|||
},
|
||||
|
||||
/**
|
||||
* Doesn't support caching.
|
||||
* Name of the language detector.
|
||||
*/
|
||||
cacheUserLanguage: Function.prototype
|
||||
name: 'configLanguageDetector'
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* The available/supported languages.
|
||||
*
|
||||
* XXX The element at index zero is the default language.
|
||||
*
|
||||
* @public
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
export const LANGUAGES = [
|
||||
'en', // XXX The default language.
|
||||
|
||||
'bg',
|
||||
'de',
|
||||
'es',
|
||||
'fr',
|
||||
'hy',
|
||||
'it',
|
||||
'oc',
|
||||
'pl',
|
||||
'ptBR',
|
||||
'ru',
|
||||
'sk',
|
||||
'sl',
|
||||
'sv',
|
||||
'tr'
|
||||
];
|
||||
|
||||
/**
|
||||
* The default language.
|
||||
*
|
||||
* XXX The element at index zero of {@link LANGUAGES} is the default language.
|
||||
*
|
||||
* @public
|
||||
* @type {string} The default language.
|
||||
*/
|
||||
export const DEFAULT_LANGUAGE = LANGUAGES[0];
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import { translate as reactI18nextTranslate } from 'react-i18next';
|
||||
|
||||
/**
|
||||
* Wraps a specific React Component in order to enable translations in it.
|
||||
*
|
||||
* @param {Component} component - The React Component to wrap.
|
||||
* @returns {Component} The React Component which wraps {@link component} and
|
||||
* enables translations in it.
|
||||
*/
|
||||
export function translate(component) {
|
||||
// Use the default list of namespaces.
|
||||
return (
|
||||
reactI18nextTranslate([ 'main', 'languages' ], { wait: true })(
|
||||
component));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a specific key to text containing HTML via a specific translate
|
||||
* function.
|
||||
*
|
||||
* @param {Function} t - The translate function.
|
||||
* @param {string} key - The key to translate.
|
||||
* @param {Array<*>} options - The options, if any, to pass to {@link t}.
|
||||
* @returns {ReactElement} A ReactElement which depicts the translated HTML
|
||||
* text.
|
||||
*/
|
||||
export function translateToHTML(t, key, options = {}) {
|
||||
// eslint-disable-next-line react/no-danger
|
||||
return <span dangerouslySetInnerHTML = {{ __html: t(key, options) }} />;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import i18next from 'i18next';
|
||||
import I18nextXHRBackend from 'i18next-xhr-backend';
|
||||
|
||||
import LANGUAGES_RESOURCES from '../../../../lang/languages.json';
|
||||
import MAIN_RESOURCES from '../../../../lang/main.json';
|
||||
|
||||
import { DEFAULT_LANGUAGE, LANGUAGES } from './constants';
|
||||
import languageDetector from './languageDetector';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The options to initialize i18next with.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const options = {
|
||||
app:
|
||||
(typeof interfaceConfig !== 'undefined' && interfaceConfig.APP_NAME)
|
||||
|| 'Jitsi Meet',
|
||||
compatibilityAPI: 'v1',
|
||||
compatibilityJSON: 'v1',
|
||||
fallbackLng: DEFAULT_LANGUAGE,
|
||||
fallbackOnEmpty: true,
|
||||
fallbackOnNull: true,
|
||||
|
||||
// XXX i18next modifies the array lngWhitelist so make sure to clone
|
||||
// LANGUAGES.
|
||||
lngWhitelist: LANGUAGES.slice(),
|
||||
load: 'unspecific',
|
||||
ns: {
|
||||
defaultNs: 'main',
|
||||
namespaces: [ 'main', 'languages' ]
|
||||
},
|
||||
resGetPath: 'lang/__ns__-__lng__.json',
|
||||
useDataAttrOptions: true
|
||||
};
|
||||
|
||||
i18next
|
||||
.use(I18nextXHRBackend)
|
||||
.use(languageDetector)
|
||||
.use({
|
||||
name: 'resolveAppName',
|
||||
process: (res, key) => i18next.t(key, { app: options.app }),
|
||||
type: 'postProcessor'
|
||||
})
|
||||
.init(options);
|
||||
|
||||
// Add default language which is preloaded from the source code.
|
||||
i18next.addResourceBundle(
|
||||
DEFAULT_LANGUAGE,
|
||||
'main',
|
||||
MAIN_RESOURCES,
|
||||
/* deep */ true,
|
||||
/* overwrite */ true);
|
||||
i18next.addResourceBundle(
|
||||
DEFAULT_LANGUAGE,
|
||||
'languages',
|
||||
LANGUAGES_RESOURCES,
|
||||
/* deep */ true,
|
||||
/* overwrite */ true);
|
||||
|
||||
export default i18next;
|
|
@ -0,0 +1,6 @@
|
|||
export * from './constants';
|
||||
export * from './functions';
|
||||
|
||||
// TODO Eventually (e.g. when the non-React Web app is rewritten into React), it
|
||||
// should not be necessary to export i18next.
|
||||
export { default as i18next } from './i18next';
|
|
@ -0,0 +1,24 @@
|
|||
/* @flow */
|
||||
|
||||
import locale from 'react-native-locale-detector';
|
||||
|
||||
/**
|
||||
* The singleton language detector for React Native which uses the system-wide
|
||||
* locale.
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Does not support caching.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
cacheUserLanguage: Function.prototype,
|
||||
|
||||
detect() {
|
||||
return locale;
|
||||
},
|
||||
|
||||
init: Function.prototype,
|
||||
|
||||
type: 'languageDetector'
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
/* @flow */
|
||||
|
||||
import BrowserLanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
import configLanguageDetector from './configLanguageDetector';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The ordered list (by name) of language detectors to be utilized as backends
|
||||
* by the singleton language detector for Web.
|
||||
*
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
const order = [
|
||||
'querystring',
|
||||
'localStorage',
|
||||
configLanguageDetector.name
|
||||
];
|
||||
|
||||
// Allow i18next to detect the system language reported by the Web browser
|
||||
// itself.
|
||||
interfaceConfig.LANG_DETECTION && order.push('navigator');
|
||||
|
||||
/**
|
||||
* The singleton language detector for Web.
|
||||
*/
|
||||
const languageDetector
|
||||
= new BrowserLanguageDetector(
|
||||
/* services */ null,
|
||||
/* options */ {
|
||||
caches: [ 'localStorage' ],
|
||||
lookupLocalStorage: 'language',
|
||||
lookupQuerystring: 'lang',
|
||||
order
|
||||
});
|
||||
|
||||
// Add the language detector which looks the language up in the config. Its
|
||||
// order has already been established above.
|
||||
languageDetector.addDetector(configLanguageDetector);
|
||||
|
||||
export default languageDetector;
|
|
@ -1,7 +1,8 @@
|
|||
/* @flow */
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { translate } from '../../translation';
|
||||
|
||||
import { translate } from '../../i18n';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var interfaceConfig: Object;
|
||||
|
@ -19,7 +20,7 @@ const _RIGHT_WATERMARK_STYLE = {
|
|||
* A Web Component which renders watermarks such as Jits, brand, powered by,
|
||||
* etc.
|
||||
*/
|
||||
class WatermarksComponent extends Component {
|
||||
class Watermarks extends Component {
|
||||
state = {
|
||||
brandWatermarkLink: String,
|
||||
jitsiWatermarkLink: String,
|
||||
|
@ -147,7 +148,7 @@ class WatermarksComponent extends Component {
|
|||
className = 'poweredby'
|
||||
href = 'http://jitsi.org'
|
||||
target = '_new'>
|
||||
<span>{t('poweredby')} jitsi.org</span>
|
||||
<span>{ t('poweredby') } jitsi.org</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
@ -156,4 +157,4 @@ class WatermarksComponent extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export const Watermarks = translate(WatermarksComponent);
|
||||
export default translate(Watermarks);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export * from './Container';
|
||||
export * from './Link';
|
||||
export * from './Watermarks';
|
||||
export { default as Watermarks } from './Watermarks';
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import locale from 'react-native-locale-detector';
|
||||
|
||||
/**
|
||||
* A language detector that uses native locale.
|
||||
*/
|
||||
export default {
|
||||
init: Function.prototype,
|
||||
type: 'languageDetector',
|
||||
detect: () => locale,
|
||||
cacheUserLanguage: Function.prototype
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
/* global interfaceConfig */
|
||||
import Browser from 'i18next-browser-languagedetector';
|
||||
import ConfigLanguageDetector from './ConfigLanguageDetector';
|
||||
|
||||
/**
|
||||
* List of detectors to use in their order.
|
||||
*
|
||||
* @type {[*]}
|
||||
*/
|
||||
const detectors = [ 'querystring', 'localStorage', 'configLanguageDetector' ];
|
||||
|
||||
/**
|
||||
* Allow i18n to detect the system language from the browser.
|
||||
*/
|
||||
if (interfaceConfig.LANG_DETECTION) {
|
||||
detectors.push('navigator');
|
||||
}
|
||||
|
||||
/**
|
||||
* The language detectors.
|
||||
*/
|
||||
const browser = new Browser(null, {
|
||||
order: detectors,
|
||||
lookupQuerystring: 'lang',
|
||||
lookupLocalStorage: 'language',
|
||||
caches: [ 'localStorage' ]
|
||||
});
|
||||
|
||||
/**
|
||||
* adds a language detector that just checks the config
|
||||
*/
|
||||
browser.addDetector(ConfigLanguageDetector);
|
||||
|
||||
export default browser;
|
|
@ -1,46 +0,0 @@
|
|||
/* global interfaceConfig */
|
||||
import i18n from 'i18next';
|
||||
import XHR from 'i18next-xhr-backend';
|
||||
import { DEFAULT_LANG, languages } from './constants';
|
||||
import languagesR from '../../../../lang/languages.json';
|
||||
import mainR from '../../../../lang/main.json';
|
||||
|
||||
import LanguageDetector from './LanguageDetector';
|
||||
|
||||
/**
|
||||
* Default options to initialize i18next.
|
||||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
const defaultOptions = {
|
||||
compatibilityAPI: 'v1',
|
||||
compatibilityJSON: 'v1',
|
||||
fallbackLng: DEFAULT_LANG,
|
||||
load: 'unspecific',
|
||||
resGetPath: 'lang/__ns__-__lng__.json',
|
||||
ns: {
|
||||
namespaces: [ 'main', 'languages' ],
|
||||
defaultNs: 'main'
|
||||
},
|
||||
lngWhitelist: languages.getLanguages(),
|
||||
fallbackOnNull: true,
|
||||
fallbackOnEmpty: true,
|
||||
useDataAttrOptions: true,
|
||||
app: typeof interfaceConfig === 'undefined'
|
||||
? 'Jitsi Meet' : interfaceConfig.APP_NAME
|
||||
};
|
||||
|
||||
i18n.use(XHR)
|
||||
.use(LanguageDetector)
|
||||
.use({
|
||||
type: 'postProcessor',
|
||||
name: 'resolveAppName',
|
||||
process: (res, key) => i18n.t(key, { app: defaultOptions.app })
|
||||
})
|
||||
.init(defaultOptions);
|
||||
|
||||
// adds default language which is preloaded from code
|
||||
i18n.addResourceBundle(DEFAULT_LANG, 'main', mainR, true, true);
|
||||
i18n.addResourceBundle(DEFAULT_LANG, 'languages', languagesR, true, true);
|
||||
|
||||
export default i18n;
|
|
@ -1,13 +0,0 @@
|
|||
import languages from '../../../../service/translation/languages';
|
||||
|
||||
/**
|
||||
* The default language globally for the project.
|
||||
*
|
||||
* @type {string} the default language globally for the project.
|
||||
*/
|
||||
export const DEFAULT_LANG = languages.EN;
|
||||
|
||||
/**
|
||||
* Exports the list of languages currently supported.
|
||||
*/
|
||||
export { languages };
|
|
@ -1,32 +0,0 @@
|
|||
import { translate as reactTranslate } from 'react-i18next';
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Wrap a translatable component.
|
||||
*
|
||||
* @param {Component} component - The component to wrap.
|
||||
* @returns {Component} The wrapped component.
|
||||
*/
|
||||
export function translate(component) {
|
||||
// use the default list of namespaces
|
||||
return reactTranslate([ 'main', 'languages' ], { wait: true })(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates key and prepares data to be passed to dangerouslySetInnerHTML.
|
||||
* Used when translation text contains html.
|
||||
*
|
||||
* @param {func} t - Translate function.
|
||||
* @param {string} key - The key to translate.
|
||||
* @param {Array} options - Optional options.
|
||||
* @returns {XML} A span using dangerouslySetInnerHTML to insert html text.
|
||||
*/
|
||||
export function translateToHTML(t, key, options = {}) {
|
||||
/* eslint-disable react/no-danger */
|
||||
return (
|
||||
<span
|
||||
dangerouslySetInnerHTML = {{ __html: t(key, options) }} />
|
||||
);
|
||||
|
||||
/* eslint-enable react/no-danger */
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export { default as i18n } from './Translation';
|
||||
export * from './constants';
|
||||
export * from './functions';
|
|
@ -3,8 +3,7 @@ import Prompt from 'react-native-prompt';
|
|||
import { connect } from 'react-redux';
|
||||
|
||||
import { setPassword } from '../../base/conference';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
/**
|
||||
* Implements a React Component which prompts the user when a password is
|
||||
|
@ -24,6 +23,13 @@ class PasswordRequiredPrompt extends Component {
|
|||
*/
|
||||
conference: React.PropTypes.object,
|
||||
dispatch: React.PropTypes.func,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: React.PropTypes.func
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { randomInt } from '../../base/util';
|
||||
|
||||
import AbstractOverlay from './AbstractOverlay';
|
||||
import ReloadTimer from './ReloadTimer';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
declare var AJS: Object;
|
||||
|
||||
|
@ -57,10 +57,10 @@ class ReloadTimer extends Component {
|
|||
step: React.PropTypes.number,
|
||||
|
||||
/**
|
||||
* The function used to translate strings.
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {func}
|
||||
* @type {Function}
|
||||
*/
|
||||
t: React.PropTypes.func
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
|
||||
import AbstractOverlay from './AbstractOverlay';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
import AbstractOverlay from './AbstractOverlay';
|
||||
|
||||
/**
|
||||
* Implements a React Component for suspended overlay. Shown when a suspend is
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import AbstractOverlay from './AbstractOverlay';
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/translation';
|
||||
import AbstractOverlay from './AbstractOverlay';
|
||||
|
||||
/**
|
||||
* Implements a React Component for overlay with guidance how to proceed with
|
||||
|
@ -56,7 +56,7 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
|
|||
* @protected
|
||||
*/
|
||||
_renderOverlayContent() {
|
||||
const { t } = this.props;
|
||||
const { browser, t } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -64,12 +64,18 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
|
|||
<span className = 'inlay__icon icon-microphone' />
|
||||
<span className = 'inlay__icon icon-camera' />
|
||||
<h3 className = 'inlay__title'>
|
||||
{ t('startupoverlay.title',
|
||||
{ postProcess: 'resolveAppName' }) }
|
||||
{
|
||||
t(
|
||||
'startupoverlay.title',
|
||||
{ postProcess: 'resolveAppName' })
|
||||
}
|
||||
</h3>
|
||||
<span className = 'inlay__text'>
|
||||
{ translateToHTML(t,
|
||||
`userMedia.${this.props.browser}GrantPermissions`)}
|
||||
{
|
||||
translateToHTML(
|
||||
t,
|
||||
`userMedia.${browser}GrantPermissions`)
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div className = 'policy overlay__policy'>
|
||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from 'react';
|
|||
import Prompt from 'react-native-prompt';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { endRoomLockRequest } from '../actions';
|
||||
import { translate } from '../../base/i18n';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
import { endRoomLockRequest } from '../actions';
|
||||
|
||||
/**
|
||||
* Implements a React Component which prompts the user for a password to lock a
|
||||
|
@ -24,6 +24,13 @@ class RoomLockPrompt extends Component {
|
|||
*/
|
||||
conference: React.PropTypes.object,
|
||||
dispatch: React.PropTypes.func,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: React.PropTypes.func
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { Platform } from '../../base/react';
|
||||
import { translate } from '../../base/translation';
|
||||
|
||||
import { CHROME, FIREFOX, IE, SAFARI } from './browserLinks';
|
||||
import HideNotificationBarStyle from './HideNotificationBarStyle';
|
||||
|
||||
/**
|
||||
* The CSS style namespace of UnsupportedDesktopBrowser.
|
||||
* The namespace of the CSS styles of UnsupportedDesktopBrowser.
|
||||
*
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
const _NS = 'unsupported-desktop-browser';
|
||||
const _SNS = 'unsupported-desktop-browser';
|
||||
|
||||
/**
|
||||
* React component representing unsupported browser page.
|
||||
|
@ -28,6 +28,12 @@ class UnsupportedDesktopBrowser extends Component {
|
|||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: React.PropTypes.func
|
||||
}
|
||||
|
||||
|
@ -38,17 +44,17 @@ class UnsupportedDesktopBrowser extends Component {
|
|||
*/
|
||||
render() {
|
||||
return (
|
||||
<div className = { _NS }>
|
||||
<h2 className = { `${_NS}__title` }>
|
||||
<div className = { _SNS }>
|
||||
<h2 className = { `${_SNS}__title` }>
|
||||
It looks like you're using a browser we don't support.
|
||||
</h2>
|
||||
<p className = { `${_NS}__description` }>
|
||||
<p className = { `${_SNS}__description` }>
|
||||
Please try again with the latest version of
|
||||
<a
|
||||
className = { `${_NS}__link` }
|
||||
className = { `${_SNS}__link` }
|
||||
href = { CHROME } >Chrome</a>,
|
||||
<a
|
||||
className = { `${_NS}__link` }
|
||||
className = { `${_SNS}__link` }
|
||||
href = { FIREFOX }>Firefox</a> or
|
||||
{
|
||||
this._renderOSSpecificBrowserDownloadLink()
|
||||
|
@ -84,7 +90,7 @@ class UnsupportedDesktopBrowser extends Component {
|
|||
if (typeof link !== 'undefined') {
|
||||
return (
|
||||
<a
|
||||
className = { `${_NS}__link` }
|
||||
className = { `${_SNS}__link` }
|
||||
href = { link }>
|
||||
{
|
||||
text
|
||||
|
|
|
@ -3,16 +3,33 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
import { Platform } from '../../base/react';
|
||||
import { translate, translateToHTML } from '../../base/translation';
|
||||
|
||||
import HideNotificationBarStyle from './HideNotificationBarStyle';
|
||||
|
||||
/**
|
||||
* The namespace of the CSS styles of UnsupportedMobileBrowser.
|
||||
*
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
const _SNS = 'unsupported-mobile-browser';
|
||||
|
||||
/**
|
||||
* The namespace of the i18n/translation keys of UnsupportedMobileBrowser.
|
||||
*
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
const _TNS = 'unsupportedBrowser';
|
||||
|
||||
/**
|
||||
* The map of platforms to URLs at which the mobile app for the associated
|
||||
* platform is available for download.
|
||||
*
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
const _URLS = {
|
||||
android: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
|
||||
|
@ -41,6 +58,13 @@ class UnsupportedMobileBrowser extends Component {
|
|||
* @type {string}
|
||||
*/
|
||||
_room: React.PropTypes.string,
|
||||
|
||||
/**
|
||||
* The function to translate human-readable text.
|
||||
*
|
||||
* @public
|
||||
* @type {Function}
|
||||
*/
|
||||
t: React.PropTypes.func
|
||||
}
|
||||
|
||||
|
@ -52,8 +76,7 @@ class UnsupportedMobileBrowser extends Component {
|
|||
*/
|
||||
componentWillMount() {
|
||||
const joinText
|
||||
= this.props._room ? 'unsupportedPage.joinConversation'
|
||||
: 'unsupportedPage.startConference';
|
||||
= this.props._room ? 'joinConversation' : 'startConference';
|
||||
|
||||
// If the user installed the app while this Component was displayed
|
||||
// (e.g. the user clicked the Download the App button), then we would
|
||||
|
@ -75,32 +98,36 @@ class UnsupportedMobileBrowser extends Component {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const ns = 'unsupported-mobile-browser';
|
||||
const downloadButtonClassName = `${ns}__button ${ns}__button_primary`;
|
||||
const { t } = this.props;
|
||||
|
||||
const downloadButtonClassName
|
||||
= `${_SNS}__button ${_SNS}__button_primary`;
|
||||
|
||||
return (
|
||||
<div className = { ns }>
|
||||
<div className = { `${ns}__body` }>
|
||||
<div className = { _SNS }>
|
||||
<div className = { `${_SNS}__body` }>
|
||||
<img
|
||||
className = { `${ns}__logo` }
|
||||
className = { `${_SNS}__logo` }
|
||||
src = 'images/logo-blue.svg' />
|
||||
<p className = { `${ns}__text` }>
|
||||
{ translateToHTML(t,
|
||||
'unsupportedPage.joinConversationMobile',
|
||||
{ postProcess: 'resolveAppName' }) }
|
||||
<p className = { `${_SNS}__text` }>
|
||||
{
|
||||
translateToHTML(
|
||||
t,
|
||||
`${_TNS}.appNotInstalled`,
|
||||
{ postProcess: 'resolveAppName' })
|
||||
}
|
||||
</p>
|
||||
<a href = { _URLS[Platform.OS] }>
|
||||
<button className = { downloadButtonClassName }>
|
||||
{ t('unsupportedPage.downloadApp') }
|
||||
{ t(`${_TNS}.downloadApp`) }
|
||||
</button>
|
||||
</a>
|
||||
<p className = { `${ns}__text ${ns}__text_small` }>
|
||||
{ translateToHTML(t, 'unsupportedPage.availableApp') }
|
||||
<p className = { `${_SNS}__text ${_SNS}__text_small` }>
|
||||
{ translateToHTML(t, `${_TNS}.appInstalled`) }
|
||||
</p>
|
||||
<a href = { this.state.joinURL }>
|
||||
<button className = { `${ns}__button` }>
|
||||
{ t(this.state.joinText) }
|
||||
<button className = { `${_SNS}__button` }>
|
||||
{ t(`${_TNS}.${this.state.joinText}`) }
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -2,14 +2,13 @@ import React from 'react';
|
|||
import { Text, TextInput, TouchableHighlight, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { Link } from '../../base/react';
|
||||
import { ColorPalette } from '../../base/styles';
|
||||
|
||||
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
||||
import { styles } from './styles';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
|
||||
/**
|
||||
* The URL at which the privacy policy is available to the user.
|
||||
*/
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { Watermarks } from '../../base/react';
|
||||
|
||||
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
||||
|
||||
import { translate } from '../../base/translation';
|
||||
|
||||
/* eslint-disable require-jsdoc */
|
||||
|
||||
/**
|
||||
|
@ -142,19 +141,17 @@ class WelcomePage extends AbstractWelcomePage {
|
|||
*/
|
||||
_renderFeature(index) {
|
||||
const { t } = this.props;
|
||||
const tns = `welcomepage.feature${index}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = 'feature_holder'
|
||||
key = { index } >
|
||||
<div
|
||||
className = 'feature_icon'>
|
||||
{ t(`welcomepage.feature${index}.title`) }
|
||||
<div className = 'feature_icon'>
|
||||
{ t(`${tns}.title`) }
|
||||
</div>
|
||||
<div
|
||||
className = 'feature_description'>
|
||||
{ t(`welcomepage.feature${index}.content`,
|
||||
{ postProcess: 'resolveAppName' }) }
|
||||
<div className = 'feature_description'>
|
||||
{ t(`${tns}.content`, { postProcess: 'resolveAppName' }) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
export default {
|
||||
getLanguages : function () {
|
||||
var languages = [];
|
||||
for (var lang in this)
|
||||
{
|
||||
if (typeof this[lang] === "string")
|
||||
languages.push(this[lang]);
|
||||
}
|
||||
return languages;
|
||||
},
|
||||
EN: "en",
|
||||
|
||||
BG: "bg",
|
||||
DE: "de",
|
||||
ES: "es",
|
||||
FR: "fr",
|
||||
HY: "hy",
|
||||
IT: "it",
|
||||
OC: "oc",
|
||||
PL: "pl",
|
||||
PTBR: "ptBR",
|
||||
RU: "ru",
|
||||
SK: "sk",
|
||||
SL: "sl",
|
||||
SV: "sv",
|
||||
TR: "tr"
|
||||
};
|
Loading…
Reference in New Issue