fix(translation) translation button visibility for users, add missing languages

This commit is contained in:
tamasdomokos 2022-09-29 14:44:59 +03:00 committed by GitHub
parent 69e0a37529
commit 8162ae4dbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 179 additions and 37 deletions

View File

@ -375,6 +375,14 @@ var config = {
// // Whether the feature should be enabled or not.
// enabled: false,
// // Translation languages.
// // Available languages can be found in
// // ./src/react/features/transcribing/translation-languages.json.
// translationLanguages: ['en', 'es', 'fr', 'ro'],
// // Important languages to show on the top of the language list.
// translationLanguagesHead: ['en'],
// // If true transcriber will use the application language.
// // The application language is either explicitly set by participants in their settings or automatically
// // detected based on the environment, e.g. if the app is opened in a chrome instance which
@ -1349,6 +1357,8 @@ var config = {
*/
mouseMoveCallbackInterval: 1000,
hiddenDomain: 'tdomokos.jitsi.net',
/**
Use this array to configure which notifications will be shown to the user
The items correspond to the title or description key of that notification

View File

@ -0,0 +1,111 @@
{
"af": "Afrikaans",
"am": "Amharic",
"ar": "Arabic",
"az": "Azerbaijani",
"be": "Belarusian",
"bg": "Bulgarian",
"bn": "Bengali",
"bs": "Bosnian",
"ca": "Catalan",
"ceb": "Cebuano",
"co": "Corsican",
"cs": "Czech",
"cy": "Welsh",
"da": "Danish",
"de": "German",
"el": "Greek",
"en": "English",
"eo": "Esperanto",
"es": "Spanish",
"et": "Estonian",
"eu": "Basque",
"fa": "Persian",
"fi": "Finnish",
"fr": "French",
"fy": "Frisian",
"ga": "Irish",
"gd": "Scots Gaelic",
"gl": "Galician",
"gu": "Gujarati",
"ha": "Hausa",
"haw": "Hawaiian",
"he": "Hebrew",
"hi": "Hindi",
"hmn": "Hmong",
"hr": "Croatian",
"ht": "Haitian Creole",
"hu": "Hungarian",
"hy": "Armenian",
"id": "Indonesian",
"ig": "Igbo",
"is": "Icelandic",
"it": "Italian",
"ja": "Japanese",
"jv": "Javanese",
"ka": "Georgian",
"kk": "Kazakh",
"km": "Khmer",
"kn": "Kannada",
"ko": "Korean",
"ku": "Kurdish",
"ky": "Kyrgyz",
"la": "Latin",
"lb": "Luxembourgish",
"lo": "Lao",
"lt": "Lithuanian",
"lv": "Latvian",
"mg": "Malagasy",
"mi": "Maori",
"mk": "Macedonian",
"ml": "Malayalam",
"mn": "Mongolian",
"mr": "Marathi",
"ms": "Malay",
"mt": "Maltese",
"my": "Myanmar (Burmese)",
"ne": "Nepali",
"nl": "Dutch",
"no": "Norwegian",
"ny": "Nyanja (Chichewa)",
"or": "Odia (Oriya)",
"pa": "Punjabi",
"pl": "Polish",
"ps": "Pashto",
"pt": "Portuguese (Portugal, Brazil)",
"ro": "Romanian",
"ru": "Russian",
"rw": "Kinyarwanda",
"sd": "Sindhi",
"si": "Sinhala (Sinhalese)",
"sk": "Slovak",
"sl": "Slovenian",
"sm": "Samoan",
"sn": "Shona",
"so": "Somali",
"sq": "Albanian",
"sr": "Serbian",
"st": "Sesotho",
"su": "Sundanese",
"sv": "Swedish",
"sw": "Swahili",
"ta": "Tamil",
"te": "Telugu",
"tg": "Tajik",
"th": "Thai",
"tk": "Turkmen",
"tl": "Tagalog (Filipino)",
"tr": "Turkish",
"tt": "Tatar",
"ug": "Uyghur",
"uk": "Ukrainian",
"ur": "Urdu",
"uz": "Uzbek",
"vi": "Vietnamese",
"xh": "Xhosa",
"yi": "Yiddish",
"yo": "Yoruba",
"zh-CN": "Chinese (Simplified)",
"zh-TW": "Chinese (Traditional)",
"zu": "Zulu"
}

View File

@ -464,6 +464,8 @@ export interface IConfig {
disableStartForAll?: boolean;
enabled?: boolean;
preferredLanguage?: string;
translationLanguages?: Array<string>;
translationLanguagesHead?: Array<string>;
useAppLanguage?: boolean;
};
useHostPageLocalStorage?: boolean;

View File

@ -7,6 +7,7 @@ import _ from 'lodash';
import LANGUAGES_RESOURCES from '../../../../lang/languages.json';
import MAIN_RESOURCES from '../../../../lang/main.json';
import TRANSLATION_LANGUAGES_RESOURCES from '../../../../lang/translation-languages.json';
import { I18NEXT_INITIALIZED, LANGUAGE_CHANGED } from './actionTypes';
// eslint-disable-next-line lines-around-comment
@ -36,22 +37,21 @@ const COUNTRIES = _.merge({}, COUNTRIES_RESOURCES, COUNTRIES_RESOURCES_OVERRIDES
export const LANGUAGES: Array<string> = Object.keys(LANGUAGES_RESOURCES);
/**
* The languages for the top section of the translation language list.
* The available/supported translation languages.
*
* @public
* @type {Array<string>}
*/
export const TRANSLATION_LANGUAGES: Array<string> = Object.keys(TRANSLATION_LANGUAGES_RESOURCES);
/**
* The available/supported translation languages head. (Languages displayed on the top ).
*
* @public
* @type {Array<string>}
*/
export const TRANSLATION_LANGUAGES_HEAD: Array<string> = [ 'en' ];
/**
* The languages to explude from the translation language list.
*
* @public
* @type {Array<string>}
*/
export const TRANSLATION_LANGUAGES_EXCLUDE: Array<string>
= [ 'enGB', 'esUS', 'frCA', 'hsb', 'kab', 'ptBR', 'zhCN', 'zhTW' ];
/**
* The default language.
*
@ -77,7 +77,7 @@ const options = {
escapeValue: false // not needed for react as it escapes by default
},
load: 'languageOnly',
ns: [ 'main', 'languages', 'countries' ],
ns: [ 'main', 'languages', 'countries', 'translation-languages' ],
react: {
// re-render when a new resource bundle is added
bindI18nStore: 'added',
@ -109,6 +109,12 @@ i18next.addResourceBundle(
LANGUAGES_RESOURCES,
/* deep */ true,
/* overwrite */ true);
i18next.addResourceBundle(
DEFAULT_LANGUAGE,
'translation-languages',
TRANSLATION_LANGUAGES_RESOURCES,
/* deep */ true,
/* overwrite */ true);
i18next.addResourceBundle(
DEFAULT_LANGUAGE,
'main',

View File

@ -4,4 +4,4 @@ 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, DEFAULT_LANGUAGE,
LANGUAGES, TRANSLATION_LANGUAGES_HEAD, TRANSLATION_LANGUAGES_EXCLUDE } from './i18next';
LANGUAGES, TRANSLATION_LANGUAGES, TRANSLATION_LANGUAGES_HEAD, i18n } from './i18next';

View File

@ -11,7 +11,7 @@ export * from './actions.any';
* type: UPDATE_TRANSLATION_LANGUAGE
* }}
*/
export function toggleLangugeSelectorDialog() {
export function toggleLanguageSelectorDialog() {
return function(dispatch: (Object) => Object) {
dispatch(toggleDialog(LanguageSelectorDialogWeb));
};

View File

@ -3,7 +3,7 @@
import { translate } from '../../base/i18n';
import { IconClosedCaption } from '../../base/icons';
import { connect } from '../../base/redux';
import { toggleLangugeSelectorDialog } from '../actions';
import { toggleLanguageSelectorDialog } from '../actions';
import {
AbstractClosedCaptionButton,
@ -20,7 +20,9 @@ class ClosedCaptionButton
tooltip = 'transcribing.ccButtonTooltip';
label = 'toolbar.startSubtitles';
labelProps = {
language: this.props.t(this.props._language)
language: this.props.t(this.props._language),
languages: this.props.t(this.props.languages),
languagesHead: this.props.t(this.props.languagesHead)
};
/**
@ -31,7 +33,7 @@ class ClosedCaptionButton
_handleClickOpenLanguageSelector() {
const { dispatch } = this.props;
dispatch(toggleLangugeSelectorDialog());
dispatch(toggleLanguageSelectorDialog());
}
}

View File

@ -31,7 +31,11 @@ const useStyles = makeStyles()((theme: Theme) => {
display: 'flex',
color: theme.palette.text01,
alignItems: 'center',
fontSize: '14px'
fontSize: '14px',
cursor: 'pointer',
'&:hover': {
backgroundColor: theme.palette.ui04
}
},
iconWrapper: {
margin: '4px 10px',

View File

@ -6,15 +6,17 @@ import { IState } from '../../app/types';
// @ts-ignore
import { Dialog } from '../../base/dialog';
// @ts-ignore
import { LANGUAGES, TRANSLATION_LANGUAGES_EXCLUDE, TRANSLATION_LANGUAGES_HEAD } from '../../base/i18n';
import { TRANSLATION_LANGUAGES, TRANSLATION_LANGUAGES_HEAD } from '../../base/i18n';
import { connect } from '../../base/redux/functions';
// @ts-ignore
import { setRequestingSubtitles, toggleLangugeSelectorDialog, updateTranslationLanguage } from '../actions';
import { setRequestingSubtitles, toggleLanguageSelectorDialog, updateTranslationLanguage } from '../actions';
import LanguageList from './LanguageList';
interface ILanguageSelectorDialogProps {
_language: string;
_translationLanguages: Array<string>;
_translationLanguagesHead: Array<string>;
t: Function;
}
@ -23,18 +25,21 @@ interface ILanguageSelectorDialogProps {
*
* @returns {React$Element<any>}
*/
const LanguageSelectorDialog = ({ _language }: ILanguageSelectorDialogProps) => {
const LanguageSelectorDialog = ({ _language, _translationLanguages, _translationLanguagesHead }:
ILanguageSelectorDialogProps) => {
const dispatch = useDispatch();
const off = 'transcribing.subtitlesOff';
const [ language, setLanguage ] = useState(off);
const importantLanguages = TRANSLATION_LANGUAGES_HEAD.map((lang: string) => `languages:${lang}`);
const fixedItems = [ off, ...importantLanguages ];
const languages = LANGUAGES
.filter((lang: string) => !TRANSLATION_LANGUAGES_EXCLUDE.includes(lang))
.map((lang: string) => `languages:${lang}`)
.filter((lang: string) => !(lang === language || importantLanguages.includes(lang)));
const languagesHead = _translationLanguagesHead.map((lang: string) => `translation-languages:${lang}`);
// The off and the head languages are always on the top of the list. But once you are selecting
// a language from the translationLanguages, that language is moved under the fixedItems list,
// until a new languages is selected. FixedItems keep their positions.
const fixedItems = [ off, ...languagesHead ];
const languages = _translationLanguages
.map((lang: string) => `translation-languages:${lang}`)
.filter((lang: string) => !(lang === language || languagesHead.includes(lang)));
const listItems = (fixedItems.includes(language)
? [ ...fixedItems, ...languages ]
@ -55,7 +60,7 @@ const LanguageSelectorDialog = ({ _language }: ILanguageSelectorDialogProps) =>
setLanguage(e);
dispatch(updateTranslationLanguage(e));
dispatch(setRequestingSubtitles(e !== off));
dispatch(toggleLangugeSelectorDialog());
dispatch(toggleLanguageSelectorDialog());
}, [ _language ]);
return (
@ -81,17 +86,18 @@ const LanguageSelectorDialog = ({ _language }: ILanguageSelectorDialogProps) =>
* @returns {Props}
*/
function mapStateToProps(state: IState) {
const {
conference
} = state['features/base/conference'];
const { conference } = state['features/base/conference'];
const { _language } = state['features/subtitles'];
const { transcription } = state['features/base/config'];
const {
_language
} = state['features/subtitles'];
const languages = transcription?.translationLanguages ?? TRANSLATION_LANGUAGES;
const languagesHead = transcription?.translationLanguagesHead ?? TRANSLATION_LANGUAGES_HEAD;
return {
_conference: conference,
_language
_language,
_translationLanguages: languages,
_translationLanguagesHead: languagesHead
};
}

View File

@ -1,4 +1,5 @@
// @flow
import i18next from 'i18next';
import { MiddlewareRegistry } from '../base/redux';
@ -115,7 +116,7 @@ function _endpointMessageReceived({ dispatch, getState }, next, action) {
newTranscriptMessage));
} else if (json.type === JSON_TYPE_TRANSCRIPTION_RESULT
&& !translationLanguage) {
&& i18next.language === translationLanguage) {
// Displays interim and final results without any translation if
// translations are disabled.
@ -186,7 +187,7 @@ function _requestingSubtitlesChange({ getState }) {
if (requestingSubtitles) {
conference.setLocalParticipantProperty(
P_NAME_TRANSLATION_LANGUAGE,
_language.replace('languages:', ''));
_language.replace('translation-languages:', ''));
}
}