latest dev + i18n

This commit is contained in:
_Bastler 2022-01-27 13:03:59 +01:00
parent e3b58a0d56
commit 7e987ad470
12 changed files with 70 additions and 34 deletions

View File

@ -1,6 +1,8 @@
<script lang="ts">
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
import { i18nJson } from "../../i18n/locales";
function onClick(callback: () => void) {
callback();
@ -8,20 +10,7 @@
function i18n(text: string | number | boolean | undefined): string {
if (typeof text === "string") {
if (text.trim().startsWith("{")) {
try {
let textObject = JSON.parse(text);
if (textObject[$locale]) {
return textObject[$locale];
} else if (Object.keys(textObject).length > 0) {
// fallback to first value
return textObject[Object.keys(textObject)[0]];
}
} catch (err) {
//
}
}
return text;
return i18nJson(text);
}
return "";
}

View File

@ -34,5 +34,5 @@
<SoundMeterWidget {stream} />
{/if}
</div>
<div class="is-silent" class:hide={isSilent}>{$LL.camera.my.silentZone()}</div>
<div class="nes-container is-dark is-silent" class:hide={isSilent}>{$LL.camera.my.silentZone()}</div>
</div>

View File

@ -17,6 +17,9 @@ import { isRegisterData } from "../Messages/JsonMessages/RegisterData";
import { isAdminApiData } from "../Messages/JsonMessages/AdminApiData";
import { limitMapStore } from "../Stores/GameStore";
import { showLimitRoomModalStore } from "../Stores/ModalStore";
import { locales } from "../i18n/i18n-util";
import type { Locales } from "../i18n/i18n-types";
import { setCurrentLocale } from "../i18n/locales";
class ConnectionManager {
private localUser!: LocalUser;
@ -343,9 +346,12 @@ class ConnectionManager {
throw new Error("No Auth code provided");
}
}
const { authToken, userUuid, textures, email, username } = await Axios.get(`${PUSHER_URL}/login-callback`, {
params: { code, nonce, token, playUri: this.currentRoom?.key },
}).then((res) => {
const { authToken, userUuid, textures, email, username, locale } = await Axios.get(
`${PUSHER_URL}/login-callback`,
{
params: { code, nonce, token, playUri: this.currentRoom?.key },
}
).then((res) => {
return res.data;
});
localUserStore.setAuthToken(authToken);
@ -355,6 +361,25 @@ class ConnectionManager {
if (username) {
gameManager.setPlayerName(username);
}
if (locale) {
try {
if (locales.indexOf(locale) == -1) {
locales.forEach((l) => {
if (l.startsWith(locale.split("-")[0])) {
setCurrentLocale(l);
return;
}
});
} else {
setCurrentLocale(locale as Locales);
}
} catch (err) {
console.warn("Could not set locale", err);
}
} else {
console.log("no locale", locale);
}
//user connected, set connected store for menu at true
userIsConnected.set(true);
}

View File

@ -92,6 +92,7 @@ import { followUsersColorStore } from "../../Stores/FollowStore";
import Camera = Phaser.Cameras.Scene2D.Camera;
import { GameSceneUserInputHandler } from "../UserInput/GameSceneUserInputHandler";
import { locale } from "../../i18n/i18n-svelte";
import { i18nJson } from "../../i18n/locales";
export interface GameSceneInitInterface {
initPosition: PointInterface | null;
@ -1066,7 +1067,7 @@ export class GameScene extends DirtyScene {
);
return;
}
const escapedMessage = HtmlUtils.sanitize(openPopupEvent.message);
const escapedMessage = HtmlUtils.sanitize(i18nJson(openPopupEvent.message));
let html = `<div id="container" hidden><div class="nes-container with-title is-centered">`;
html += escapedMessage;
if (openPopupEvent.input) {
@ -1080,7 +1081,9 @@ export class GameScene extends DirtyScene {
for (const button of openPopupEvent.buttons) {
html += `<button type="button" class="nes-btn is-${HtmlUtils.escapeHtml(
button.className ?? ""
)}" id="popup-${openPopupEvent.popupId}-${id}">${HtmlUtils.escapeHtml(button.label)}</button>`;
)}" id="popup-${openPopupEvent.popupId}-${id}">${HtmlUtils.escapeHtml(
i18nJson(button.label)
)}</button>`;
id++;
}
html += "</div>";

View File

@ -28,7 +28,7 @@ const de_DE: Translation = {
menu,
report,
warning,
emiji,
emoji,
};
export default de_DE;

View File

@ -114,6 +114,7 @@ const menu: NonNullable<Translation["menu"]> = {
},
sub: {
profile: "Profil",
worlds: "Welt",
settings: "Einstellungen",
invite: "Einladung",
credit: "Über die Karte",

View File

@ -113,6 +113,7 @@ const menu: BaseTranslation = {
},
sub: {
profile: "Profile",
worlds: "Worlds",
settings: "Settings",
invite: "Invite",
credit: "Credit",

View File

@ -1,8 +1,9 @@
import { detectLocale, navigatorDetector, initLocalStorageDetector } from "typesafe-i18n/detectors";
import { FALLBACK_LOCALE } from "../Enum/EnvironmentVariable";
import { initI18n, setLocale } from "./i18n-svelte";
import { initI18n, setLocale, locale } from "./i18n-svelte";
import type { Locales, Translation } from "./i18n-types";
import { baseLocale, getTranslationForLocale, locales } from "./i18n-util";
import { get } from "svelte/store";
const fallbackLocale = FALLBACK_LOCALE || baseLocale;
const localStorageProperty = "language";
@ -50,3 +51,20 @@ function getDisplayableLocales() {
}
export const displayableLocales = getDisplayableLocales();
export const i18nJson = (text: string): string => {
if (text.trim().startsWith("{")) {
try {
const textObject = JSON.parse(text);
if (textObject[get(locale)]) {
return textObject[get(locale)];
} else if (Object.keys(textObject).length > 0) {
// fallback to first value
return textObject[Object.keys(textObject)[0]];
}
} catch (err) {
//
}
}
return text;
};

View File

@ -1047,15 +1047,12 @@ div.action.danger p.action-body{
}
div.is-silent {
position: absolute;
position: absolute !important;
bottom: 40px;
border-radius: 15px 15px 15px 15px;
max-height: 20%;
transition: right 350ms;
right: -300px;
background-color: black;
right: -1000px;
font-size: 20px;
color: white;
padding: 30px 20px;
}
div.is-silent.hide {

View File

@ -91,7 +91,7 @@ export class AuthenticateController extends BaseController {
const resCheckTokenAuth = await openIDClient.checkTokenAuth(authTokenData.accessToken);
res.writeStatus("200");
this.addCorsHeaders(res);
return res.end(JSON.stringify({ ...resCheckTokenAuth, ...resUserData, username: authTokenData.username, authToken: token }));
return res.end(JSON.stringify({ ...resCheckTokenAuth, ...resUserData, username: authTokenData.username, locale: authTokenData.locale, authToken: token }));
} catch (err) {
console.info("User was not connected", err);
}
@ -113,7 +113,7 @@ export class AuthenticateController extends BaseController {
if (!sub) {
throw new Error("No sub in the response");
}
const authToken = jwtTokenManager.createAuthToken(sub, userInfo?.access_token, userInfo?.username);
const authToken = jwtTokenManager.createAuthToken(sub, userInfo?.access_token, userInfo?.username, userInfo.locale);
//Get user data from Admin Back Office
//This is very important to create User Local in LocalStorage in WorkAdventure
@ -121,7 +121,7 @@ export class AuthenticateController extends BaseController {
res.writeStatus("200");
this.addCorsHeaders(res);
return res.end(JSON.stringify({ ...data, authToken, username: userInfo.username, userUuid : sub }));
return res.end(JSON.stringify({ ...data, authToken, username: userInfo.username, locale: userInfo.locale, userUuid : sub }));
} catch (e) {
console.error("openIDCallback => ERROR", e);
return this.errorToResponse(e, res);

View File

@ -6,6 +6,7 @@ export interface AuthTokenData {
identifier: string; //will be a sub (id) if logged in or an uuid if anonymous
accessToken?: string;
username?: string;
locale?: string;
}
export interface AdminSocketTokenData {
authorizedRoomIds: string[]; //the list of rooms the client is authorized to read from.
@ -17,8 +18,8 @@ class JWTTokenManager {
return Jwt.verify(token, ADMIN_SOCKETS_TOKEN) as AdminSocketTokenData;
}
public createAuthToken(identifier: string, accessToken?: string, username?: string) {
return Jwt.sign({ identifier, accessToken, username }, SECRET_KEY, { expiresIn: "30d" });
public createAuthToken(identifier: string, accessToken?: string, username?: string, locale?: string) {
return Jwt.sign({ identifier, accessToken, username, locale }, SECRET_KEY, { expiresIn: "30d" });
}
public verifyJWTToken(token: string, ignoreExpiration: boolean = false): AuthTokenData {

View File

@ -26,7 +26,7 @@ class OpenIDClient {
public authorizationUrl(state: string, nonce: string, playUri?: string, redirect?: string) {
return this.initClient().then((client) => {
return client.authorizationUrl({
scope: "openid email",
scope: "openid profile email",
prompt: "login",
state: state,
nonce: nonce,
@ -36,7 +36,7 @@ class OpenIDClient {
});
}
public getUserInfo(code: string, nonce: string): Promise<{ email: string; sub: string; access_token: string; username: string }> {
public getUserInfo(code: string, nonce: string): Promise<{ email: string; sub: string; access_token: string; username: string, locale: string }> {
return this.initClient().then((client) => {
return client.callback(OPID_CLIENT_REDIRECT_URL, { code }, { nonce }).then((tokenSet) => {
return client.userinfo(tokenSet).then((res) => {
@ -46,6 +46,7 @@ class OpenIDClient {
sub: res.sub,
access_token: tokenSet.access_token as string,
username: (res.preferred_username || res.username || res.nickname || res.name || res.email) as string,
locale: res.locale as string,
};
});
});