diff --git a/src/service/localization.js b/src/service/localization.js index 4f20d3c992ae..48e153d90678 100644 --- a/src/service/localization.js +++ b/src/service/localization.js @@ -18,6 +18,7 @@ // LocalizedStringId enum values and any other strings. // eslint-disable-next-line no-unused-vars import {LocalizedStringId} from '../localized-strings'; +import {Services} from '../services'; import {closest} from '../dom'; /** @@ -94,6 +95,11 @@ export class LocalizationService { constructor(element) { this.element_ = element; + /** + * @private @const {?string} + */ + this.viewerLanguageCode_ = Services.viewerForDoc(element).getParam('lang'); + /** * A mapping of language code to localized string bundle. * @private @const {!Object} @@ -109,7 +115,13 @@ export class LocalizationService { getLanguageCodesForElement_(element) { const languageEl = closest(element, (el) => el.hasAttribute('lang')); const languageCode = languageEl ? languageEl.getAttribute('lang') : null; - return getLanguageCodesFromString(languageCode || ''); + const languageCodesToUse = getLanguageCodesFromString(languageCode || ''); + + if (this.viewerLanguageCode_) { + languageCodesToUse.unshift(this.viewerLanguageCode_); + } + + return languageCodesToUse; } /** diff --git a/test/unit/test-localization.js b/test/unit/test-localization.js index 0ae26975610a..a4d7dedeecc7 100644 --- a/test/unit/test-localization.js +++ b/test/unit/test-localization.js @@ -22,6 +22,7 @@ import { LocalizedStringId, createPseudoLocale, } from '../../src/localized-strings'; +import {Services} from '../../src/services'; describes.fakeWin('localization', {amp: true}, (env) => { let win; @@ -164,3 +165,65 @@ describes.fakeWin('localization', {amp: true}, (env) => { }); }); }); + +describes.fakeWin('viewer localization', {amp: true}, (env) => { + describe('viewer language override', () => { + let win; + + beforeEach(() => { + win = env.win; + env.sandbox + .stub(Services.viewerForDoc(env.ampdoc), 'getParam') + .returns('fr'); + }); + + it('should take precedence over document language', () => { + const localizationService = new LocalizationService(win.document.body); + localizationService.registerLocalizedStringBundle('fr', { + 'test_string_id': { + string: 'oui', + }, + }); + localizationService.registerLocalizedStringBundle('en', { + 'test_string_id': { + string: 'yes', + }, + }); + + expect(localizationService.getLocalizedString('test_string_id')).to.equal( + 'oui' + ); + }); + + it('should fall back if string is not found', () => { + const localizationService = new LocalizationService(win.document.body); + localizationService.registerLocalizedStringBundle('fr', { + 'incorrect_test_string_id': { + string: 'non', + }, + }); + localizationService.registerLocalizedStringBundle('en', { + 'correct_test_string_id': { + string: 'yes', + }, + }); + + expect( + localizationService.getLocalizedString('correct_test_string_id') + ).to.equal('yes'); + }); + + it('should fall back if language code is not registered', () => { + const localizationService = new LocalizationService(win.document.body); + localizationService.registerLocalizedStringBundle('en', { + 'test_string_id': { + string: 'yes', + }, + }); + + expect(localizationService.getLocalizedString('test_string_id')).to.equal( + 'yes' + ); + }); + }); +});