Comply w/ coding style
This commit is contained in:
parent
c361e1e31a
commit
18368fefaa
|
@ -5,8 +5,14 @@ debian/
|
||||||
libs/
|
libs/
|
||||||
node_modules/
|
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/
|
flow-typed/
|
||||||
react/
|
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
|
analytics.js
|
||||||
|
|
|
@ -39,44 +39,44 @@
|
||||||
"videoMute": "Start or stop your camera"
|
"videoMute": "Start or stop your camera"
|
||||||
},
|
},
|
||||||
"welcomepage":{
|
"welcomepage":{
|
||||||
"go": "GO",
|
|
||||||
"join": "JOIN",
|
|
||||||
"roomname": "Enter room name",
|
|
||||||
"roomnamePlaceHolder": "room name",
|
|
||||||
"disable": "Don't show this page again",
|
"disable": "Don't show this page again",
|
||||||
"feature1": {
|
"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": {
|
"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": {
|
"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": {
|
"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": {
|
"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": {
|
"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": {
|
"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": {
|
"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",
|
"privacy": "Privacy",
|
||||||
|
"roomname": "Enter room name",
|
||||||
|
"roomnamePlaceHolder": "room name",
|
||||||
"sendFeedback": "Send feedback",
|
"sendFeedback": "Send feedback",
|
||||||
"terms": "Terms"
|
"terms": "Terms"
|
||||||
},
|
},
|
||||||
|
@ -115,14 +115,12 @@
|
||||||
"profile": "Edit your profile",
|
"profile": "Edit your profile",
|
||||||
"raiseHand": "Raise / Lower your hand"
|
"raiseHand": "Raise / Lower your hand"
|
||||||
},
|
},
|
||||||
"unsupportedPage": {
|
"unsupportedBrowser": {
|
||||||
"onlySupportedBy": "This application is currently only supported by",
|
"appInstalled": "or if you already have it<br /><strong>then</strong>",
|
||||||
"download": "DOWNLOAD",
|
"appNotInstalled": "You need <strong>__app__</strong> to join a conversation on your mobile",
|
||||||
"joinConversation": "Join the conversation",
|
|
||||||
"startConference": "Start a conference",
|
|
||||||
"joinConversationMobile": "You need <strong>__app__</strong> to join a conversation on your mobile",
|
|
||||||
"downloadApp": "Download the App",
|
"downloadApp": "Download the App",
|
||||||
"availableApp": "or if you already have it<br /><strong>then</strong>"
|
"joinConversation": "Join the conversation",
|
||||||
|
"startConference": "Start a conference"
|
||||||
},
|
},
|
||||||
"bottomtoolbar": {
|
"bottomtoolbar": {
|
||||||
"chat": "Open / close chat",
|
"chat": "Open / close chat",
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/* global $, APP, AJS, interfaceConfig, JitsiMeetJS */
|
/* global $, APP, AJS, interfaceConfig, JitsiMeetJS */
|
||||||
|
|
||||||
|
import { LANGUAGES } from "../../../../react/features/base/i18n";
|
||||||
|
|
||||||
import UIUtil from "../../util/UIUtil";
|
import UIUtil from "../../util/UIUtil";
|
||||||
import UIEvents from "../../../../service/UI/UIEvents";
|
import UIEvents from "../../../../service/UI/UIEvents";
|
||||||
import languages from "../../../../service/translation/languages";
|
|
||||||
import Settings from '../../../settings/Settings';
|
import Settings from '../../../settings/Settings';
|
||||||
|
|
||||||
const sidePanelsContainerId = 'sideToolbarContainer';
|
const sidePanelsContainerId = 'sideToolbarContainer';
|
||||||
|
@ -145,7 +146,7 @@ export default {
|
||||||
let selectInput;
|
let selectInput;
|
||||||
|
|
||||||
selectEl.html(generateLanguagesOptions(
|
selectEl.html(generateLanguagesOptions(
|
||||||
languages.getLanguages(),
|
LANGUAGES,
|
||||||
APP.translation.getCurrentLanguage()
|
APP.translation.getCurrentLanguage()
|
||||||
));
|
));
|
||||||
initSelect2(selectEl, () => {
|
initSelect2(selectEl, () => {
|
||||||
|
|
|
@ -1,46 +1,56 @@
|
||||||
/* global $ */
|
/* @flow */
|
||||||
import { i18n, DEFAULT_LANG } from '../../react/features/base/translation';
|
|
||||||
import jqueryI18next from 'jquery-i18next';
|
import jqueryI18next from 'jquery-i18next';
|
||||||
|
|
||||||
function initCompleted() {
|
import { DEFAULT_LANGUAGE, i18next } from '../../react/features/base/i18n';
|
||||||
$("[data-i18n]").localize();
|
|
||||||
|
declare var $: Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies that the {@link i18next} instance has finished its initialization.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function _onI18nInitialized() {
|
||||||
|
$('[data-i18n]').localize();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Translation {
|
class Translation {
|
||||||
init () {
|
addLanguageChangedListener(listener: Function) {
|
||||||
if (i18n.isInitialized)
|
i18next.on('languageChanged', listener);
|
||||||
initCompleted();
|
|
||||||
else
|
|
||||||
i18n.on('initialized', initCompleted);
|
|
||||||
|
|
||||||
jqueryI18next.init(i18n, $, {useOptionsAttr: true});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setLanguage (lang) {
|
generateTranslationHTML(key: string, options: Object) {
|
||||||
if(!lang)
|
const optAttr
|
||||||
lang = DEFAULT_LANG;
|
= options ? ` data-i18n-options='${JSON.stringify(options)}'` : '';
|
||||||
i18n.setLng(lang, {}, initCompleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentLanguage () {
|
// XXX i18next expects undefined if options are missing.
|
||||||
return i18n.lng();
|
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>`;
|
return `<span data-i18n="${key}"${optAttr}>${text}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
addLanguageChangedListener(listener) {
|
getCurrentLanguage() {
|
||||||
i18n.on('languageChanged', listener);
|
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-background-timer": "1.0.0",
|
||||||
"react-native-immersive": "0.0.4",
|
"react-native-immersive": "0.0.4",
|
||||||
"react-native-keep-awake": "^2.0.2",
|
"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-prompt": "^1.0.0",
|
||||||
"react-native-vector-icons": "^4.0.0",
|
"react-native-vector-icons": "^4.0.0",
|
||||||
"react-native-webrtc": "jitsi/react-native-webrtc",
|
"react-native-webrtc": "jitsi/react-native-webrtc",
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
/* global APP */
|
/* global APP */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { compose, createStore } from 'redux';
|
import { compose, createStore } from 'redux';
|
||||||
import Thunk from 'redux-thunk';
|
import Thunk from 'redux-thunk';
|
||||||
|
|
||||||
import { I18nextProvider } from 'react-i18next';
|
import { i18next } from '../../base/i18n';
|
||||||
import { i18n } from '../../base/translation';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
localParticipantJoined,
|
localParticipantJoined,
|
||||||
localParticipantLeft
|
localParticipantLeft
|
||||||
|
@ -137,7 +136,7 @@ export class AbstractApp extends Component {
|
||||||
|
|
||||||
if (route) {
|
if (route) {
|
||||||
return (
|
return (
|
||||||
<I18nextProvider i18n = { i18n }>
|
<I18nextProvider i18n = { i18next }>
|
||||||
<Provider store = { this._getStore() }>
|
<Provider store = { this._getStore() }>
|
||||||
{
|
{
|
||||||
this._createElement(route.component)
|
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.
|
* Custom language detection, just returns the config property if any.
|
||||||
*/
|
*/
|
||||||
export default {
|
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.
|
* @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 */
|
/* @flow */
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { translate } from '../../translation';
|
|
||||||
|
import { translate } from '../../i18n';
|
||||||
|
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
declare var interfaceConfig: 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,
|
* A Web Component which renders watermarks such as Jits, brand, powered by,
|
||||||
* etc.
|
* etc.
|
||||||
*/
|
*/
|
||||||
class WatermarksComponent extends Component {
|
class Watermarks extends Component {
|
||||||
state = {
|
state = {
|
||||||
brandWatermarkLink: String,
|
brandWatermarkLink: String,
|
||||||
jitsiWatermarkLink: String,
|
jitsiWatermarkLink: String,
|
||||||
|
@ -147,7 +148,7 @@ class WatermarksComponent extends Component {
|
||||||
className = 'poweredby'
|
className = 'poweredby'
|
||||||
href = 'http://jitsi.org'
|
href = 'http://jitsi.org'
|
||||||
target = '_new'>
|
target = '_new'>
|
||||||
<span>{t('poweredby')} jitsi.org</span>
|
<span>{ t('poweredby') } jitsi.org</span>
|
||||||
</a>
|
</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 './Container';
|
||||||
export * from './Link';
|
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 { connect } from 'react-redux';
|
||||||
|
|
||||||
import { setPassword } from '../../base/conference';
|
import { setPassword } from '../../base/conference';
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { translate } from '../../base/translation';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements a React Component which prompts the user when a password is
|
* Implements a React Component which prompts the user when a password is
|
||||||
|
@ -24,6 +23,13 @@ class PasswordRequiredPrompt extends Component {
|
||||||
*/
|
*/
|
||||||
conference: React.PropTypes.object,
|
conference: React.PropTypes.object,
|
||||||
dispatch: React.PropTypes.func,
|
dispatch: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to translate human-readable text.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
t: React.PropTypes.func
|
t: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { randomInt } from '../../base/util';
|
import { randomInt } from '../../base/util';
|
||||||
|
|
||||||
import AbstractOverlay from './AbstractOverlay';
|
import AbstractOverlay from './AbstractOverlay';
|
||||||
import ReloadTimer from './ReloadTimer';
|
import ReloadTimer from './ReloadTimer';
|
||||||
|
|
||||||
import { translate } from '../../base/translation';
|
|
||||||
|
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
|
|
||||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import { translate } from '../../base/translation';
|
import { translate } from '../../base/i18n';
|
||||||
|
|
||||||
declare var AJS: Object;
|
declare var AJS: Object;
|
||||||
|
|
||||||
|
@ -57,10 +57,10 @@ class ReloadTimer extends Component {
|
||||||
step: React.PropTypes.number,
|
step: React.PropTypes.number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The function used to translate strings.
|
* The function to translate human-readable text.
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
* @type {func}
|
* @type {Function}
|
||||||
*/
|
*/
|
||||||
t: React.PropTypes.func
|
t: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
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
|
* Implements a React Component for suspended overlay. Shown when a suspend is
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
import React from 'react';
|
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
|
* Implements a React Component for overlay with guidance how to proceed with
|
||||||
|
@ -56,7 +56,7 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
_renderOverlayContent() {
|
_renderOverlayContent() {
|
||||||
const { t } = this.props;
|
const { browser, t } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -64,12 +64,18 @@ class UserMediaPermissionsOverlay extends AbstractOverlay {
|
||||||
<span className = 'inlay__icon icon-microphone' />
|
<span className = 'inlay__icon icon-microphone' />
|
||||||
<span className = 'inlay__icon icon-camera' />
|
<span className = 'inlay__icon icon-camera' />
|
||||||
<h3 className = 'inlay__title'>
|
<h3 className = 'inlay__title'>
|
||||||
{ t('startupoverlay.title',
|
{
|
||||||
{ postProcess: 'resolveAppName' }) }
|
t(
|
||||||
|
'startupoverlay.title',
|
||||||
|
{ postProcess: 'resolveAppName' })
|
||||||
|
}
|
||||||
</h3>
|
</h3>
|
||||||
<span className = 'inlay__text'>
|
<span className = 'inlay__text'>
|
||||||
{ translateToHTML(t,
|
{
|
||||||
`userMedia.${this.props.browser}GrantPermissions`)}
|
translateToHTML(
|
||||||
|
t,
|
||||||
|
`userMedia.${browser}GrantPermissions`)
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className = 'policy overlay__policy'>
|
<div className = 'policy overlay__policy'>
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from 'react';
|
||||||
import Prompt from 'react-native-prompt';
|
import Prompt from 'react-native-prompt';
|
||||||
import { connect } from 'react-redux';
|
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
|
* 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,
|
conference: React.PropTypes.object,
|
||||||
dispatch: React.PropTypes.func,
|
dispatch: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to translate human-readable text.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
t: React.PropTypes.func
|
t: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { Platform } from '../../base/react';
|
import { Platform } from '../../base/react';
|
||||||
import { translate } from '../../base/translation';
|
|
||||||
|
|
||||||
import { CHROME, FIREFOX, IE, SAFARI } from './browserLinks';
|
import { CHROME, FIREFOX, IE, SAFARI } from './browserLinks';
|
||||||
import HideNotificationBarStyle from './HideNotificationBarStyle';
|
import HideNotificationBarStyle from './HideNotificationBarStyle';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CSS style namespace of UnsupportedDesktopBrowser.
|
* The namespace of the CSS styles of UnsupportedDesktopBrowser.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
const _NS = 'unsupported-desktop-browser';
|
const _SNS = 'unsupported-desktop-browser';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React component representing unsupported browser page.
|
* React component representing unsupported browser page.
|
||||||
|
@ -28,6 +28,12 @@ class UnsupportedDesktopBrowser extends Component {
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
/**
|
||||||
|
* The function to translate human-readable text.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
t: React.PropTypes.func
|
t: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,17 +44,17 @@ class UnsupportedDesktopBrowser extends Component {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className = { _NS }>
|
<div className = { _SNS }>
|
||||||
<h2 className = { `${_NS}__title` }>
|
<h2 className = { `${_SNS}__title` }>
|
||||||
It looks like you're using a browser we don't support.
|
It looks like you're using a browser we don't support.
|
||||||
</h2>
|
</h2>
|
||||||
<p className = { `${_NS}__description` }>
|
<p className = { `${_SNS}__description` }>
|
||||||
Please try again with the latest version of
|
Please try again with the latest version of
|
||||||
<a
|
<a
|
||||||
className = { `${_NS}__link` }
|
className = { `${_SNS}__link` }
|
||||||
href = { CHROME } >Chrome</a>,
|
href = { CHROME } >Chrome</a>,
|
||||||
<a
|
<a
|
||||||
className = { `${_NS}__link` }
|
className = { `${_SNS}__link` }
|
||||||
href = { FIREFOX }>Firefox</a> or
|
href = { FIREFOX }>Firefox</a> or
|
||||||
{
|
{
|
||||||
this._renderOSSpecificBrowserDownloadLink()
|
this._renderOSSpecificBrowserDownloadLink()
|
||||||
|
@ -84,7 +90,7 @@ class UnsupportedDesktopBrowser extends Component {
|
||||||
if (typeof link !== 'undefined') {
|
if (typeof link !== 'undefined') {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className = { `${_NS}__link` }
|
className = { `${_SNS}__link` }
|
||||||
href = { link }>
|
href = { link }>
|
||||||
{
|
{
|
||||||
text
|
text
|
||||||
|
|
|
@ -3,16 +3,33 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { translate, translateToHTML } from '../../base/i18n';
|
||||||
import { Platform } from '../../base/react';
|
import { Platform } from '../../base/react';
|
||||||
import { translate, translateToHTML } from '../../base/translation';
|
|
||||||
|
|
||||||
import HideNotificationBarStyle from './HideNotificationBarStyle';
|
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
|
* The map of platforms to URLs at which the mobile app for the associated
|
||||||
* platform is available for download.
|
* platform is available for download.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
|
* @type {Array<string>}
|
||||||
*/
|
*/
|
||||||
const _URLS = {
|
const _URLS = {
|
||||||
android: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
|
android: 'https://play.google.com/store/apps/details?id=org.jitsi.meet',
|
||||||
|
@ -41,6 +58,13 @@ class UnsupportedMobileBrowser extends Component {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
_room: React.PropTypes.string,
|
_room: React.PropTypes.string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to translate human-readable text.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
t: React.PropTypes.func
|
t: React.PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +76,7 @@ class UnsupportedMobileBrowser extends Component {
|
||||||
*/
|
*/
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const joinText
|
const joinText
|
||||||
= this.props._room ? 'unsupportedPage.joinConversation'
|
= this.props._room ? 'joinConversation' : 'startConference';
|
||||||
: 'unsupportedPage.startConference';
|
|
||||||
|
|
||||||
// If the user installed the app while this Component was displayed
|
// If the user installed the app while this Component was displayed
|
||||||
// (e.g. the user clicked the Download the App button), then we would
|
// (e.g. the user clicked the Download the App button), then we would
|
||||||
|
@ -75,32 +98,36 @@ class UnsupportedMobileBrowser extends Component {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const ns = 'unsupported-mobile-browser';
|
|
||||||
const downloadButtonClassName = `${ns}__button ${ns}__button_primary`;
|
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
|
||||||
|
const downloadButtonClassName
|
||||||
|
= `${_SNS}__button ${_SNS}__button_primary`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className = { ns }>
|
<div className = { _SNS }>
|
||||||
<div className = { `${ns}__body` }>
|
<div className = { `${_SNS}__body` }>
|
||||||
<img
|
<img
|
||||||
className = { `${ns}__logo` }
|
className = { `${_SNS}__logo` }
|
||||||
src = 'images/logo-blue.svg' />
|
src = 'images/logo-blue.svg' />
|
||||||
<p className = { `${ns}__text` }>
|
<p className = { `${_SNS}__text` }>
|
||||||
{ translateToHTML(t,
|
{
|
||||||
'unsupportedPage.joinConversationMobile',
|
translateToHTML(
|
||||||
{ postProcess: 'resolveAppName' }) }
|
t,
|
||||||
|
`${_TNS}.appNotInstalled`,
|
||||||
|
{ postProcess: 'resolveAppName' })
|
||||||
|
}
|
||||||
</p>
|
</p>
|
||||||
<a href = { _URLS[Platform.OS] }>
|
<a href = { _URLS[Platform.OS] }>
|
||||||
<button className = { downloadButtonClassName }>
|
<button className = { downloadButtonClassName }>
|
||||||
{ t('unsupportedPage.downloadApp') }
|
{ t(`${_TNS}.downloadApp`) }
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<p className = { `${ns}__text ${ns}__text_small` }>
|
<p className = { `${_SNS}__text ${_SNS}__text_small` }>
|
||||||
{ translateToHTML(t, 'unsupportedPage.availableApp') }
|
{ translateToHTML(t, `${_TNS}.appInstalled`) }
|
||||||
</p>
|
</p>
|
||||||
<a href = { this.state.joinURL }>
|
<a href = { this.state.joinURL }>
|
||||||
<button className = { `${ns}__button` }>
|
<button className = { `${_SNS}__button` }>
|
||||||
{ t(this.state.joinText) }
|
{ t(`${_TNS}.${this.state.joinText}`) }
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,14 +2,13 @@ import React from 'react';
|
||||||
import { Text, TextInput, TouchableHighlight, View } from 'react-native';
|
import { Text, TextInput, TouchableHighlight, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { Link } from '../../base/react';
|
import { Link } from '../../base/react';
|
||||||
import { ColorPalette } from '../../base/styles';
|
import { ColorPalette } from '../../base/styles';
|
||||||
|
|
||||||
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
||||||
import { styles } from './styles';
|
import { styles } from './styles';
|
||||||
|
|
||||||
import { translate } from '../../base/translation';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The URL at which the privacy policy is available to the user.
|
* The URL at which the privacy policy is available to the user.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { translate } from '../../base/i18n';
|
||||||
import { Watermarks } from '../../base/react';
|
import { Watermarks } from '../../base/react';
|
||||||
|
|
||||||
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
|
||||||
|
|
||||||
import { translate } from '../../base/translation';
|
|
||||||
|
|
||||||
/* eslint-disable require-jsdoc */
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,19 +141,17 @@ class WelcomePage extends AbstractWelcomePage {
|
||||||
*/
|
*/
|
||||||
_renderFeature(index) {
|
_renderFeature(index) {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
const tns = `welcomepage.feature${index}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className = 'feature_holder'
|
className = 'feature_holder'
|
||||||
key = { index } >
|
key = { index } >
|
||||||
<div
|
<div className = 'feature_icon'>
|
||||||
className = 'feature_icon'>
|
{ t(`${tns}.title`) }
|
||||||
{ t(`welcomepage.feature${index}.title`) }
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className = 'feature_description'>
|
||||||
className = 'feature_description'>
|
{ t(`${tns}.content`, { postProcess: 'resolveAppName' }) }
|
||||||
{ t(`welcomepage.feature${index}.content`,
|
|
||||||
{ postProcess: 'resolveAppName' }) }
|
|
||||||
</div>
|
</div>
|
||||||
</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