Merge pull request #252 from simoleo89/fix/purse-seasonal-currency-label

fix(purse): don't show raw localization keys for unnamed seasonal currencies
This commit is contained in:
DuckieTM
2026-06-18 12:28:02 +02:00
committed by GitHub
5 changed files with 49 additions and 9 deletions
+1
View File
@@ -14,6 +14,7 @@ export * from './PlaySound';
export * from './PrefixUtils';
export * from './ProductImageUtility';
export * from './Randomizer';
export * from './localizeWithFallback';
export * from './RememberLogin';
export * from './isSafeExternalUrl';
export * from './RoomChatFormatter';
@@ -0,0 +1,29 @@
import { describe, expect, it } from 'vitest';
import { resolveLocalized } from './localizeWithFallback';
/**
* The localization manager returns the KEY itself when a translation is missing
* (LocalizationManager.getValue → `value || key`). `resolveLocalized` turns that
* "missing" signal into a caller-supplied fallback so raw keys like
* `purse.seasonal.currency.11` never reach the UI.
*/
describe('resolveLocalized', () =>
{
it('returns the localized text when it differs from the key', () =>
{
expect(resolveLocalized('Pixels', 'purse.seasonal.currency.5', 'fallback')).toBe('Pixels');
});
it('returns the fallback when the text equals the key (missing translation)', () =>
{
expect(resolveLocalized('purse.seasonal.currency.11', 'purse.seasonal.currency.11', '')).toBe('');
expect(resolveLocalized('purse.seasonal.currency.11', 'purse.seasonal.currency.11', 'Currency')).toBe('Currency');
});
it('returns the fallback for empty / null text', () =>
{
expect(resolveLocalized('', 'some.key', 'FB')).toBe('FB');
expect(resolveLocalized(null as unknown as string, 'some.key', 'FB')).toBe('FB');
});
});
+16
View File
@@ -0,0 +1,16 @@
import { LocalizeText } from './LocalizeText';
/**
* Pure decision: the localization manager returns the key itself for a missing
* translation, so treat "text equals the key" (or empty) as "no translation"
* and use the fallback instead.
*/
export const resolveLocalized = (localized: string, key: string, fallback: string): string =>
((localized && (localized !== key)) ? localized : fallback);
/**
* Localize `key`, returning `fallback` when the key has no translation
* (so raw keys never surface in the UI).
*/
export const localizeWithFallback = (key: string, fallback: string): string =>
resolveLocalized(LocalizeText(key), key, fallback);
+1 -7
View File
@@ -1,18 +1,12 @@
import { CreateLinkEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useMemo, useState } from 'react';
import { FaChartBar, FaCog, FaSignOutAlt } from 'react-icons/fa';
import { ClearRememberLogin, GetConfigurationValue, GetRememberLogin, LocalizeText } from '../../api';
import { ClearRememberLogin, GetConfigurationValue, GetRememberLogin, localizeWithFallback, LocalizeText } from '../../api';
import { Column, LayoutCurrencyIcon } from '../../common';
import { usePurse } from '../../hooks';
import { CurrencyView } from './views/CurrencyView';
import { SeasonalView } from './views/SeasonalView';
const localizeWithFallback = (key: string, fallback: string) =>
{
const text = LocalizeText(key);
return (text && text !== key) ? text : fallback;
};
export const PurseView: FC<{}> = props =>
{
const { purse = null, hcDisabled = false } = usePurse();
+2 -2
View File
@@ -1,5 +1,5 @@
import { FC } from 'react';
import { GetConfigurationValue, LocalizeFormattedNumber, LocalizeText } from '../../../api';
import { GetConfigurationValue, localizeWithFallback, LocalizeFormattedNumber } from '../../../api';
import { Flex, Text } from '../../../common';
interface SeasonalViewProps {
@@ -22,7 +22,7 @@ export const SeasonalView: FC<SeasonalViewProps> = props =>
>
<Flex fullWidth className="seasonal-row">
<Text truncate fullWidth variant="white" className="seasonal-text-padding seasonal-text">
{LocalizeText(`purse.seasonal.currency.${type}`)}
{localizeWithFallback(`purse.seasonal.currency.${type}`, '')}
</Text>
<Text
variant="white"