Skip to content
Draft
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
30 changes: 22 additions & 8 deletions packages/fxa-settings/src/components/DeviceInfoBlock/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,52 @@ export const DeviceInfoBlock = ({ remoteMetadata }: DeviceInfoBlockProps) => {
city,
region,
country,
countryCode,
} = remoteMetadata;
const currentLocale = document.documentElement.lang || 'en-US';
let localizedCountry = country;

if (countryCode && typeof Intl !== 'undefined' && Intl.DisplayNames) {
try {
const regionNames = new Intl.DisplayNames([currentLocale], {
type: 'region',
});
localizedCountry = regionNames.of(countryCode) || country;
} catch (e) {
// Fallback to raw country name if Intl fails
}
}
const LocalizedLocation = () => {
if (city && region && country) {
return (
<FtlMsg
id="device-info-block-location-city-region-country"
vars={{ city, region, country }}
>{`${city}, ${region}, ${country} (estimated)`}</FtlMsg>
vars={{ city, region, country: localizedCountry }}
>{`${city}, ${region}, ${localizedCountry} (estimated)`}</FtlMsg>
);
}
if (region && country) {
return (
<FtlMsg
id="device-info-block-location-region-country"
vars={{ region, country }}
>{`${region}, ${country} (estimated)`}</FtlMsg>
vars={{ region, country: localizedCountry }}
>{`${region}, ${localizedCountry} (estimated)`}</FtlMsg>
);
}
if (city && country) {
return (
<FtlMsg
id="device-info-block-location-city-country"
vars={{ city, country }}
>{`${city}, ${country} (estimated)`}</FtlMsg>
vars={{ city, country: localizedCountry }}
>{`${city}, ${localizedCountry} (estimated)`}</FtlMsg>
);
}
if (country) {
return (
<FtlMsg
id="device-info-block-location-country"
vars={{ country }}
>{`${country} (estimated)`}</FtlMsg>
vars={{ country: localizedCountry }}
>{`${localizedCountry} (estimated)`}</FtlMsg>
);
}
return (
Expand Down
1 change: 1 addition & 0 deletions packages/fxa-settings/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type RemoteMetadata = {
deviceOS: string;
ipAddress: string;
country?: string;
countryCode?: string;
region?: string;
city?: string;
};
Expand Down
45 changes: 8 additions & 37 deletions packages/fxa-shared/connected-services/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,47 +50,18 @@ export class ClientFormatter implements IClientFormatter {
client: AttachedClient,
request: IClientFormatterRequest
) {
let language;
if (!client.location) {
client.location = {};
} else {
const location = client.location;
try {
language = determineLocale(
request.app.acceptLanguage,
this.supportedLanguages
);

// For English, we can leave all the location components intact.
// For other languages, only return what we can translate
if (language[0] === 'e' || language[1] === 'n') {
client.location = {
city: location.city,
country: location.country,
state: location.state,
stateCode: location.stateCode,
};
} else if (location.countryCode) {
const territoriesLang =
language === 'en-US' ? 'en-US-POSIX' : language;
const territories = require(`cldr-localenames-full/main/${territoriesLang}/territories.json`);
client.location = {
country:
territories.main[language].localeDisplayNames.territories[
location.countryCode
],
};
}
} catch (err) {
const log = this.logProvider();
log.debug('attached-clients.formatLocation.warning', {
err: err.message,
languages: request.app.acceptLanguage,
language,
location,
});
client.location = {};
}
// ClientFormatter should be locale-agnostic and return consistent identifiers across all requests.
client.location = {
city: location.city,
country: location.country,
countryCode: location.countryCode,
state: location.state,
stateCode: location.stateCode,
};
}
return client;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type AttachedClient = {
lastAccessTimeFormatted?: string;
approximateLastAccessTime?: number;
approximateLastAccessTimeFormatted?: string;
countryCode?: string | null;
};

export const attachedClientsDefaults: AttachedClient = {
Expand Down
19 changes: 12 additions & 7 deletions packages/fxa-shared/test/connected-services/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,29 @@ describe('connected-services/formatters', () => {
assert.exists(client.location?.state);
assert.exists(client.location?.stateCode);
assert.exists(client.location?.country);
// Not set, is this a bug?
// assert.exists(client.location?.countryCode);
assert.exists(client.location?.countryCode);
});

it('formats DE location', () => {
request.app.acceptLanguage = 'de-DE';
client.location = {
city: 'Berlin',
countryCode: 'DE',
country: 'Germany',
state: 'Berlin',
stateCode: 'BE'
};
clientFormatter.formatLocation(client, request);

assert.exists(client.location?.city);
assert.exists(client.location?.state);
assert.exists(client.location?.stateCode);
assert.exists(client.location?.country);
// Not set, is this a bug?
// assert.exists(client.location?.city);
// assert.exists(client.location?.state);
// assert.exists(client.location?.stateCode);
// assert.exists(client.location?.countryCode);
assert.exists(client.location?.countryCode);

// Assert we are NOT localizing on the backend anymore
assert.strictEqual(client.location?.country, 'Germany'); // Should remain as input
assert.strictEqual(client.location?.countryCode, 'DE');
});

it('formats timestamps', () => {
Expand Down
Loading