Compare commits

...

1 Commits

Author SHA1 Message Date
paweldomas
855eeafc79 feat(accessibility): set html 'lang' attribute
...to match the currently selected language. Starts with
'en' by default.
2020-04-03 18:23:21 -05:00
7 changed files with 145 additions and 3 deletions

View File

@@ -1,4 +1,4 @@
<html itemscope itemtype="http://schema.org/Product" prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/html">
<html itemscope itemtype="http://schema.org/Product" lang="en" prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/html">
<head>
<!--#include virtual="head.html" -->
<meta charset="utf-8">

View File

@@ -0,0 +1,6 @@
/**
* See {@link _setLanguage}.
*
* @type {string}
*/
export const SET_LANGUAGE = 'SET_LANGUAGE';

View File

@@ -0,0 +1,33 @@
// @flow
import { i18next } from './index';
import { SET_LANGUAGE } from './actionTypes';
/**
* Makes an attempt to change the language.
*
* @param {string} newLanguage - The new language code which identifies
* the language to be set.
* @returns {Function}
*/
export function changeLanguage(newLanguage: string): Function {
return function(dispatch: (Object) => Object) {
return i18next.changeLanguage(newLanguage)
.then(() => {
dispatch(_setLanguage(i18next.language));
});
};
}
/**
* Sets the current language on the Redux store.
*
* @param {string} language - The new language code that will be stored.
* @returns {Object}
* @private
*/
export function _setLanguage(language: string): Object {
return {
type: SET_LANGUAGE,
language
};
}

View File

@@ -1,6 +1,10 @@
export * from './actions';
export * from './dateUtil';
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 } from './i18next';
import './middleware';
import './reducer';

View File

@@ -0,0 +1,69 @@
/* @flow */
/* global document */
import i18next from 'i18next';
import { APP_WILL_MOUNT } from '../app';
import { MiddlewareRegistry } from '../redux';
import { SET_LANGUAGE } from './actionTypes';
import { _setLanguage } from './actions';
/**
* The Redux middleware of the feature base/i18n.
*
* @param {Store} store - The Redux store.
* @returns {Function}
* @private
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case APP_WILL_MOUNT:
return _appWillMount(store, next, action);
case SET_LANGUAGE:
return handleSetLanguage(store, next, action);
}
return next(action);
});
/**
* Side effects for {@link APP_WILL_MOUNT}.
*
* @param {Store} store - The Redux store in which the specified {@code action}
* is being dispatched.
* @param {Dispatch} next - The Redux {@code dispatch} function to dispatch the
* specified {@code action} to the specified {@code store}.
* @param {Action} action - The Redux action {@code APP_WILL_MOUNT} which is
* being dispatched in the specified {@code store}.
* @private
* @returns {Object} The new state that is the result of the reduction of the
* specified {@code action}.
*/
function _appWillMount({ dispatch }, next, action) {
if (i18next.language) {
dispatch(_setLanguage(i18next.language));
} else {
i18next.on('initialized', () => {
dispatch(_setLanguage(i18next.language));
});
}
return next(action);
}
/**
* Side effects for the {@link SET_LANGUAGE} action.
*
* @param {Store} store - The Redux store in which the specified {@code action}
* is being dispatched.
* @param {Dispatch} next - The Redux {@code dispatch} function to dispatch the
* specified {@code action} to the specified {@code store}.
* @param {Action} action - The Redux action {@code SET_LANGUAGE} which is
* being dispatched in the specified {@code store}.
* @returns {*}
*/
function handleSetLanguage(store, next, action) {
document && document.documentElement && document.documentElement.setAttribute('lang', action.language);
return next(action);
}

View File

@@ -0,0 +1,30 @@
// @flow
import { ReducerRegistry, set } from '../redux';
import {
SET_LANGUAGE
} from './actionTypes';
import { DEFAULT_LANGUAGE } from './i18next';
/**
* The default/initial redux state of the feature base/i18n.
*
* @type {{
* language: string
* }}
*/
const DEFAULT_STATE = {
language: DEFAULT_LANGUAGE
};
ReducerRegistry.register(
'features/base/i18n',
(state = DEFAULT_STATE, action) => {
switch (action.type) {
case SET_LANGUAGE:
return set(state, 'language', action.language);
default:
return state;
}
});

View File

@@ -2,7 +2,7 @@
import { setFollowMe, setStartMutedPolicy } from '../base/conference';
import { openDialog } from '../base/dialog';
import { i18next } from '../base/i18n';
import { changeLanguage } from '../base/i18n';
import {
SET_AUDIO_SETTINGS_VISIBILITY,
@@ -89,7 +89,7 @@ export function submitMoreTab(newState: Object): Function {
}
if (newState.currentLanguage !== currentState.currentLanguage) {
i18next.changeLanguage(newState.currentLanguage);
dispatch(changeLanguage(newState.currentLanguage));
}
};
}