Skip to content
Merged

Lang #31

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions __tests__/core/configuration/locale_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* @jest-environment jsdom
*/

import { Locale } from '../../../src/core/configuration/locale'

describe('Locale', () => {
beforeEach(() => {
Locale._identifier = undefined
})

describe('identifier setter and getter', () => {
it('sets and gets the identifier explicitly', () => {
Locale.identifier = 'es'
expect(Locale.identifier).toBe('es')
})

it('allows changing the identifier', () => {
Locale.identifier = 'fr'
expect(Locale.identifier).toBe('fr')

Locale.identifier = 'en'
expect(Locale.identifier).toBe('en')
})

it('falls back to "en" when nothing is set', () => {
expect(Locale.identifier).toBe('en')
})
})

describe('toString method', () => {
it('returns the same value as identifier getter', () => {
Locale.identifier = 'es'
expect(Locale.toString()).toBe('es')
expect(Locale.toString()).toBe(Locale.identifier)
})
})

describe('auto-detection fallback', () => {
it('falls back to "en" when nothing is set', () => {
document.documentElement.lang = ''

const originalQuerySelector = document.querySelector
document.querySelector = jest.fn().mockReturnValue(null)

Object.defineProperty(navigator, 'language', {
writable: true,
value: undefined
})

expect(Locale.identifier).toBe('en')
document.querySelector = originalQuerySelector
})

it('uses HTML lang attribute when available', () => {
document.documentElement.lang = 'es'
expect(Locale.identifier).toBe('es')
})

it('uses meta locale when HTML lang is empty', () => {
document.documentElement.lang = ''

const mockMetaElement = { content: 'fr' }
document.querySelector = jest.fn().mockReturnValue(mockMetaElement)

expect(Locale.identifier).toBe('fr')
expect(document.querySelector).toHaveBeenCalledWith('meta[name="locale"]')
})

it('uses browser language when HTML and meta are empty', () => {
document.documentElement.lang = ''
document.querySelector = jest.fn().mockReturnValue(null)

Object.defineProperty(navigator, 'language', {
writable: true,
value: 'de-DE'
})

expect(Locale.identifier).toBe('de')
})
})

describe('priority order', () => {
it('prioritizes explicit setting over everything', () => {
Locale.identifier = 'en'

document.documentElement.lang = 'es'
document.querySelector = jest.fn().mockReturnValue({ content: 'fr' })
Object.defineProperty(navigator, 'language', {
writable: true,
value: 'de-DE'
})

expect(Locale.identifier).toBe('en')
})

it('prioritizes HTML lang over meta and browser', () => {
document.documentElement.lang = 'es'
document.querySelector = jest.fn().mockReturnValue({ content: 'fr' })
Object.defineProperty(navigator, 'language', {
writable: true,
value: 'de-DE'
})

expect(Locale.identifier).toBe('es')
})

it('prioritizes meta over browser language', () => {
document.documentElement.lang = ''
document.querySelector = jest.fn().mockReturnValue({ content: 'fr' })
Object.defineProperty(navigator, 'language', {
writable: true,
value: 'de-DE'
})

expect(Locale.identifier).toBe('fr')
})
})
})
16 changes: 16 additions & 0 deletions __tests__/core/configuration_test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Configuration } from '../../src/core'
import { Locale } from '../../src/core/configuration/locale'

describe('Configuration', () => {
describe('.autoGenerateSession', () => {
Expand Down Expand Up @@ -32,4 +33,19 @@ describe('Configuration', () => {
expect(Configuration.webchat.id).toEqual('123')
})
})

describe('.locale', () => {
beforeEach(() => {
Locale._identifier = undefined
})

it('can be set', () => {
Configuration.locale = 'es'
expect(Configuration.locale).toEqual('es')
})

it('defaults to "en" when nothing is set', () => {
expect(Configuration.locale).toEqual('en')
})
})
})
2 changes: 1 addition & 1 deletion dist/hellotext.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion lib/api/forms.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _hellotext = _interopRequireDefault(require("../hellotext"));
var _core = require("../core");
var _hellotext = _interopRequireDefault(require("../hellotext"));
var _response = require("./response");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
Expand All @@ -27,6 +27,7 @@ let FormsAPI = /*#__PURE__*/function () {
value: async function get(id) {
const url = new URL(`${this.endpoint}/${id}`);
url.searchParams.append('session', _hellotext.default.session);
url.searchParams.append('locale', _core.Locale.toString());
return fetch(url, {
method: 'GET',
headers: _hellotext.default.headers
Expand Down
3 changes: 2 additions & 1 deletion lib/api/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { Configuration, Locale } from '../core';
import Hellotext from '../hellotext';
import { Configuration } from '../core';
import { Response } from './response';
var FormsAPI = /*#__PURE__*/function () {
function FormsAPI() {
Expand All @@ -26,6 +26,7 @@ var FormsAPI = /*#__PURE__*/function () {
var _get = _asyncToGenerator(function* (id) {
var url = new URL("".concat(this.endpoint, "/").concat(id));
url.searchParams.append('session', Hellotext.session);
url.searchParams.append('locale', Locale.toString());
return fetch(url, {
method: 'GET',
headers: Hellotext.headers
Expand Down
2 changes: 2 additions & 0 deletions lib/api/webchats.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ let WebchatsAPI = /*#__PURE__*/function () {
value: async function get(id) {
const url = new URL(`${this.endpoint}/${id}`);
url.searchParams.append('session', _hellotext.default.session);
url.searchParams.append('locale', _core.Locale.toString());
Object.entries(_core.Configuration.webchat.style).forEach(([key, value]) => {
url.searchParams.append(`style[${key}]`, value);
});
Expand All @@ -37,6 +38,7 @@ let WebchatsAPI = /*#__PURE__*/function () {
const data = await response.json();
if (!_hellotext.default.business.data) {
_hellotext.default.business.setData(data.business);
_hellotext.default.business.setLocale(data.locale);
}
return new DOMParser().parseFromString(data.html, 'text/html').querySelector('article');
}
Expand Down
4 changes: 3 additions & 1 deletion lib/api/webchats.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
import { Configuration } from '../core';
import { Configuration, Locale } from '../core';
import Hellotext from '../hellotext';
var WebchatsAPI = /*#__PURE__*/function () {
function WebchatsAPI() {
Expand All @@ -22,6 +22,7 @@ var WebchatsAPI = /*#__PURE__*/function () {
var _get = _asyncToGenerator(function* (id) {
var url = new URL("".concat(this.endpoint, "/").concat(id));
url.searchParams.append('session', Hellotext.session);
url.searchParams.append('locale', Locale.toString());
Object.entries(Configuration.webchat.style).forEach(_ref => {
var [key, value] = _ref;
url.searchParams.append("style[".concat(key, "]"), value);
Expand All @@ -34,6 +35,7 @@ var WebchatsAPI = /*#__PURE__*/function () {
var data = yield response.json();
if (!Hellotext.business.data) {
Hellotext.business.setData(data.business);
Hellotext.business.setLocale(data.locale);
}
return new DOMParser().parseFromString(data.html, 'text/html').querySelector('article');
});
Expand Down
2 changes: 1 addition & 1 deletion lib/builders/logo_builder.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function _template2() {
return `
<div data-logo-container>
<small>${_hellotext.default.business.locale.white_label.powered_by}</small>

<a href="${url}" rel="noreferrer" target="_blank">
<svg data-hello-brand viewBox="0 0 224 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Hellotext</title>
Expand Down
Loading