diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 3963b9f5bd5..e4d42eebb9b 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -24,6 +24,7 @@ 1. [MISC] Added aircraft version check and uer notification - @frankkopp (Frank Kopp) 1. [EFB] Added boarding time indication to Payload page - @ChristianLutzCL (Christian Lutz) @frankkopp (Frank Kopp) 1. [ADIRU/ND/PFD] Initial support for polar navigation - @tracernz (Mike) +1. [MISC] Added aircraft version check and uer notification - @frankkopp (Frank Kopp) ## 0.9.0 @@ -1160,4 +1161,3 @@ 1. [DCDU] Fixed MSG- and MSG+ button labels - @tyler58546 (tyler58546) 1. [ISIS] Fixed issue where ISIS was allowing a bug to be set while in the OFF state - Patrick Macken (@Pat M on Discord) -1. [EFB] Added estimated boarding time to Payload screen - @ChristianLutzCL (Christian Lutz) diff --git a/package-lock.json b/package-lock.json index fc022e924f4..9c8870e5d3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3977,7 +3977,8 @@ "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true }, "node_modules/@types/stack-utils": { "version": "2.0.1", @@ -39011,7 +39012,8 @@ "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true }, "@types/stack-utils": { "version": "2.0.1", diff --git a/src/instruments/src/EFB/Localization/de.json b/src/instruments/src/EFB/Localization/de.json index f3c17bb1469..1b161e35e68 100644 --- a/src/instruments/src/EFB/Localization/de.json +++ b/src/instruments/src/EFB/Localization/de.json @@ -643,10 +643,13 @@ "Wed": "Mi" }, "VersionCheck": { + "Title": "Neue Version verfügbar", + "StatusBarWarning": "Neue A32NX Version verfügbar", "CurrentVersionText": "Momentan wird die $edition Edition in dieser Version genutzt:", "LatestVersionText": "Die aktuell verfügbare $edition Version ist:", "RecommendationText": "Bitte mit Hilfe des FlyByWire-Installer die neueste Version installieren.", - "StatusBarWarning": "Neue A32NX Version verfügbar", - "Title": "Neue Version verfügbar" + "TT": { + "StatusBarWarning": "Bitte mit Hilfe des FlyByWire-Installer die neueste Version installieren." + } } } diff --git a/src/instruments/src/EFB/Localization/en.json b/src/instruments/src/EFB/Localization/en.json index 729e7152c01..030f9c071e9 100644 --- a/src/instruments/src/EFB/Localization/en.json +++ b/src/instruments/src/EFB/Localization/en.json @@ -643,10 +643,13 @@ "Wed": "Wed" }, "VersionCheck": { + "Title": "New Version Available", + "StatusBarWarning": "Outdated Aircraft Version", "CurrentVersionText": "You are using the $edition edition with version:", "LatestVersionText": "Latest $edition version is", "RecommendationText": "Please update your aircraft using the FlyByWire Installer.", - "StatusBarWarning": "Outdated Aircraft Version", - "Title": "New Version Available" + "TT": { + "StatusBarWarning": "Please update your aircraft using the FlyByWire Installer." + } } -} \ No newline at end of file +} diff --git a/src/instruments/src/EFB/Settings/Pages/AboutPage.tsx b/src/instruments/src/EFB/Settings/Pages/AboutPage.tsx index d19abeffdee..9dbdde1ad3f 100644 --- a/src/instruments/src/EFB/Settings/Pages/AboutPage.tsx +++ b/src/instruments/src/EFB/Settings/Pages/AboutPage.tsx @@ -1,3 +1,6 @@ +// Copyright (c) 2022 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + import React, { useEffect, useState } from 'react'; import { usePersistentProperty, useSessionStorage } from '@instruments/common/persistence'; import { SentryConsentState, SENTRY_CONSENT_KEY } from '../../../../../sentry-client/src/FbwAircraftSentryClient'; diff --git a/src/instruments/src/EFB/StatusBar/StatusBar.tsx b/src/instruments/src/EFB/StatusBar/StatusBar.tsx index a8d3617cc74..9ecffcf49aa 100644 --- a/src/instruments/src/EFB/StatusBar/StatusBar.tsx +++ b/src/instruments/src/EFB/StatusBar/StatusBar.tsx @@ -152,9 +152,13 @@ export const StatusBar = ({ batteryLevel, isCharging }: StatusBarProps) => {

{`${dayName} ${monthName} ${dayOfMonth}`}

-
- {outdatedVersionFlag ? 'OUTDATED AIRCRAFT VERSION' : ''} -
+ {outdatedVersionFlag ? ( +
+ + {t('VersionCheck.StatusBarWarning').toUpperCase()} + +
+ ) : ''}
{(timeDisplayed === 'utc' || timeDisplayed === 'both') && ( diff --git a/src/instruments/src/EFB/Utils/AircraftVersionChecker.ts b/src/instruments/src/EFB/Utils/AircraftVersionChecker.ts index 2d9d4f9c160..26c3839fc58 100644 --- a/src/instruments/src/EFB/Utils/AircraftVersionChecker.ts +++ b/src/instruments/src/EFB/Utils/AircraftVersionChecker.ts @@ -1,12 +1,11 @@ -/* eslint-disable no-console */ // Copyright (c) 2022 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 +/* eslint-disable no-console */ import Compare from 'semver/functions/compare'; import { CommitInfo, GitVersions, ReleaseInfo } from '@flybywiresim/api-client'; -// jest in test-js.sh requires relative path can't handle "@shared" alias -// noinspection ES6PreferShortImport -import { PopUp } from '../../../../shared/src/popup'; +import { PopUp } from '@shared/popup'; +import { t } from '../translation'; /** * Contains the a32nx_build_info.json file's information in a structured way. @@ -128,19 +127,13 @@ export class AircraftVersionChecker { public static getVersionInfo(versionString: string): VersionInfoData { const matchBuildInfo = versionString.match(/^v?((\d+)\.(\d+)\.(\d+))-(.*)\.(.{7})$/); if (matchBuildInfo) { - const version = matchBuildInfo[1]; - const major = parseInt(matchBuildInfo[2], 10); - const minor = parseInt(matchBuildInfo[3], 10); - const patch = parseInt(matchBuildInfo[4], 10); - const branch = matchBuildInfo[5]; - const commit = matchBuildInfo[6]; return { - version, - major, - minor, - patch, - branch, - commit, + version: matchBuildInfo[1], + major: parseInt(matchBuildInfo[2], 10), + minor: parseInt(matchBuildInfo[3], 10), + patch: parseInt(matchBuildInfo[4], 10), + branch: matchBuildInfo[5], + commit: matchBuildInfo[6], }; } throw new Error('Invalid version format'); @@ -242,12 +235,16 @@ export class AircraftVersionChecker { private static showVersionPopup(branchName, currentVersion, releaseVersion) { const popup = new PopUp(); popup.showInformation( - 'NEW VERSION AVAILABLE', + t('VersionCheck.Title'), `
- You are using ${branchName} version:
${currentVersion}

- Latest ${branchName} version is:
${releaseVersion}

- Please update your aircraft using the FlyByWire Installer. -
`, + ${t('VersionCheck.CurrentVersionText', [{ edition: branchName }])}
+ ${currentVersion}

+ + ${t('VersionCheck.LatestVersionText', [{ edition: branchName }])}
+ ${releaseVersion}

+ + ${t('VersionCheck.RecommendationText')} +
`, 'normal', () => {}, ); diff --git a/src/instruments/src/EFB/translation.ts b/src/instruments/src/EFB/translation.ts index 0d7880c5bf1..cadb80c4c46 100644 --- a/src/instruments/src/EFB/translation.ts +++ b/src/instruments/src/EFB/translation.ts @@ -153,6 +153,17 @@ if (process.env.VITE_BUILD) { watchLanguageChanges(); } +const placeholderReplace = (translation: string, replacements: Record[]): string => { + let result = translation; + replacements.forEach((replacement: Record) => { + // Localazy uses $ as placeholder - $key will be replaced with the value of key + const searchValue = `$${Object.keys(replacement)[0]}`; + const replaceValue = Object.values(replacement)[0].toString(); + result = result.replace(searchValue, replaceValue); + }); + return result; +}; + /** * Returns localized string in the currently configured language when provided with * correct identifier key. @@ -160,14 +171,26 @@ if (process.env.VITE_BUILD) { * find the key there. * If the key is not available in the default language the key itself will be returned. * + * If a replacement list is provided it will replace the placeholders in the string with the + * key as placeholder-text to be search and the value as the string to be put in place. + * + * Placeholders are defined as follows: $key + * + * E.g. "Hello $name" with {name: "John"} will return "Hello John" + * * Note: Currently all language files are imported and contain all keys so this is redundant * but still implemented for future changes. * @param key String identifier key + * @param replacements list of Records of key value pairs to replace in the string * @return translated string in the current language if available, or default * language, or key string */ -export function t(key: string): string { - return currentLanguageMap.get(key) || defaultLanguage.get(key) || key; +export function t(key: string, replacements?: Record[]): string { + const translation = currentLanguageMap.get(key) || defaultLanguage.get(key) || key; + if (replacements) { + return placeholderReplace(translation, replacements); + } + return translation; } // Workaround after simvar hook changes - only required on FlyPadPage.tsx from flypad settings