From 604d600d0687853bba3492156766350faaab06ed Mon Sep 17 00:00:00 2001 From: Made Baruna Date: Sun, 14 Mar 2021 18:23:17 +0800 Subject: [PATCH] Add localization --- package.json | 2 + rollup.config.js | 4 + src/client.js | 4 + src/components/CalculatorHowToModal.svelte | 9 +- src/components/Header.svelte | 18 +- src/components/Sidebar/Sidebar.svelte | 43 +++ src/components/TodoAddModal.svelte | 12 +- src/components/TodoDeleteModal.svelte | 8 +- src/components/WishCounterHowToModal.svelte | 61 ++--- src/components/WishImportModal.svelte | 146 +++++----- src/i18n.js | 63 +++++ src/locales/en.json | 266 +++++++++++++++++++ src/locales/id.json | 266 +++++++++++++++++++ src/routes/calculator/_character.svelte | 95 ++++--- src/routes/calculator/_characterTable.svelte | 10 +- src/routes/calculator/_weapon.svelte | 67 +++-- src/routes/calculator/index.svelte | 14 +- src/routes/characters.svelte | 19 +- src/routes/items.svelte | 25 +- src/routes/settings/_deleteAccount.svelte | 10 +- src/routes/settings/_resetAccount.svelte | 10 +- src/routes/settings/index.svelte | 58 ++-- src/routes/timeline/_detail.svelte | 10 +- src/routes/timeline/index.svelte | 6 +- src/routes/todo.svelte | 18 +- src/routes/wish/_counter.svelte | 8 +- src/routes/wish/_firstTime.svelte | 10 +- src/routes/wish/_summary.svelte | 4 +- src/routes/wish/index.svelte | 10 +- src/server.js | 3 + static/images/locales/en.svg | 52 ++++ static/images/locales/id.svg | 18 ++ yarn.lock | 84 +++++- 33 files changed, 1156 insertions(+), 277 deletions(-) create mode 100644 src/i18n.js create mode 100644 src/locales/en.json create mode 100644 src/locales/id.json create mode 100644 static/images/locales/en.svg create mode 100644 static/images/locales/id.svg diff --git a/package.json b/package.json index 125cb951..adf5b578 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@rollup/plugin-babel": "^5.0.0", "@rollup/plugin-commonjs": "^16.0.0", "@rollup/plugin-dynamic-import-vars": "^1.1.0", + "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^10.0.0", "@rollup/plugin-replace": "^2.3.4", "@rollup/plugin-url": "^5.0.0", @@ -37,6 +38,7 @@ "rollup-plugin-terser": "^7.0.0", "sapper": "^0.28.0", "svelte": "^3.17.3", + "svelte-i18n": "^3.3.6", "svelte-preprocess": "^4.5.1", "svelte-simple-modal": "^0.6.1", "tailwindcss": "^1.9.5" diff --git a/rollup.config.js b/rollup.config.js index 697900fb..21f56a33 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -6,6 +6,8 @@ import url from '@rollup/plugin-url'; import svelte from 'rollup-plugin-svelte'; import babel from '@rollup/plugin-babel'; import { terser } from 'rollup-plugin-terser'; +import json from '@rollup/plugin-json'; + import config from 'sapper/config/rollup.js'; import { config as envConfig } from 'dotenv'; @@ -50,6 +52,7 @@ export default { dedupe: ['svelte'], }), commonjs(), + json(), legacy && babel({ @@ -113,6 +116,7 @@ export default { dedupe: ['svelte'], }), commonjs(), + json(), ], external: Object.keys(pkg.dependencies).concat(require('module').builtinModules), diff --git a/src/client.js b/src/client.js index cec91725..071e75f3 100644 --- a/src/client.js +++ b/src/client.js @@ -1,5 +1,9 @@ import * as sapper from '@sapper/app'; +import { startClient } from './i18n.js'; + +startClient(); + sapper.start({ target: document.querySelector('#sapper') }); \ No newline at end of file diff --git a/src/components/CalculatorHowToModal.svelte b/src/components/CalculatorHowToModal.svelte index de53be11..b0763b01 100644 --- a/src/components/CalculatorHowToModal.svelte +++ b/src/components/CalculatorHowToModal.svelte @@ -1,5 +1,6 @@ @@ -8,16 +9,16 @@ -

Click the picture to maximize

+

{$t('calculator.guide.clickToMaximize')}

-

How to use the Weapon Calculator

+

{$t('calculator.guide.howToWeapon')}

how to use calculator weapon
-

How to use the Character Calculator

+

{$t('calculator.guide.howToCharacter')}

how to use calculator character diff --git a/src/components/Header.svelte b/src/components/Header.svelte index 9b2fc529..45dfad2f 100644 --- a/src/components/Header.svelte +++ b/src/components/Header.svelte @@ -9,6 +9,15 @@ } + + - - -

- Paimon.moe -

-
- -
-
diff --git a/src/components/Sidebar/Sidebar.svelte b/src/components/Sidebar/Sidebar.svelte index 307358c0..467b1e6b 100644 --- a/src/components/Sidebar/Sidebar.svelte +++ b/src/components/Sidebar/Sidebar.svelte @@ -2,6 +2,7 @@ import { fly } from 'svelte/transition'; import { getContext } from 'svelte'; import { mdiCloseCircle } from '@mdi/js'; + import { locale } from 'svelte-i18n'; import Icon from '../Icon.svelte'; @@ -18,6 +19,13 @@ export let segment; export let mobile = false; + const languages = [ + { id: 'en', label: 'English' }, + { id: 'id', label: 'Indonesia' }, + ]; + $: locales = languages.filter((e) => e.id !== $locale.substring(0, 2)); + $: currentLocale = languages.find((e) => e.id === $locale.substring(0, 2)); + function openDonationModal() { openModal( DonateModal, @@ -32,6 +40,10 @@ function close() { showSidebar.set(false); } + + function changeLocale(lang) { + locale.set(lang); + }
+
+ {currentLocale.label} + {currentLocale.label} +
+ {#each locales as locale} +
changeLocale(locale.id)} + > + {locale.label} + {locale.label} +
+
+ {/each} +
+
- + +
diff --git a/src/components/WishCounterHowToModal.svelte b/src/components/WishCounterHowToModal.svelte index 067c5a48..9107016e 100644 --- a/src/components/WishCounterHowToModal.svelte +++ b/src/components/WishCounterHowToModal.svelte @@ -1,4 +1,6 @@
-

Wish Counter Help & Settings

+

{$t('wish.help.title')}

Enable Manual Input{$t('wish.help.enableManual')}
-

- Using the Auto Import and manual input together is not recommended, still need some testing! -

-

Consider using the Auto Import first, access it on button beside the button you click to open this How To

+

{$t('wish.help.notice')}

+

{$t('wish.help.consider')}

-

How to use manual input

+

{$t('wish.help.howto.title')}

-

After you do 1 pull Wish:

+

{$t('wish.help.howto.subtitle')}

- Press + {$t('wish.help.howto.press')} +1 - when you get + {$t('wish.help.howto.whenYouGet')} 3

- Press + {$t('wish.help.howto.press')} Get 4 - when you get + {$t('wish.help.howto.whenYouGet')} 4

- Press + {$t('wish.help.howto.press')} Get 5 - when you get + {$t('wish.help.howto.whenYouGet')} 5

- It will automatically add the lifetime pulls, + {$t('wish.help.howto.p1')} 5 - and + {$t('wish.help.howto.and')} 4

- When the + {$t('wish.help.howto.p2.0')} 4 - pity reach 10, it will automatically reset to 0 + {$t('wish.help.howto.p2.1')}

- When the + {$t('wish.help.howto.p3.0')} 5 - pity reach 90, it will automatically reset to 0 + {$t('wish.help.howto.p3.1')}

- For when you do 10 pulls Wish, press the + {$t('wish.help.howto.p4.0')} +10 - button, - but the pity counter won't be accurate, because there is no way to tell when the drop occur (maybe you got it on - the 1st or even the 10th). To make the counter still accurate, you need to check it on the history table and add - it 1 by 1 like you do 1 pull Wish. + {$t('wish.help.howto.p4.1')}
- You can also press + {$t('wish.help.howto.p5.0')} - button to edit the values manually! + {$t('wish.help.howto.p5.1')}
- Press the arrow on the bottom to see your pulls detail. A popup will show when you get 5 - or + {$t('wish.help.howto.p6.1')} 4 . Or you can add or edit the table manually. + >. {$t('wish.help.howto.p6.2')}
diff --git a/src/components/WishImportModal.svelte b/src/components/WishImportModal.svelte index d42779d0..ee784cf2 100644 --- a/src/components/WishImportModal.svelte +++ b/src/components/WishImportModal.svelte @@ -1,4 +1,6 @@ {#if processingLog} -

Import Wish History

+

{$t('wish.import.title')}

{#if finishedProcessingLog} @@ -462,24 +464,24 @@ {numberFormat.format(wishes[code].length)} {:else} - No New Wishes + {$t('wish.import.nonew')} {/if} {/each}
-

Imported wishes will be appended or replaced accordingly to existing data

-

If you don't have any data saved before, first wish will be counted as pity 1

-

Save the data?

+

{$t('wish.import.importNotice1')}

+

{$t('wish.import.importNotice2')}

+

{$t('wish.import.saveData')}

{:else if calculatingPity} - Re-calculating pity... + {$t('wish.import.reCalculating')} {:else if fetchingWishes}
-

{`Processing ${currentBanner} Banner`}

-

{`Page ${currentPage}`}

+

{$t('wish.import.processing')} {currentBanner} {$t('wish.import.banner')}

+

{$t('wish.import.page')} {currentPage}

@@ -501,79 +503,65 @@
{:else} - Parsing... + {$t('wish.import.parsing')} {/if}
{#if finishedProcessingLog && !calculatingPity} - + {/if} - +
{:else}
{#if showFaq} -

Import Wish History FAQS

+

{$t('wish.import.faqs.title')}

-

How does it work?

+

{$t('wish.import.faqs.q1')}

+

{$t('wish.import.faqs.a1')}

+

{$t('wish.import.faqs.q2')}

+

{$t('wish.import.faqs.a2')}

+

{$t('wish.import.faqs.q3')}

- Genshin Impact wish history is basically a web page, so you can access it by opening the web page url. A - temporary key will be generated after you open the wish history page or the feedback page, and the importer - will automatically use the MiHoYo API to fetch your wish history. -

-

Is it safe? Will I get banned?

-

- Paimon.moe use the same request that Genshin Impact use to get the wish history, and Paimon.moe has no way - whatsoever to modify any game files or memory, and it should be safe. But use it at your own risk (well I use - it on my main account). You still can input your data manually πŸ˜€. -

-

Can you hack my account then?

-

- Paimon.moe never save anything related to your account (even your uid or nickname), so the answer is no. This - project is open source on + {$t('wish.import.faqs.a3.0')} Github, I'm not planning to damage my reputation by hacking other people account. -

-

- Hey I checked the request and stuff, but why it request to your domain instead of MiHoYo API? + >{$t('wish.import.faqs.a3.1')}

+

{$t('wish.import.faqs.q4')}

- Paimon.moe cannot request directly to MiHoYo API because of + {$t('wish.import.faqs.a4.0')} CORS, so the request redirected to a simple cors proxy to make it work. You can see the code + >{$t('wish.import.faqs.a4.1')} here{$t('wish.import.faqs.a4.2')}

-

Do you store my temporary key or wish history?

+

{$t('wish.import.faqs.q5')}

- Paimon.moe never store your key, and use HTTPS to pass your url to a cors proxy to make the CORS works. All - your wish history is saved on your device only (or your google drive if you turn on sync on setting). - Paimon.moe does not save anything to the server (yes anything). + {$t('wish.import.faqs.a5')}

-

I tried the step, but I got some API error?

-

- Make sure you copy all the text (just hold and press select all), maybe you left over some text that are - needed for the importer to work -

+

{$t('wish.import.faqs.q6')}

+

{$t('wish.import.faqs.a6')}

{:else}
-

Import Wish History

+

{$t('wish.import.title')}

@@ -599,13 +587,13 @@ {#if selectedType === 'pc'}
    -
  1. Open Paimon menu [ESC]
  2. -
  3. Click Feedback
  4. -
  5. Wait for it to load and a browser page should open
  6. -
  7. Copy & paste the link to the textbox below
  8. +
  9. {$t('wish.import.guide.pc.0')}
  10. +
  11. {$t('wish.import.guide.pc.1')}
  12. +
  13. {$t('wish.import.guide.pc.2')}
  14. +
  15. {$t('wish.import.guide.pc.3')}
- + {:else if selectedType === 'pclocal'}
    @@ -624,33 +612,31 @@ {:else if selectedType === 'android'}
      -
    1. Open Paimon menu
    2. -
    3. Press Feedback
    4. -
    5. Wait for it to load and a feedback page should open
    6. -
    7. Turn off your wifi and data connection
    8. -
    9. Press refresh on top right corner
    10. -
    11. The page should error and show you a text with black font
    12. -
    13. - Hold the text and press select all, then copy that text (don't copy only some portion of the text) -
    14. -
    15. Turn on your wifi or data connection
    16. -
    17. Paste the text to the textbox below
    18. +
    19. {$t('wish.import.guide.android.0')}
    20. +
    21. {$t('wish.import.guide.android.1')}
    22. +
    23. {$t('wish.import.guide.android.2')}
    24. +
    25. {$t('wish.import.guide.android.3')}
    26. +
    27. {$t('wish.import.guide.android.4')}
    28. +
    29. {$t('wish.import.guide.android.5')}
    30. +
    31. {$t('wish.import.guide.android.6')}
    32. +
    33. {$t('wish.import.guide.android.7')}
    34. +
    35. {$t('wish.import.guide.android.8')}
    - + {:else if selectedType === 'ios'}
      -
    1. Open Paimon menu
    2. -
    3. Press Feedback
    4. -
    5. Wait for it to load and a feedback page should open
    6. -
    7. Press In-game issue
    8. -
    9. Press Co-Op Mode
    10. -
    11. There is a link on the bottom of the reply, press that
    12. -
    13. A browser should open up, copy the link and paste it below
    14. +
    15. {$t('wish.import.guide.ios.0')}
    16. +
    17. {$t('wish.import.guide.ios.1')}
    18. +
    19. {$t('wish.import.guide.ios.2')}
    20. +
    21. {$t('wish.import.guide.ios.3')}
    22. +
    23. {$t('wish.import.guide.ios.4')}
    24. +
    25. {$t('wish.import.guide.ios.5')}
    26. +
    27. {$t('wish.import.guide.ios.6')}
    - + {/if} {/if} @@ -658,19 +644,19 @@ {#if !showFaq}
    - Import new wish only + {$t('wish.import.importNewWishOnly')} - Uncheck only if you need to re-import all your wish history + {$t('wish.import.importNewWishUncheck')}
    {/if}
    {#if !showFaq} - + {/if} - +
diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 00000000..07ee0390 --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,63 @@ +import { addMessages, init, getLocaleFromNavigator, locale as $locale } from 'svelte-i18n'; + +import en from './locales/en.json'; +import id from './locales/id.json'; + +const INIT_OPTIONS = { + fallbackLocale: 'en', + initialLocale: null, +}; + +let currentLocale = null; + +$locale.subscribe((value) => { + if (value == null) return; + + currentLocale = value; + + if (typeof window !== 'undefined') { + localStorage.setItem('locale', value); + } +}); + +addMessages('en', en); +addMessages('en-US', en); +addMessages('id', id); + +export function startClient() { + const savedLocale = localStorage.getItem('locale'); + + init({ + ...INIT_OPTIONS, + initialLocale: savedLocale !== null ? savedLocale : getLocaleFromNavigator(), + }); +} + +const DOCUMENT_REGEX = /(^([^.?#@]+)?([?#](.+)?)?|service-worker.*?\.html)$/; +export function i18nMiddleware() { + init(INIT_OPTIONS); + + return (req, res, next) => { + const isDocument = DOCUMENT_REGEX.test(req.originalUrl); + if (!isDocument) { + next(); + return; + } + + let locale = 'en'; + if (req.headers['accept-language']) { + const headerLang = req.headers['accept-language'].split(',')[0].trim(); + if (headerLang.length > 1) { + locale = headerLang; + } + } else { + locale = INIT_OPTIONS.initialLocale || INIT_OPTIONS.fallbackLocale; + } + + if (locale != null && locale !== currentLocale) { + $locale.set(locale); + } + + next(); + }; +} diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 00000000..5271b600 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,266 @@ +{ + "characters": { + "title": "Characters", + "subtitle": "Stat numbers are at level 80 Ascension 6. You can also click the table header to sort!", + "name": "Name", + "element": "Element", + "rarity": "Rarity", + "weapon": "Weapon", + "hp": "HP", + "atk": "ATK", + "def": "DEF" + }, + "wish": { + "autoImport": "Auto Import", + "helpAndSetting": "Help & Setting", + "wishesWorth": "Wishes Worth", + "lifetimePulls": "Lifetime Pulls", + "guarantee": "Guaranteed at {pity}", + "name": "Name", + "time": "Time", + "pity": "Pity", + "welcome": "Welcome to Paimon.moe Wish Counter! The recommended usage is to import your wish history with the Auto Importer.", + "welcomeStart1": "To start, press the", + "welcomeStart2": "button up there", + "manual": "If you want to manually input the data, you can enable it here:", + "manualButton": "Enable Manual Input", + "import": { + "title": "Import Wish History", + "faqsButton": "FAQS - READ FIRST", + "nonew": "No New Wishes", + "importNotice1": "Imported wishes will be appended or replaced accordingly to existing data", + "importNotice2": "If you don't have any data saved before, first wish will be counted as pity 1", + "saveData": "Save the data?", + "reCalculating": "Re-calculating pity...", + "processing": "Processing", + "banner": "Banner", + "page": "Page", + "parsing": "Parsing...", + "save": "Save", + "cancel": "Cancel", + "canceling": "Canceling...", + "importNewWishOnly": "Import new wish only", + "importNewWishUncheck": "Uncheck only if you need to re-import all your wish history", + "import": "Import", + "close": "Close", + "invalidLink": "Invalid link, please check it again", + "errorApi": "Error code returned from MiHoYo API, please try again later!", + "timeout": "Connection timeout, please wait a moment and try again later", + "invalidData": "Invalid data returned from API, try again later", + "success": "Import success πŸ˜€!", + "faqs": { + "title": "Import Wish History FAQS", + "q1": "How does it work?", + "a1": "Genshin Impact wish history is basically a web page, so you can access it by opening the web page url. A temporary key will be generated after you open the wish history page or the feedback page, and the importer will automatically use the MiHoYo API to fetch your wish history.", + "q2": "Is it safe? Will I get banned?", + "a2": "Paimon.moe use the same request that Genshin Impact use to get the wish history, and Paimon.moe has no way whatsoever to modify any game files or memory, and it should be safe. But use it at your own risk (well I use it on my main account). You still can input your data manually πŸ˜€.", + "q3": "Can you hack my account then?", + "a3": [ + "Paimon.moe never save anything related to your account (even your uid or nickname), so the answer is no. This project is open source on", + ", I'm not planning to damage my reputation by hacking other people account." + ], + "q4": "Hey I checked the request and stuff, but why it request to your domain instead of MiHoYo API?", + "a4": [ + "Paimon.moe cannot request directly to MiHoYo API because of", + ", so the request redirected to a simple cors proxy to make it work. You can see the code", + "here" + ], + "q5": "Do you store my temporary key or wish history?", + "a5": "Paimon.moe never store your key, and use HTTPS to pass your url to a cors proxy to make the CORS works. All your wish history is saved on your device only (or your google drive if you turn on sync on setting). Paimon.moe does not save anything to the server (yes anything).", + "q6": "I tried the step, but I got some API error?", + "a6": "Make sure you copy all the text (just hold and press select all), maybe you left over some text that are needed for the importer to work" + }, + "guide": { + "pc": [ + "Open Paimon menu [ESC]", + "Click Feedback", + "Wait for it to load and a browser page should open", + "Copy & paste the link to the textbox below", + "Paste link here... https://webstatic..." + ], + "android": [ + "Open Paimon menu", + "Press Feedback", + "Wait for it to load and a feedback page should open", + "Turn off your wifi and data connection", + "Press refresh on top right corner", + "The page should error and show you a text with black font", + "Hold the text and press select all, then copy that text (don't copy only some portion of the text)", + "Turn on your wifi or data connection", + "Paste the text to the textbox below", + "Paste text here... Webpage not available..." + ], + "ios": [ + "Open Paimon menu", + "Press Feedback", + "Wait for it to load and a feedback page should open", + "Press In-game issue", + "Press Co-Op Mode", + "There is a link on the bottom of the reply, press that", + "A browser should open up, copy the link and paste it below", + "Paste link here... https://genshin.mihoyo..." + ] + } + }, + "help": { + "title": "Wish Counter Help & Settings", + "enableManual": "Enable Manual Input", + "notice": "Using the Auto Import and manual input together is not recommended still need some testing!", + "consider": "Consider using the Auto Import first, access it on button beside the button you click to open this How To", + "howto": { + "title": "How to use manual input", + "subtitle": "After you do x1 pull Wish:", + "press": "Press", + "whenYouGet": "when you get", + "p1": "It will automatically add the lifetime pulls,", + "and": "and", + "p2": ["When the", "pity reach 10, it will automatically reset to 0"], + "p3": ["When the", "pity reach 90, it will automatically reset to 0"], + "p4": [ + "For when you do x10 pulls Wish, press", + "but the pity counter won't be accurate, because there is no way to tell when the drop occur (maybe you got it on the 1st or even the 10th). To make the counter still accurate, you need to check it on the history table and add it 1 by 1 like you do 1 pull Wish." + ], + "p5": ["You can also press", "button to edit the values manually!"], + "p6": [ + "Press the arrow on the bottom to see your pulls detail. A popup will show up when you get", + "or", + "Or you can add or edit the table manually." + ] + } + } + }, + "calculator": { + "titleWeapon": "Weapon Calculator", + "titleCharacter": "Character Calculator", + "goto": "Go To", + "howToUse": "How to Use", + "guide": { + "clickToMaximize": "Click the picture to maximize", + "howToWeapon": "How to use the Weapon Calculator", + "howToCharacter": "How to use the Character Calculator" + }, + "weapon": { + "calculateAscension": "Calculate Ascension Material?", + "selectRarity": "Select weapon rarity", + "selectWeapon": "Select weapon", + "current": "Current Weapon Level, Exp, & Ascension", + "inputCurrentLevel": "Input current weapon level...", + "inputCurrentExp": "Input current weapon exp...", + "intended": "Intended Weapon Level & Ascension", + "inputIntendedLevel": "Input intended weapon level...", + "resource": "Resource to Use", + "calculate": "Calculate", + "unknownInformation": "There are some unknown information", + "ascensionLevel": "Ascension level", + "mora": "Mora (approximate Β±40)", + "expWasted": "EXP Wasted", + "addToTodo": "Add to Todo List", + "addedToTodo": "Added to Todo List" + }, + "character": { + "calculateAscension": "Calculate Ascension Material?", + "selectCharacter": "Select character", + "current": "Current Character Level, Exp, & Ascension", + "inputCurrentLevel": "Input current character level...", + "inputCurrentExp": "Input current character exp...", + "intended": "Intended Character Level & Ascension", + "inputIntendedLevel": "Input intended character level...", + "resource": "Resource to Use", + "calculateTalent": "Calculate Talent Material?", + "inputTalentLevel": "Input the 1st, 2nd & 3rd current talent level", + "inputTalentNotice": "If it has different color, substract it by 3", + "inputTalent": ["1st talent lvl", "2nd talent lvl", "3rd talent lvl"], + "talentToLevel": "to level", + "calculate": "Calculate", + "unknownInformation": "There are some unknown information", + "ascensionLevel": "Ascension level", + "mora": "Mora (approximate Β±40)", + "expWasted": "EXP Wasted", + "addToTodo": "Add to Todo List", + "addedToTodo": "Added to Todo List" + }, + "expTable": { + "level": "Level", + "items": "Items", + "wasted": "Wasted Exp", + "mora": "Mora Cost" + } + }, + "items": { + "title": "Item List", + "subtitle": "Click the item image to add it to the todo list", + "searchCharacter": "Search character", + "searchWeapon": "Search weapon", + "day": "Days", + "material": "Materials", + "characterWeapons": "Characters & Weapons", + "add": { + "rarity": "Select Rarity", + "amount": "Amount", + "inputAmount": "Input amount...", + "cancel": "Cancel", + "add": "Add to Todo" + } + }, + "days": { + "Sunday": "Sunday", + "Monday": "Monday", + "Tuesday": "Tuesday", + "Wednesday": "Wednesday", + "Thursday": "Thursday", + "Friday": "Friday", + "Saturday": "Saturday" + }, + "todo": { + "title": "Todo List", + "summary": "Summary", + "empty": ["Nothing to do yet πŸ˜€", "Add some from the Items page or the Calculator!"], + "farmableToday": "Farmable Today", + "resin": "resin needed", + "based": "Based on AR:{ar} and WL:{wl}", + "change": "(change on settings)", + "approximation": "Approximation calculated from drop rates by", + "delete": { + "title": "Delete this todo?", + "cancel": "Cancel", + "delete": "Delete" + } + }, + "timeline": { + "title": "Timeline", + "localTime": "Show as local time", + "starting": "Starting in", + "ending": "Ending in", + "live": "Live Now!", + "finished": "Finished" + }, + "settings": { + "version": "Data Version:", + "multiple": "Have multiple account? Choose account here to separate your wish and todo data", + "selectAccount": "Select your account", + "reset": "Reset", + "delete": "Delete", + "add": "Add", + "server": "Select your server:", + "drive": [ + "Paimon.moe use Application Data Directory on your Google Drive to save and sync your wish counter and todo list.", + "Paimon.moe can only read and write file that this site create." + ], + "driveError": "Google Drive API cannot be loaded", + "driveSignIn": "Sign in to Google Drive", + "driveSignOut": "Sign out Google Drive", + "synced": "Synced", + "waiting": "Waiting...", + "syncing": "Syncing...", + "lastSync": "Last Sync:", + "feedback": "If you found any bug, wrong data, or you have any feedback, please leave a message on", + "or": "or", + "thanks": "Thanks😁!", + "modal": { + "notice": "All todo and wish history data will be deleted", + "cancel": "Cancel", + "delete": "Delete", + "reset": "Reset" + } + } +} diff --git a/src/locales/id.json b/src/locales/id.json new file mode 100644 index 00000000..342101eb --- /dev/null +++ b/src/locales/id.json @@ -0,0 +1,266 @@ +{ + "characters": { + "title": "Karakter", + "subtitle": "Angka stat adalah saat level 80 Ascension 6. Kamu juga dapat mengklik judul tabel untuk mengurutkan!", + "name": "Nama", + "element": "Element", + "rarity": "Rarity", + "weapon": "Senjata", + "hp": "HP", + "atk": "ATK", + "def": "DEF" + }, + "wish": { + "autoImport": "Import Otomatis", + "helpAndSetting": "Bantuan & Pengaturan", + "wishesWorth": "Wish Setara Dengan", + "lifetimePulls": "Total Pull", + "guarantee": "Dijamin saat {pity}", + "name": "Nama", + "time": "Waktu", + "pity": "Pity", + "welcome": "Selamat datang di Paimon.moe Wish Counter! Kamu bisa mengimport riwayat wish dengan menggunakan Import Otomatis.", + "welcomeStart1": "Tekan tombol", + "welcomeStart2": "diatas untuk mulai", + "manual": "Jika kamu ingin memasukkan datanya secara manual, kamu bisa menyalakannya disini:", + "manualButton": "Nyalakan Input Manual", + "import": { + "title": "Import Riwayat Wish", + "faqsButton": "FAQS - BACA DULU", + "nonew": "Tdk ada wish baru", + "importNotice1": "Wish yang diimport akan ditambah atau dihapus sesuai dengan data yang sudah pernah diimport", + "importNotice2": "Jika kamu tidak mempunyai data yang tersimpan sebelumnya, wish pertama akan dihitung sebagai pity 1.", + "saveData": "Simpan data?", + "reCalculating": "Menghitung pity...", + "processing": "Memproses", + "banner": "Banner", + "page": "Halaman", + "parsing": "Membaca...", + "save": "Simpan", + "cancel": "Batal", + "canceling": "Membatalkan...", + "importNewWishOnly": "Import wish baru saja", + "importNewWishUncheck": "Hapus centang hanya jika kamu ingin mengimport ulang semua riwayat history mu", + "import": "Import", + "close": "Tutup", + "invalidLink": "Link invalid, silahkan dicek kembali", + "errorApi": "Error code dikembalikan dari API MiHoYo, coba lagi nanti!", + "timeout": "Connection timeout, tunggu sebentar dan coba lagi nanti", + "invalidData": "Invalid data dikembalikan dari API, coba lagi nanti", + "success": "Import berhasil πŸ˜€!", + "faqs": { + "title": "Import Riwayat Wish FAQS", + "q1": "Cara kerjanya gimana?", + "a1": "Riwayat history Genshin Impact sebenarnya adalah sebuah halaman web, jadi kamu bisa mengakses nya dengan url web nya. Ada key sementara yang akan dibuat setelah kamu membuka halaman riwayat wish atau halaman feedback, dan importer ini akan secara otomatis menggunakan API MiHoYo untuk mengambil riwayat wish mu", + "q2": "Aman gak? Apakah bisa ke ban?", + "a2": "Paimon.moe menggunakan request yang sama yang digunakan di Genshin Impact untuk mengambil riwayat wish nya, dan Paimon.moe tidak bisa mengubah file-file game atau memori game, dan seharusnya aman. Namun gunakan dengan resiko anda sendiri (saya pakai di akun utama saya sih...). Dan kamu masih bisa input data nya secara manual πŸ˜€.", + "q3": "Akun nya bisa kamu hack dong?", + "a3": [ + "Paimon.moe tidak menyimpan apapun yang berkaitan dengan akun mu (bahkan uid atau nickname mu), jadi jawabannya adalah tidak. Projek ini open source di", + ", Saya belum berencana untuk merusak reputasi saya dengan meng-hack akun orang lain, tidak ada gunanya..." + ], + "q4": "Hey saya coba cek request nya, tapi kok malah me-request ke domain ini, bukan ke API MiHoYo?", + "a4": [ + "Paimon.moe tidak bisa langsung me-request ke API MiHoYo karena", + ", jadi request nya di redirect ke proxy cors agar bisa digunakan. Kamu bisa melihat source code nya di", + "sini" + ], + "q5": "Apakah kamu menyimpan key sementara ku atau riwayat history ku?", + "a5": "Paimon.moe tidak menyimpan key mu, dan menggunakan HTTPS untuk mengirim link mu ke proxy cors sehingga bisa digunakan. Semua data riwayat wish mu disimpan pada device masing-masing (atau google drive mu jika kamu menyalakan sync di setting). Paimon.moe tidak menyimpan apapun di server (ya apapun)", + "q6": "Saya udah coba step-step nya, tapi kok malah dapet API error?", + "a6": "Coba pastiin sudah di copy semua text nya (coba select all aja text nya, jangan di potong-potong), mungkin ada yang kelewatan, jadi ada yang terpotong" + }, + "guide": { + "pc": [ + "Buka menu Paimon [ESC]", + "Klik Masukan", + "Tunggu sampai sudah ke-load dan browser mu akan terbuka", + "Copy & paste link nya ke input dibawah", + "Paste link disini... https://webstatic..." + ], + "android": [ + "Buka menu Paimon", + "Tekan Masukan", + "Tunggu sampai sudah ke-load dan halaman masukan harusnya akan terbuka", + "Matikan wifi dan data selular", + "Tekan refresh di ujung kanan atas", + "Halaman nya seharusnya error dan akan menampilkan text dengan warna hitam", + "Tekan dan tahan text nya lalu pilih semua, kemudian copy text nya (jangan copy hanya sebagian text nya, jangan dipotong-potong lagi)", + "Nyalakan lagi wifi atau data selular mu", + "Paste text nya ke input dibawah", + "Paste text disini... Webpage not available..." + ], + "ios": [ + "Buka menu Paimon", + "Tekan Masukan", + "Tunggu sampai sudah ke-load dan halaman masukan harusnya akan terbuka", + "Tekan Masalah Game", + "Tekan Mode Co-Op", + "Ada link warna biru di bawah reply nya, klik link nya", + "Browser mu akan terbuka, copy link nya dan paste ke input dibawah", + "Paste link disini... https://genshin.mihoyo..." + ] + } + }, + "help": { + "title": "Wish Counter Bantuan & Pengaturan", + "enableManual": "Nyalakan Manual Input", + "notice": "Menggunakan Import Otomatis dan Manual Input secara bersamaan tidak direkomendasikan karena belum stabil, dan masih perlu di testing!", + "consider": "Pertimbangkan untuk menggunakan Import Otomatis dulu, buka menu nya di tombol di sebelah tombol yang kamu gunakan untuk membuka halaman bantuan ini", + "howto": { + "title": "Cara menggunakan manual input", + "subtitle": "Setelah kamu melakukan x1 pull wish:", + "press": "Tekan", + "whenYouGet": "ketika kamu mendapatkan", + "p1": "Itu akan otomatis menambahkan total pull", + "and": "dan", + "p2": ["Ketika", "pity mencapai 10, angkanya akan otomatis reset menjadi 0"], + "p3": ["Ketika", "pity mencapai 90, angkanya akan otomatis reset menjadi 0"], + "p4": [ + "Ketika kamu melakukan wish x10 pull, tekan", + "tapi counter pity nya tidak akan akurat, karena tidak tahu kapan drop nya terjadi (bisa saja kamu dapat nya saat pull ke 1 atau bisa saja ke 10). Untuk membuat counter nya akurat, kamu perlu mengecek nya di tabel riwayat wish mu dan tabahkan 1-per-1 seperti kamu melakukan 1x pull wish." + ], + "p5": ["Kamu juga bisa menekan", "untuk mengedit nilai nya secara manual!"], + "p6": [ + "Tekan tombol panah dibawah untuk melihat detail riwayat mu. Sebuah form akan muncul ketika kamu mendapat", + "atau", + "Atau kamu bisa menambahkan atau mengedit tabel nya secara manual." + ] + } + } + }, + "calculator": { + "titleWeapon": "Kalulator Senjata", + "titleCharacter": "Kalkulator Karakter", + "goto": "Ke", + "howToUse": "Cara Penggunaan", + "guide": { + "clickToMaximize": "Klik gambar untuk memperbesar", + "howToWeapon": "Cara menggunakan Kalkulator Senjata", + "howToCharacter": "Cara menggunakan Kalkulator Karakter" + }, + "weapon": { + "calculateAscension": "Hitung Material Ascension?", + "selectRarity": "Pilih bintang senjata", + "selectWeapon": "Pilih senjata", + "current": "Level Senjata, Exp, & Ascension Saat Ini", + "inputCurrentLevel": "Masukkan level senjata saat ini...", + "inputCurrentExp": "Masukkan exp senjata saat ini...", + "intended": "Level Senjata & Ascension Yang Diinginkan", + "inputIntendedLevel": "Masukkan level senjata yang diinginkan...", + "resource": "Resource yang digunakan", + "calculate": "Hitung", + "unknownInformation": "Ada beberapa informasi yang tidak diketahui", + "ascensionLevel": "Level Ascension", + "mora": "Mora (kurang lebih Β±40)", + "expWasted": "EXP Terbuang", + "addToTodo": "Tambah ke Todo List", + "addedToTodo": "Sudah ditambahkan ke Todo List" + }, + "character": { + "calculateAscension": "Hitung Material Ascension?", + "selectCharacter": "Pilih karakter", + "current": "Level Karakter, Exp, & Ascension Saat Ini", + "inputCurrentLevel": "Masukkan level karakter saat ini...", + "inputCurrentExp": "Masukkan exp karakter saat ini...", + "intended": "Level Karakter & Ascension Yang Diinginkan", + "inputIntendedLevel": "Masukkan level karakter yang diinginkan...", + "resource": "Resource yang digunakan", + "calculateTalent": "Hitung Material Talent?", + "inputTalentLevel": "Masukkan level talent ke 1, 2 dan 3 saat ini", + "inputTalentNotice": "Jika warna level nya berbeda, kurangi 3", + "inputTalent": ["lvl talent ke 1", "lvl talent ke 2", "lvl talent ke 3"], + "talentToLevel": "ke level", + "calculate": "Hitung", + "unknownInformation": "Ada beberapa informasi yang tidak diketahui", + "ascensionLevel": "Level Ascension", + "mora": "Mora (kurang lebih Β±40)", + "expWasted": "EXP Terbuang", + "addToTodo": "Tambah ke Todo List", + "addedToTodo": "Sudah ditambahkan ke Todo List" + }, + "expTable": { + "level": "Level", + "items": "Items", + "wasted": "Exp Terbuang", + "mora": "Jumlah Mora" + } + }, + "items": { + "title": "Daftar Item", + "subtitle": "Klik gambar item untuk menambahkannya ke todo list", + "searchCharacter": "Cari karakter", + "searchWeapon": "Cari senjata", + "day": "Hari", + "material": "Material", + "characterWeapons": "Karakter & Senjata", + "add": { + "rarity": "Pilih Rarity", + "amount": "Jumlah", + "inputAmount": "Masukkan jumlah...", + "cancel": "Batal", + "add": "Tambah ke Todo" + } + }, + "days": { + "Sunday": "Minggu", + "Monday": "Senin", + "Tuesday": "Selasa", + "Wednesday": "Rabu", + "Thursday": "Kamis", + "Friday": "Jumat", + "Saturday": "Sabtu" + }, + "todo": { + "title": "Todo List", + "summary": "Summary", + "empty": ["Belum ada yang ditambahkan πŸ˜€", "Tambahkan todo dari halaman Items atau dari Kalkulator!"], + "farmableToday": "Bisa di farm hari ini", + "resin": "resin diperlukan", + "based": "Berdasarkan AR:{ar} and WL:{wl}", + "change": "(ganti di settings)", + "approximation": "Perkiraan dikalkulasi berdasarkan data dari", + "delete": { + "title": "Hapus todo ini?", + "cancel": "Batal", + "delete": "Hapus" + } + }, + "timeline": { + "title": "Timeline", + "localTime": "Tampilkan sebagai waktu lokal", + "starting": "Dimulai dalam", + "ending": "Selesai dalam", + "live": "Live Sekarang!", + "finished": "Sudah Selesai" + }, + "settings": { + "version": "Versi Data:", + "multiple": "Punya beberapa akun? Pilih akun disini untuk memisahkan data todo dan riwayat wish", + "selectAccount": "Pilih akun mu", + "reset": "Reset", + "delete": "Hapus", + "add": "Tambah", + "server": "Pilih server mu:", + "drive": [ + "Paimon.moe use menggunakan folder Application Data di Google Drive mu untuk menyimpan riwayat wish dan todo list.", + "Paimon.moe hanya bisa membaca dan menulis file yang dibuat oleh website ini." + ], + "driveError": "Google Drive API tidak bisa dimuat", + "driveSignIn": "Sign in ke Google Drive", + "driveSignOut": "Sign out dari Google Drive", + "synced": "Synced", + "waiting": "Menunggu...", + "syncing": "Syncing...", + "lastSync": "Sync Terakhir:", + "feedback": "Jika kamu menemukan bug, data yang salah, atau ada feedback, kamu bisa chat di", + "or": "atau", + "thanks": "Thanks😁!", + "modal": { + "notice": "Semua todo dan riwayat wish akan dihapus", + "cancel": "Cancel", + "delete": "Delete", + "reset": "Reset" + } + } +} diff --git a/src/routes/calculator/_character.svelte b/src/routes/calculator/_character.svelte index 9f9184f6..e6ee7f0e 100644 --- a/src/routes/calculator/_character.svelte +++ b/src/routes/calculator/_character.svelte @@ -1,4 +1,6 @@
-

Delete {account.label}?

-

All todo and wish history data will be deleted

+

{$t('settings.modal.delete')} {account.label}?

+

{$t('settings.modal.notice')}

- - + +
diff --git a/src/routes/settings/_resetAccount.svelte b/src/routes/settings/_resetAccount.svelte index 6006e0c0..48a88b53 100644 --- a/src/routes/settings/_resetAccount.svelte +++ b/src/routes/settings/_resetAccount.svelte @@ -1,4 +1,6 @@
-

Reset {account.label}?

-

All todo and wish history data will be deleted

+

{$t('settings.modal.reset')} {account.label}?

+

{$t('settings.modal.notice')}

- - + +
diff --git a/src/routes/settings/index.svelte b/src/routes/settings/index.svelte index 902b82e3..d875edc9 100644 --- a/src/routes/settings/index.svelte +++ b/src/routes/settings/index.svelte @@ -1,4 +1,6 @@