(refactor) add i18n to frontend and refactor

This commit is contained in:
Halit Aksoy 2024-06-17 23:50:13 +03:00
parent 02277287d0
commit 66b61215c1
21 changed files with 196 additions and 258 deletions

View File

@ -1,4 +1,5 @@
export * from './models/index'
export * from './rtmt/index'
export * from './theme/index'
export * from './storage/storage'
export * from './storage/storage'
export * from './localization/index'

View File

@ -0,0 +1,40 @@
export const en = {
Mancala: "Mancala",
Leave: "Leave The Game",
NewGame: "New Game",
YourTurn: "Your Turn",
OpponentTurn: "Opponent Turn",
GameEnded: "Game Ended",
InternalErrorOccurred: "An internal error has occurred",
YouWon: "You Won",
Won: "Won",
YouLost: "You Lost",
Connecting: "Connecting",
Connected: "Connected",
CannotConnect: "Can't Connect",
ConnectionLost: "Network Connection Lost",
ConnectingAgain: "Connecting Again",
ServerError: "Server Error",
SearchingOpponet: "Searching Opponet",
OpponentLeftTheGame: "Opponent Leaves The Game",
YouLeftTheGame: "You Left The Game",
UserLeftTheGame: "Left The Game",
SearchingOpponent: "Searching Opponent",
PleaseWait: "Please Wait",
GameDraw: "Draw",
Anonymous: "Anonymous",
GameNotFound: "Game Not Found",
Loading: "Loading",
Playing: "Playing",
Error: "Error",
ErrorWhenRetrievingInformation: "An error occured when retrieving information!",
UCanOnlyPlayYourOwnPits: "You can only play your own pits",
UMustWaitUntilCurrentMoveComplete: "You must wait until the current move is complete",
UCanNotPlayEmptyPit: "You can not play empty pit",
AreYouSureToLeaveGame: "Are you sure to leave game?",
Yes: "Yes",
Cancel: "Cancel",
Help: "Help",
WebApp: "Goto WebApp",
Privacy: "Open Privacy Policy"
}

View File

@ -0,0 +1,2 @@
export * from './en'
export * from './tr'

View File

@ -0,0 +1,40 @@
export const tr = {
Mancala: "Köçürme",
Leave: "Oyundan Ayrıl",
NewGame: "Yeni Oyun",
YourTurn: "Sıra Sende",
OpponentTurn: "Sıra Rakipte",
GameEnded: "Oyun Bitti",
InternalErrorOccurred: "Dahili bir hata oluştu",
YouWon: "Kazandın",
Won: "Kazandı",
YouLost: "Kaybettin",
Connecting: "Bağlanılıyor",
Connected: "Bağlandı",
CannotConnect: "Bağlanılamadı",
ConnectionLost: "Ağ Bağlantısı Koptu",
ConnectingAgain: "Tekrar Bağlanılıyor",
ServerError: "Sunucu Hatası",
SearchingOpponet: "Rakip Aranıyor",
OpponentLeftTheGame: "Rakip Oyundan Ayrıldı",
YouLeftTheGame: "Sen Oyundan Ayrıldın",
UserLeftTheGame: "Oyundan Ayrıldı",
SearchingOpponent: "Rakip Aranıyor",
PleaseWait: "Lütfen Bekleyin",
GameDraw: "Berabere",
Anonymous: "Anonim",
GameNotFound: "Oyun Bulunamadı",
Loading: "Yükleniyor",
Playing: "Oynuyor",
Error: "Hata",
ErrorWhenRetrievingInformation: "Bilgiler toplanırken bir hata oluştu!",
UCanOnlyPlayYourOwnPits: "Sadece sana ait olan kuyular ile oynayabilirsin",
UMustWaitUntilCurrentMoveComplete: "Devam eden haraketin bitmesini beklemelisin",
UCanNotPlayEmptyPit: "Boş kuyu ile oynayamazsın",
AreYouSureToLeaveGame: "Oyundan ayrılmak istediğine emin misin?",
Yes: "Evet",
Cancel: "İptal",
Help: "Yardım",
WebApp: "Web Uygulamasına Git",
Privacy: "Gizlilik Politikasını Göster"
};

View File

@ -2,5 +2,6 @@ import * as React from 'react';
import { createRoot } from 'react-dom/client';
const container = document.getElementById('main');
const root = createRoot(container!);
import './localization/i18n';
import MancalaApp from './MancalaApp';
root.render(<MancalaApp/>);

View File

@ -12,17 +12,20 @@ import Home from './routes/Home';
import { initContext } from './context/context';
import { RTMTWS, ConnectionState } from '@mancala/core';
import { getColorByBrightness } from './util/ColorUtil';
import { Theme } from './theme/Theme';
import { Theme } from '@mancala/core';
import LobyPage from './routes/LobyPage';
import PrivacyPage from './routes/PrivacyPage';
import swal from 'sweetalert';
import Util from './util/Util';
import { server } from './const/config';
import { useTranslation } from 'react-i18next';
const context = initContext();
const MancalaApp: FunctionComponent = () => {
const { t } = useTranslation();
const [userKey, setUserKey] = useState<string | undefined>(undefined);
const [connectionState, setConnetionState] = useState<ConnectionState>("connecting");
@ -50,7 +53,7 @@ const MancalaApp: FunctionComponent = () => {
connectRTMT(userKey);
}).catch((error) => {
//TODO: check if it is network error!
swal(context.texts.Error + "!", context.texts.ErrorWhenRetrievingInformation, "error");
swal(t("Error") + "!", t("ErrorWhenRetrievingInformation"), "error");
console.error(error);
});
}
@ -88,7 +91,7 @@ const MancalaApp: FunctionComponent = () => {
</Routes>
</BrowserRouter>
<FloatingPanel context={context} color={context.themeManager.theme.boardColor} visible={connectionState != "connected"}>
<span style={{ color: textColorOnBoard, transition: 'color 0.5s' }}>{Util.getTextByConnectionState(context, connectionState)}</span>
<span style={{ color: textColorOnBoard, transition: 'color 0.5s' }}>{Util.getTextByConnectionState(context, connectionState, t)}</span>
</FloatingPanel>
</>
);

View File

@ -4,9 +4,11 @@ import { Context } from "../context/context";
import { Game, User } from "@mancala/core";
import { getColorByBrightness } from "../util/ColorUtil";
import CircularPanel from "./CircularPanel";
import { useTranslation } from "react-i18next";
function getInfoPanelTextByGameState(params: {
context: Context;
t: (text: string) => string;
game?: Game;
currentUser: User;
whitePlayer: User;
@ -16,6 +18,7 @@ function getInfoPanelTextByGameState(params: {
}): string | undefined {
const {
context,
t,
game,
currentUser,
whitePlayer,
@ -25,8 +28,8 @@ function getInfoPanelTextByGameState(params: {
} = params;
if (leftPlayer) {
return isSpectator ? `${leftPlayer.name} ${context.texts.UserLeftTheGame}` :
leftPlayer.id == currentUser.id ? context.texts.YouLeftTheGame : context.texts.OpponentLeftTheGame;
return isSpectator ? `${leftPlayer.name} ${t("UserLeftTheGame")}` :
leftPlayer.id == currentUser.id ? t("YouLeftTheGame") : t("OpponentLeftTheGame");
}
const isGameEnded = game?.mancalaGame.state == "ended";
@ -35,21 +38,21 @@ function getInfoPanelTextByGameState(params: {
let whoWon;
if (wonPlayerID) {
const wonPlayer = wonPlayerID == whitePlayer.id ? whitePlayer : blackPlayer;
whoWon = isSpectator ? `${wonPlayer.name} ${context.texts.Won}` :
whoWon = isSpectator ? `${wonPlayer.name} ${t("Won")}` :
game.mancalaGame.getWonPlayerId() === currentUser.id
? context.texts.YouWon
: context.texts.YouLost;
? t("YouWon")
: t("YouLost");
} else {
whoWon = context.texts.GameDraw;
whoWon = t("GameDraw");
}
return context.texts.GameEnded + " " + whoWon;
return t("GameEnded") + " " + whoWon;
}
if (game) {
const playingPlayer = game.mancalaGame.checkIsPlayerTurn(whitePlayer.id) ? whitePlayer : blackPlayer;
return isSpectator ? `${playingPlayer.name} ${context.texts.Playing}` : game.mancalaGame.checkIsPlayerTurn(currentUser.id)
? context.texts.YourTurn
: context.texts.OpponentTurn;
return isSpectator ? `${playingPlayer.name} ${t("Playing")}` : game.mancalaGame.checkIsPlayerTurn(currentUser.id)
? t("YourTurn")
: t("OpponentTurn");
}
return undefined;
@ -76,6 +79,9 @@ const InfoPanel: FunctionComponent<{
visible,
isSpectator
}) => {
const { t } = useTranslation();
if (visible === false) return <></>;
const isUserTurn = currentUser.id ? game?.mancalaGame.checkIsPlayerTurn(currentUser.id) : false;
const containerColor = isUserTurn
@ -88,6 +94,7 @@ const InfoPanel: FunctionComponent<{
);
const text = getInfoPanelTextByGameState({
context,
t,
game,
currentUser,
whitePlayer,

View File

@ -4,8 +4,12 @@ import { Context } from '../context/context';
import { LoadingState } from "@mancala/core";
import { getColorByBrightness } from '../util/ColorUtil';
import CircularPanel from './CircularPanel';
import { useTranslation } from 'react-i18next';
const LoadingComponent: FunctionComponent<{ context: Context, loadingState: LoadingState<any> }> = ({ context, loadingState }) => {
const { t } = useTranslation();
if (loadingState.isUnset() || loadingState.isLoaded()) {
return <></>
}
@ -15,7 +19,7 @@ const LoadingComponent: FunctionComponent<{ context: Context, loadingState: Load
context.themeManager.theme.textColor,
context.themeManager.theme.textLightColor
);
const text = loadingState.isLoading() ? context.texts.Loading +"..." : loadingState.errorMessage;
const text = loadingState.isLoading() ? t("Loading") +"..." : loadingState.errorMessage;
return (
<CircularPanel color={context.themeManager.theme.boardColor}>
<h4 style={{ margin: "0", color: textColorOnBoard }}>{`${text}`}</h4>

View File

@ -4,6 +4,7 @@ import { Context } from '../context/context';
import { User } from "@mancala/core";
import { getColorByBrightness } from '../util/ColorUtil';
import Space from './Space';
import { useTranslation } from 'react-i18next';
export type LayoutMode = "right" | "left";
@ -15,6 +16,9 @@ const UserStatus: FunctionComponent<{
style?: React.CSSProperties
}> = ({ context, user, layoutMode, visible, style }) => {
if (visible === false) return <></>;
const { t } = useTranslation();
const textColorOnBoard = getColorByBrightness(
context.themeManager.theme.background,
context.themeManager.theme.textColor,
@ -22,7 +26,7 @@ const UserStatus: FunctionComponent<{
);
return (
<div style={style} className={layoutMode === "right" ? "flex-rtl" : "flex-ltr"}>
<span style={{color: textColorOnBoard, transition: 'color 0.5s'}} className='text'>{user.isAnonymous ? context.texts.Anonymous : user.name}</span>
<span style={{color: textColorOnBoard, transition: 'color 0.5s'}} className='text'>{user.isAnonymous ? t("Anonymous") : user.name}</span>
<Space width='5px' />
<div className={"circle " + (user.isOnline ? "online" : "offline")}></div>
<style jsx>{`

View File

@ -1,6 +1,5 @@
import * as React from 'react';
import { FunctionComponent } from 'react';
import { Context } from '../../context/context';
const HeaderbarTitle: FunctionComponent<{ title: string, color: string }> = ({ title, color }) => {
return (

View File

@ -1,114 +0,0 @@
export type Texts = {
Mancala: string,
Leave: string,
NewGame: string,
YourTurn: string,
OpponentTurn: string,
GameEnded: string,
InternalErrorOccurred: string,
YouWon: string,
Won: string,
YouLost: string,
Connecting: string,
Connected: string,
CannotConnect: string,
ConnectionLost: string,
ConnectingAgain: string,
ServerError: string,
SearchingOpponet: string,
OpponentLeftTheGame: string,
YouLeftTheGame: string,
UserLeftTheGame: string,
SearchingOpponent: string,
PleaseWait: string,
GameDraw: string,
Anonymous: string,
GameNotFound: string,
Loading: string,
Playing: string,
Error: string,
ErrorWhenRetrievingInformation: string,
UCanOnlyPlayYourOwnPits: string,
UMustWaitUntilCurrentMoveComplete: string,
UCanNotPlayEmptyPit: string,
AreYouSureToLeaveGame: string,
Yes: string,
Cancel: string,
}
export const EnUs: Texts = {
Mancala: "Mancala",
Leave: "Leave The Game",
NewGame: "New Game",
YourTurn: "Your Turn",
OpponentTurn: "Opponent Turn",
GameEnded: "Game Ended",
InternalErrorOccurred: "An internal error has occurred",
YouWon: "You Won",
Won: "Won",
YouLost: "You Lost",
Connecting: "Connecting",
Connected: "Connected",
CannotConnect: "Can't Connect",
ConnectionLost: "Network Connection Lost",
ConnectingAgain: "Connecting Again",
ServerError: "Server Error",
SearchingOpponet: "Searching Opponet",
OpponentLeftTheGame: "Opponent Leaves The Game",
YouLeftTheGame: "You Left The Game",
UserLeftTheGame: "Left The Game",
SearchingOpponent: "Searching Opponent",
PleaseWait: "Please Wait",
GameDraw: "Draw",
Anonymous: "Anonymous",
GameNotFound: "Game Not Found",
Loading: "Loading",
Playing: "Playing",
Error: "Error",
ErrorWhenRetrievingInformation: "An error occured when retrieving information!",
UCanOnlyPlayYourOwnPits: "You can only play your own pits",
UMustWaitUntilCurrentMoveComplete: "You must wait until the current move is complete",
UCanNotPlayEmptyPit: "You can not play empty pit",
AreYouSureToLeaveGame: "Are you sure to leave game?",
Yes: "Yes",
Cancel: "Cancel",
}
export const TrTr: Texts = {
Mancala: "Köçürme",
Leave: "Oyundan Ayrıl",
NewGame: "Yeni Oyun",
YourTurn: "Sıra Sende",
OpponentTurn: "Sıra Rakipte",
GameEnded: "Oyun Bitti",
InternalErrorOccurred: "Dahili bir hata oluştu",
YouWon: "Kazandın",
Won: "Kazandı",
YouLost: "Kaybettin",
Connecting: "Bağlanılıyor",
Connected: "Bağlandı",
CannotConnect: "Bağlanılamadı",
ConnectionLost: "Ağ Bağlantısı Koptu",
ConnectingAgain: "Tekrar Bağlanılıyor",
ServerError: "Sunucu Hatası",
SearchingOpponet: "Rakip Aranıyor",
OpponentLeftTheGame: "Rakip Oyundan Ayrıldı",
YouLeftTheGame: "Sen Oyundan Ayrıldın",
UserLeftTheGame: "Oyundan Ayrıldı",
SearchingOpponent: "Rakip Aranıyor",
PleaseWait: "Lütfen Bekleyin",
GameDraw: "Berabere",
Anonymous: "Anonim",
GameNotFound: "Oyun Bulunamadı",
Loading: "Yükleniyor",
Playing: "Oynuyor",
Error: "Hata",
ErrorWhenRetrievingInformation: "Bilgiler toplanırken bir hata oluştu!",
UCanOnlyPlayYourOwnPits: "Sadece sana ait olan kuyular ile oynayabilirsin",
UMustWaitUntilCurrentMoveComplete: "Devam eden haraketin bitmesini beklemelisin",
UCanNotPlayEmptyPit: "Boş kuyu ile oynayamazsın",
AreYouSureToLeaveGame: "Oyundan ayrılmak istediğine emin misin?",
Yes: "Evet",
Cancel: "İptal"
}

View File

@ -1,5 +1,4 @@
import { server } from "../const/config";
import { Texts, TrTr } from "../const/texts";
import { RTMT, RTMTWS, ThemeManager } from "@mancala/core";
import { HttpServiceImpl } from "../service/HttpService";
import { GameStore, GameStoreImpl } from "../store/GameStore";
@ -10,7 +9,6 @@ import { Storage } from '@mancala/core'
export type Context = {
rtmt: RTMT;
userKeyStore: UserKeyStore;
texts: Texts;
themeManager: ThemeManager;
gameStore: GameStore;
storage: Storage;
@ -21,13 +19,11 @@ export const initContext = (): Context => {
const httpService = new HttpServiceImpl(server.serverAdress);
const userKeyStore = new UserKeyStoreImpl({ httpService });
const gameStore = new GameStoreImpl({ httpService });
const texts = TrTr;
const storage = new LocalStorage();
const themeManager = new ThemeManager(storage);
return {
rtmt: rtmt,
userKeyStore: userKeyStore,
texts: texts,
themeManager,
gameStore,
storage

View File

@ -0,0 +1,24 @@
// https://medium.com/@yashpalraj/implement-i18n-in-react-native-application-a4c573e2e2a6
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { en, tr } from '@mancala/core';
const resources = { // list of languages
en: {
translation: en
},
tr: {
translation: tr
}
};
i18n.use(initReactI18next) // passes i18n down to react-i18next
.init({
compatibilityJSON: 'v3', //To make it work for Android devices, add this line.
resources,
lng: 'en', // default language to use.
// if you're using a language detector, do not define the lng option
interpolation: {
escapeValue: false,
},
});
export default i18n;

View File

@ -21,13 +21,14 @@ import { channel_on_game_update, channel_on_game_crashed, channel_on_game_user_l
import { Context } from '../context/context';
import useWindowDimensions from '../hooks/useWindowDimensions';
import { GameMove, LoadingState, Game, GameUsersConnectionInfo } from "@mancala/core";
import { Theme } from '../theme/Theme';
import { Theme } from '@mancala/core';
import { getColorByBrightness } from '../util/ColorUtil';
import BoardViewModel from '../viewmodel/BoardViewModel';
import Center from '../components/Center';
import notyf from '../util/Notyf';
import swal from 'sweetalert';
import Util from '../util/Util';
import { useTranslation } from 'react-i18next';
const GamePage: FunctionComponent<{
context: Context,
@ -56,6 +57,8 @@ const GamePage: FunctionComponent<{
const navigate = useNavigate();
const { t } = useTranslation();
const [gameLoadingState, setLoadingStateGame] = useState<LoadingState<Game>>(LoadingState.Unset());
@ -88,7 +91,7 @@ const GamePage: FunctionComponent<{
}
const onGameCrashed = (message: any) => {
const newCrashMessage = message as string;
notyf.error(context.texts.InternalErrorOccurred);
notyf.error(t("InternalErrorOccurred"));
console.error("on_game_crash");
console.error(newCrashMessage);
}
@ -136,11 +139,11 @@ const GamePage: FunctionComponent<{
const checkHasAnOngoingAction = () => hasOngoingAction;
const onLeaveGameClick = () => {
if (Util.checkConnectionAndMaybeAlert(context)) return;
if (Util.checkConnectionAndMaybeAlert(context, t)) return;
swal({
title: context.texts.AreYouSureToLeaveGame,
title: t("AreYouSureToLeaveGame"),
icon: "warning",
buttons: [context.texts.Yes, context.texts.Cancel],
buttons: [t("Yes"), t("Cancel")],
dangerMode: true,
})
.then((cancel) => {
@ -151,7 +154,7 @@ const GamePage: FunctionComponent<{
};
const onNewGameClick = () => {
if (Util.checkConnectionAndMaybeAlert(context)) return;
if (Util.checkConnectionAndMaybeAlert(context, t)) return;
navigate("/loby")
};
@ -160,31 +163,31 @@ const GamePage: FunctionComponent<{
return;
}
if(userKeyWhoLeave) {
notyf.error(context.texts.GameEnded);
notyf.error(t("GameEnded"));
return;
}
if(game.mancalaGame.state === "ended") {
notyf.error(context.texts.GameEnded);
notyf.error(t("GameEnded"));
return;
}
if (Util.checkConnectionAndMaybeAlert(context)) return;
if (Util.checkConnectionAndMaybeAlert(context, t)) return;
if (game.mancalaGame.getPlayerIdByIndex(index) !== userKey) {
notyf.error(context.texts.UCanOnlyPlayYourOwnPits);
notyf.error(t("UCanOnlyPlayYourOwnPits"));
return;
}
const pitIndexForUser = index % (game.mancalaGame.board.totalPitCount() / 2);
if (!game.mancalaGame.canPlayerMove(userKey, pitIndexForUser)) {
notyf.error(context.texts.OpponentTurn);
notyf.error(t("OpponentTurn"));
return;
}
if (checkHasAnOngoingAction()) {
notyf.error(context.texts.UMustWaitUntilCurrentMoveComplete);
notyf.error(t("UMustWaitUntilCurrentMoveComplete"));
return;
}
if (!boardViewModel) return;
//TODO: this check should be in mancala.js
if (pit.stoneCount === 0) {
notyf.error(context.texts.UCanNotPlayEmptyPit);
notyf.error(t("UCanNotPlayEmptyPit"));
return;
}
setHasOngoingAction(true);
@ -207,7 +210,7 @@ const GamePage: FunctionComponent<{
unlistenMessages = listenMessages(game, pitAnimator);
setLoadingStateGame(LoadingState.Loaded({ value: game }))
} else {
setLoadingStateGame(LoadingState.Error({ errorMessage: context.texts.GameNotFound }))
setLoadingStateGame(LoadingState.Error({ errorMessage: t("GameNotFound") }))
}
})
return () => {
@ -273,7 +276,7 @@ const GamePage: FunctionComponent<{
<HeaderbarIcon />
</Link>
<Link style={{ textDecoration: 'none' }} to={"/"}>
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
<HeaderbarTitle title={t("Mancala")} color={textColorOnAppBar} />
</Link>
</Row>
<Row>
@ -281,7 +284,7 @@ const GamePage: FunctionComponent<{
<Button
context={context}
color={context.themeManager.theme.pitColor}
text={renderNewGameBtn ? context.texts.NewGame : context.texts.Leave}
text={renderNewGameBtn ? t("NewGame") : t("Leave")}
onClick={renderNewGameBtn ? onNewGameClick : onLeaveGameClick} />
</Row>
</HeaderBar>;

View File

@ -1,7 +1,7 @@
import * as React from "react";
import { FunctionComponent, useEffect, useState } from "react";
import { getColorByBrightness } from "../util/ColorUtil";
import { Theme } from "../theme/Theme";
import { Theme } from "@mancala/core";
import HeaderBar from "../components/headerbar/HeaderBar";
import PageContainer from "../components/PageContainer";
import Row from "../components/Row";
@ -12,6 +12,7 @@ import Button from "../components/Button";
import { Context } from "../context/context";
import { Link, useNavigate } from "react-router-dom";
import Util from "../util/Util";
import { useTranslation } from "react-i18next";
const Home: FunctionComponent<{
context: Context,
@ -21,8 +22,10 @@ const Home: FunctionComponent<{
const navigate = useNavigate();
const { t } = useTranslation();
const onNewGameClick = () => {
if(Util.checkConnectionAndMaybeAlert(context)) return;
if(Util.checkConnectionAndMaybeAlert(context, t)) return;
navigate("/loby")
};
@ -39,7 +42,7 @@ const Home: FunctionComponent<{
<HeaderbarIcon />
</Link>
<Link style={{ textDecoration: 'none' }} to={"/"}>
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
<HeaderbarTitle title={t("Mancala")} color={textColorOnAppBar} />
</Link>
</Row>
<Row>
@ -47,7 +50,7 @@ const Home: FunctionComponent<{
<Button
context={context}
color={context.themeManager.theme.pitColor}
text={context.texts.NewGame}
text={t("NewGame")}
onClick={onNewGameClick} />
</Row>
</HeaderBar>

View File

@ -12,9 +12,10 @@ import PageContainer from '../components/PageContainer';
import Row from '../components/Row';
import { channel_cancel_new_game, channel_on_game_start } from '@mancala/core';
import { Context } from '../context/context';
import { Theme } from '../theme/Theme';
import { Theme } from '@mancala/core';
import { getColorByBrightness } from '../util/ColorUtil';
import Button from "../components/Button";
import { useTranslation } from 'react-i18next';
const LobyPage: FunctionComponent<{
context: Context,
@ -24,6 +25,8 @@ const LobyPage: FunctionComponent<{
let navigate = useNavigate();
const { t } = useTranslation();
const onGameStart = (message: Object) => {
const newGame: CommonMancalaGame = message as CommonMancalaGame;
navigate(`/game/${newGame.id}`)
@ -61,7 +64,7 @@ const LobyPage: FunctionComponent<{
<HeaderbarIcon />
</Link>
<Link style={{ textDecoration: 'none' }} to={"/"}>
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
<HeaderbarTitle title={t("Mancala")} color={textColorOnAppBar} />
</Link>
</Row>
<Row>
@ -75,12 +78,12 @@ const LobyPage: FunctionComponent<{
alignContent: "center"
}}>
<CircularPanel color={context.themeManager.theme.boardColor}>
<h4 style={{ margin: "0", color: textColorOnBoard }}>{`${context.texts.SearchingOpponent} ${context.texts.PleaseWait}...`}</h4>
<h4 style={{ margin: "0", color: textColorOnBoard }}>{`${t("SearchingOpponent")} ${t("PleaseWait")}...`}</h4>
</CircularPanel>
<Button
context={context}
color={context.themeManager.theme.boardColor}
text={context.texts.Cancel}
text={t("Cancel")}
onClick={onCancelNewGameClick} />
</div>

View File

@ -8,8 +8,9 @@ import ThemeSwitchMenu from '../components/headerbar/ThemeSwitchMenu';
import PageContainer from '../components/PageContainer';
import Row from '../components/Row';
import { Context } from '../context/context';
import { Theme } from '../theme/Theme';
import { Theme } from '@mancala/core';
import { getColorByBrightness } from '../util/ColorUtil';
import { useTranslation } from 'react-i18next';
const PrivacyPage: FunctionComponent<{
context: Context,
@ -17,6 +18,8 @@ const PrivacyPage: FunctionComponent<{
theme: Theme
}> = ({ context, userKey, theme }) => {
const { t } = useTranslation();
const textColorOnAppBar = getColorByBrightness(
context.themeManager.theme.appBarBgColor,
context.themeManager.theme.textColor,
@ -35,7 +38,7 @@ const PrivacyPage: FunctionComponent<{
<HeaderbarIcon />
</Link>
<Link style={{ textDecoration: 'none' }} to={"/"}>
<HeaderbarTitle title={context.texts.Mancala} color={textColorOnAppBar} />
<HeaderbarTitle title={t("Mancala")} color={textColorOnAppBar} />
</Link>
</Row>
<Row>

View File

@ -1,5 +1,5 @@
import { Context } from "../context/context";
import { ConnectionState } from "../rtmt/rtmt";
import { ConnectionState } from "@mancala/core";
import notyf from "./Notyf";
export default class Util {
@ -11,21 +11,21 @@ export default class Util {
return ans;
}
public static checkConnectionAndMaybeAlert(context: Context): boolean {
public static checkConnectionAndMaybeAlert(context: Context, t: (text: string) => string): boolean {
if (context.rtmt.connectionState !== "connected") {
notyf.error(context.texts.ConnectionLost);
notyf.error(t("ConnectionLost"));
return true;
}
return false;
}
public static getTextByConnectionState(context: Context, connectionState: ConnectionState): string {
public static getTextByConnectionState(context: Context, connectionState: ConnectionState, t: (text: string) => string): string {
const map: { [key: string]: string } = {
connecting: context.texts.Connecting,
connected: context.texts.Connected,
error: context.texts.CannotConnect,
closed: context.texts.ConnectingAgain,
reconnecting: context.texts.ConnectingAgain,
connecting: t("Connecting"),
connected: t("Connected"),
error: t("CannotConnect"),
closed: t("ConnectingAgain"),
reconnecting: t("ConnectingAgain"),
};
return map[connectionState];
}

View File

@ -1,42 +0,0 @@
export default {
translation: {
Mancala: "Mancala",
Leave: "Leave The Game",
NewGame: "New Game",
YourTurn: "Your Turn",
OpponentTurn: "Opponent Turn",
GameEnded: "Game Ended",
InternalErrorOccurred: "An internal error has occurred",
YouWon: "You Won",
Won: "Won",
YouLost: "You Lost",
Connecting: "Connecting",
Connected: "Connected",
CannotConnect: "Can't Connect",
ConnectionLost: "Network Connection Lost",
ConnectingAgain: "Connecting Again",
ServerError: "Server Error",
SearchingOpponet: "Searching Opponet",
OpponentLeftTheGame: "Opponent Leaves The Game",
YouLeftTheGame: "You Left The Game",
UserLeftTheGame: "Left The Game",
SearchingOpponent: "Searching Opponent",
PleaseWait: "Please Wait",
GameDraw: "Draw",
Anonymous: "Anonymous",
GameNotFound: "Game Not Found",
Loading: "Loading",
Playing: "Playing",
Error: "Error",
ErrorWhenRetrievingInformation: "An error occured when retrieving information!",
UCanOnlyPlayYourOwnPits: "You can only play your own pits",
UMustWaitUntilCurrentMoveComplete: "You must wait until the current move is complete",
UCanNotPlayEmptyPit: "You can not play empty pit",
AreYouSureToLeaveGame: "Are you sure to leave game?",
Yes: "Yes",
Cancel: "Cancel",
Help: "Help",
WebApp: "Goto WebApp",
Privacy: "Open Privacy Policy "
}
};

View File

@ -2,11 +2,14 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './en';
import tr from './tr';
import { en, tr } from '@mancala/core';
const resources = { // list of languages
en,
tr,
en: {
translation: en
},
tr: {
translation: tr
}
};
i18n.use(initReactI18next) // passes i18n down to react-i18next
.init({

View File

@ -1,42 +0,0 @@
export default {
translation: {
Mancala: "Köçürme",
Leave: "Oyundan Ayrıl",
NewGame: "Yeni Oyun",
YourTurn: "Sıra Sende",
OpponentTurn: "Sıra Rakipte",
GameEnded: "Oyun Bitti",
InternalErrorOccurred: "Dahili bir hata oluştu",
YouWon: "Kazandın",
Won: "Kazandı",
YouLost: "Kaybettin",
Connecting: "Bağlanılıyor",
Connected: "Bağlandı",
CannotConnect: "Bağlanılamadı",
ConnectionLost: "Ağ Bağlantısı Koptu",
ConnectingAgain: "Tekrar Bağlanılıyor",
ServerError: "Sunucu Hatası",
SearchingOpponet: "Rakip Aranıyor",
OpponentLeftTheGame: "Rakip Oyundan Ayrıldı",
YouLeftTheGame: "Sen Oyundan Ayrıldın",
UserLeftTheGame: "Oyundan Ayrıldı",
SearchingOpponent: "Rakip Aranıyor",
PleaseWait: "Lütfen Bekleyin",
GameDraw: "Berabere",
Anonymous: "Anonim",
GameNotFound: "Oyun Bulunamadı",
Loading: "Yükleniyor",
Playing: "Oynuyor",
Error: "Hata",
ErrorWhenRetrievingInformation: "Bilgiler toplanırken bir hata oluştu!",
UCanOnlyPlayYourOwnPits: "Sadece sana ait olan kuyular ile oynayabilirsin",
UMustWaitUntilCurrentMoveComplete: "Devam eden haraketin bitmesini beklemelisin",
UCanNotPlayEmptyPit: "Boş kuyu ile oynayamazsın",
AreYouSureToLeaveGame: "Oyundan ayrılmak istediğine emin misin?",
Yes: "Evet",
Cancel: "İptal",
Help: "Yardım",
WebApp: "Web Uygulamasına Git",
Privacy: "Gizlilik Politikasını Göster"
}
};