From 6fa63b907195180b03284e682de93ca609ef31b1 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 18 Dec 2025 21:34:29 +0800 Subject: [PATCH 1/2] v0.3.9 ~ New language service, and improvements to currentUser service whois resolution --- addon/exports/host-services.js | 1 + addon/exports/services.js | 1 + addon/services/current-user.js | 6 ++ addon/services/language.js | 104 +++++++++++++++++++++++++++ app/services/language.js | 1 + package.json | 2 +- tests/unit/services/language-test.js | 12 ++++ 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 addon/services/language.js create mode 100644 app/services/language.js create mode 100644 tests/unit/services/language-test.js diff --git a/addon/exports/host-services.js b/addon/exports/host-services.js index 08316d89..cc8d3f69 100644 --- a/addon/exports/host-services.js +++ b/addon/exports/host-services.js @@ -21,6 +21,7 @@ export const hostServices = [ 'universe', 'intl', 'abilities', + 'language', { hostRouter: 'router' }, ]; diff --git a/addon/exports/services.js b/addon/exports/services.js index 3bbc9493..0f728bb9 100644 --- a/addon/exports/services.js +++ b/addon/exports/services.js @@ -23,6 +23,7 @@ export const services = [ 'universe', 'intl', 'abilities', + 'language', ]; export default services; diff --git a/addon/services/current-user.js b/addon/services/current-user.js index fe1585e4..8434877f 100644 --- a/addon/services/current-user.js +++ b/addon/services/current-user.js @@ -26,6 +26,7 @@ export default class CurrentUserService extends Service.extend(Evented) { @tracked locale = 'en-us'; @storageFor('user-options') options; + @storageFor('local-cache') cache; @alias('userSnapshot.id') id; @alias('userSnapshot.name') name; @alias('userSnapshot.phone') phone; @@ -260,6 +261,11 @@ export default class CurrentUserService extends Service.extend(Evented) { const whois = this.getOption('whois'); if (!whois || typeof whois !== 'object') { + // Fallback to lookup/whois in local-cache + const cachedWhois = this.cache.get('lookup/whois'); + if (cachedWhois) { + return get(cachedWhois, prop); + } return null; } diff --git a/addon/services/language.js b/addon/services/language.js new file mode 100644 index 00000000..2cbb581a --- /dev/null +++ b/addon/services/language.js @@ -0,0 +1,104 @@ +import Service from '@ember/service'; +import { tracked } from '@glimmer/tracking'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { isNone } from '@ember/utils'; +import { debug } from '@ember/debug'; +import { task } from 'ember-concurrency'; + +export default class LanguageService extends Service { + @service intl; + @service fetch; + @tracked locales = []; + @tracked countries = []; + @tracked currentLocale; + @tracked availableLocales = {}; + + get languages() { + const availableLanguages = []; + for (let key in this.availableLocales) { + if (!key || !this.availableLocales[key]) continue; + + availableLanguages.push({ + ...this.availableLocales[key], + locale: key, + }); + } + + return availableLanguages; + } + + constructor() { + super(...arguments); + + this.locales = this.intl.locales; + this.currentLocale = this.intl.primaryLocale; + this.loadAvailableCountries.perform(); + + // Check for locale change + this.intl.onLocaleChanged(() => { + this.currentLocale = this.intl.primaryLocale; + }); + } + + @action changeLocale(selectedLocale) { + this.currentLocale = selectedLocale; + this.intl.setLocale(selectedLocale); + this.saveUserLocale.perform(selectedLocale); + } + + @task *loadAvailableCountries() { + try { + this.countries = yield this.fetch.get( + 'lookup/countries', + { columns: ['name', 'cca2', 'flag', 'emoji', 'languages'] }, + { fromCache: true, expirationInterval: 1, expirationIntervalUnit: 'week' } + ); + this.availableLocales = this._createAvailableLocaleMap(); + } catch (error) { + debug('Locale Error: ' + error.message); + } + } + + @task *saveUserLocale(locale) { + try { + yield this.fetch.post('users/locale', { locale }); + } catch (err) { + debug('[LanguageService] Unable to save user locale: ' + err.message); + } + } + + getLanguage(languageName, options = { prop: 'language' }) { + const { prop } = options; + + return this.languages?.find((l) => l[prop] === languageName) ?? null; + } + + hasLanguage(languageName, options = { prop: 'language' }) { + return this.getLanguage(languageName, options) !== null; + } + + _createAvailableLocaleMap() { + const localeMap = {}; + + for (let i = 0; i < this.locales.length; i++) { + const locale = this.locales.objectAt(i); + + localeMap[locale] = this._findCountryDataForLocale(locale); + } + + return localeMap; + } + + _findCountryDataForLocale(locale) { + const localeCountry = locale.split('-')[1]; + const country = this.countries.find((country) => country.cca2.toLowerCase() === localeCountry); + + if (country) { + // get the language + country.language = Object.values(country.languages)[0]; + } + + return country; + } +} diff --git a/app/services/language.js b/app/services/language.js new file mode 100644 index 00000000..ff21c6ed --- /dev/null +++ b/app/services/language.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/ember-core/services/language'; diff --git a/package.json b/package.json index 49f22f6a..35a7f22a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/ember-core", - "version": "0.3.8", + "version": "0.3.9", "description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.", "keywords": [ "fleetbase-core", diff --git a/tests/unit/services/language-test.js b/tests/unit/services/language-test.js new file mode 100644 index 00000000..e4286b80 --- /dev/null +++ b/tests/unit/services/language-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'dummy/tests/helpers'; + +module('Unit | Service | language', function (hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function (assert) { + let service = this.owner.lookup('service:language'); + assert.ok(service); + }); +}); From 1405f716b4cdbd793f2beb7af7b3f72577d2b8d7 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 19 Dec 2025 16:13:39 +0800 Subject: [PATCH 2/2] fixed linter --- addon/services/language.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addon/services/language.js b/addon/services/language.js index 2cbb581a..da0d3603 100644 --- a/addon/services/language.js +++ b/addon/services/language.js @@ -2,7 +2,6 @@ import Service from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; -import { isNone } from '@ember/utils'; import { debug } from '@ember/debug'; import { task } from 'ember-concurrency';