├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── feature-request.yml │ └── system-support.md └── workflows │ ├── checks.yml │ └── release.yml ├── .gitignore ├── .gulp.json ├── .husky └── pre-commit ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── gulpfile.mjs ├── package-lock.json ├── package.json ├── rollup.config.mjs └── src ├── fonts ├── ArCiela.ttf ├── Aztec.ttf ├── Barazhad.otf ├── Celestial.ttf ├── Daedra.otf ├── DarkEldar.ttf ├── Davek.otf ├── Dethek.otf ├── ElderFutharkFS.ttf ├── Eltharin.ttf ├── Espruar.otf ├── FingerAlphabet.ttf ├── Floki.ttf ├── HighDrowic.otf ├── HighschoolRunes.ttf ├── Infernal.ttf ├── Iokharic.otf ├── JungleSlang.ttf ├── Kargi.ttf ├── KremlinPremier.ttf ├── MageScript.otf ├── MarasEye.otf ├── MeroiticDemotic.ttf ├── MiroslavNormal.ttf ├── MusiQwik.ttf ├── NyStormning.otf ├── OldeEnglish.ttf ├── OldeEspruar.otf ├── OldeThorass.otf ├── Ophidian.otf ├── Oriental.ttf ├── OrkGlyphs.ttf ├── Pulsian.ttf ├── Qijomi.otf ├── Reanaarian.otf ├── Rellanic.otf ├── Saurian.ttf ├── ScrapbookChinese.ttf ├── Semphari.otf ├── Skaven.ttf ├── Tengwar.ttf ├── Thassilonian.ttf ├── Thorass.otf ├── Tuzluca.ttf ├── Valmaric.ttf ├── _licenses.md ├── dragon_alphabet.ttf └── licenses │ ├── aztec.txt │ ├── dragon alphabet.txt │ ├── elder futhark fs.txt │ ├── infernal.txt │ ├── kremlin premier.txt │ ├── ny stormning.txt │ └── pixel sagas.txt ├── lang ├── cs.json ├── de.json ├── en.json ├── es.json ├── fi.json ├── fr.json ├── it.json ├── ja.json ├── ko.json ├── pl.json ├── pt-BR.json ├── sv.json └── zh_Hans.json ├── module.json ├── module ├── Fonts.js ├── api.js ├── forms │ ├── FontSettings.js │ ├── GeneralSettings.js │ └── LanguageSettings.js ├── hooks.js ├── libs │ ├── colorPicker.js │ └── libWrapper.js ├── logic.js ├── polyglot.js ├── preloadTemplates.js ├── providers │ ├── _module.js │ ├── _shared.js │ ├── a5e.js │ ├── aria.js │ ├── ars.js │ ├── coc7.js │ ├── cyberpunk-red-core.js │ ├── d35e.js │ ├── dark-heresy.js │ ├── dcc.js │ ├── demonlord.js │ ├── dnd4e.js │ ├── dnd5e.js │ ├── dsa5.js │ ├── earthdawn4e.js │ ├── fgg.js │ ├── gurps.js │ ├── ose.js │ ├── pf1.js │ ├── pf2e.js │ ├── sfrpg.js │ ├── shadowrun5e.js │ ├── splittermond.js │ ├── sw5e.js │ ├── swade.js │ ├── templates │ │ ├── Base.js │ │ └── Generic.js │ ├── tormenta20.js │ ├── uesrpg-d100.js │ ├── wfrp4e.js │ └── wwn.js ├── settings.js └── tour.js ├── styles ├── _chat.scss ├── _forms.scss ├── _init.scss ├── _journal.scss ├── _language-selector.scss ├── _system-specific.scss ├── fonts.css ├── forms │ ├── _common.scss │ ├── _font-settings.scss │ ├── _general-settings.scss │ └── _language-settings.scss └── polyglot.scss └── templates ├── FontSettings.hbs ├── GeneralSettings.hbs ├── LanguageSettings.hbs └── partials └── settings.hbs /.editorconfig: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Johannes Loher 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Johannes Loher 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | dist 6 | gulpfile.mjs 7 | libWrapper.js -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Johannes Loher 2 | // SPDX-FileCopyrightText: 2022 David Archibald 3 | // 4 | // SPDX-License-Identifier: MIT 5 | 6 | module.exports = { 7 | parserOptions: { 8 | ecmaVersion: 13, 9 | extraFileExtensions: [".cjs", ".mjs"], 10 | sourceType: "module", 11 | }, 12 | 13 | env: { 14 | browser: true, 15 | es6: true, 16 | jquery: true, 17 | }, 18 | 19 | extends: ["eslint:recommended", "@typhonjs-fvtt/eslint-config-foundry.js/0.8.0"], 20 | 21 | plugins: [], 22 | 23 | rules: { 24 | "array-bracket-spacing": ["warn", "never"], 25 | "array-callback-return": "warn", 26 | "arrow-spacing": "warn", 27 | "brace-style": "warn", 28 | "comma-dangle": ["warn", "only-multiline"], 29 | "comma-style": "warn", 30 | "computed-property-spacing": "warn", 31 | "constructor-super": "error", 32 | "default-param-last": "warn", 33 | "dot-location": ["warn", "property"], 34 | "eol-last": ["error", "always"], 35 | eqeqeq: ["warn", "smart"], 36 | "func-call-spacing": "warn", 37 | "func-names": ["warn", "never"], 38 | "getter-return": "warn", 39 | indent: ["warn", "tab", { SwitchCase: 1 }], 40 | "lines-between-class-members": "warn", 41 | "new-parens": ["warn", "always"], 42 | "no-alert": "warn", 43 | "no-array-constructor": "warn", 44 | "no-class-assign": "warn", 45 | "no-compare-neg-zero": "warn", 46 | "no-cond-assign": "warn", 47 | "no-const-assign": "error", 48 | "no-constant-condition": "warn", 49 | "no-constructor-return": "warn", 50 | "no-delete-var": "warn", 51 | "no-dupe-args": "warn", 52 | "no-dupe-class-members": "warn", 53 | "no-dupe-keys": "warn", 54 | "no-duplicate-case": "warn", 55 | "no-duplicate-imports": ["warn", { includeExports: true }], 56 | "no-else-return": "warn", 57 | "no-empty": ["warn", { allowEmptyCatch: true }], 58 | "no-empty-character-class": "warn", 59 | "no-empty-pattern": "warn", 60 | "no-func-assign": "warn", 61 | "no-global-assign": "warn", 62 | "no-implicit-coercion": ["warn", { allow: ["!!"] }], 63 | "no-implied-eval": "warn", 64 | "no-import-assign": "warn", 65 | "no-invalid-regexp": "warn", 66 | "no-irregular-whitespace": "warn", 67 | "no-iterator": "warn", 68 | "no-lone-blocks": "warn", 69 | "no-lonely-if": "warn", 70 | "no-misleading-character-class": "warn", 71 | "no-mixed-operators": "warn", 72 | "no-multi-str": "warn", 73 | "no-multiple-empty-lines": ["warn", { max: 1 }], 74 | "no-new-func": "warn", 75 | "no-new-object": "warn", 76 | "no-new-symbol": "warn", 77 | "no-new-wrappers": "warn", 78 | "no-nonoctal-decimal-escape": "warn", 79 | "no-obj-calls": "warn", 80 | "no-octal": "warn", 81 | "no-octal-escape": "warn", 82 | "no-promise-executor-return": "warn", 83 | "no-proto": "warn", 84 | "no-regex-spaces": "warn", 85 | "no-script-url": "warn", 86 | "no-self-assign": "warn", 87 | "no-self-compare": "warn", 88 | "no-setter-return": "warn", 89 | "no-sequences": "warn", 90 | "no-template-curly-in-string": "warn", 91 | "no-this-before-super": "error", 92 | "no-unexpected-multiline": "warn", 93 | "no-unmodified-loop-condition": "warn", 94 | "no-unneeded-ternary": "warn", 95 | "no-unreachable": "warn", 96 | "no-unreachable-loop": "warn", 97 | "no-unsafe-negation": ["warn", { enforceForOrderingRelations: true }], 98 | "no-unsafe-optional-chaining": ["warn", { disallowArithmeticOperators: true }], 99 | "no-unused-expressions": "warn", 100 | "no-useless-backreference": "warn", 101 | "no-useless-call": "warn", 102 | "no-useless-catch": "warn", 103 | "no-useless-computed-key": ["warn", { enforceForClassMembers: true }], 104 | "no-useless-concat": "warn", 105 | "no-useless-constructor": "warn", 106 | "no-useless-rename": "warn", 107 | "no-useless-return": "warn", 108 | "no-var": "warn", 109 | "no-void": "warn", 110 | "no-whitespace-before-property": "warn", 111 | "prefer-numeric-literals": "warn", 112 | "prefer-object-spread": "warn", 113 | "prefer-regex-literals": "warn", 114 | "prefer-spread": "warn", 115 | "rest-spread-spacing": ["warn", "never"], 116 | "semi-spacing": "warn", 117 | "semi-style": ["warn", "last"], 118 | "space-unary-ops": ["warn", { words: true, nonwords: false }], 119 | "switch-colon-spacing": "warn", 120 | "symbol-description": "warn", 121 | "template-curly-spacing": ["warn", "never"], 122 | "unicode-bom": ["warn", "never"], 123 | "use-isnan": ["warn", { enforceForSwitchCase: true, enforceForIndexOf: true }], 124 | "valid-typeof": ["warn", { requireStringLiterals: true }], 125 | "wrap-iife": ["warn", "inside"], 126 | 127 | "arrow-parens": ["warn", "always"], 128 | "comma-spacing": "warn", 129 | "dot-notation": "warn", 130 | "key-spacing": "warn", 131 | "keyword-spacing": ["warn", { overrides: { catch: { before: true, after: false } } }], 132 | "max-len": [ 133 | "warn", 134 | { 135 | code: 120, 136 | ignoreComments: true, 137 | ignoreTrailingComments: true, 138 | ignoreUrls: true, 139 | ignoreStrings: true, 140 | ignoreTemplateLiterals: true, 141 | ignoreRegExpLiterals: true, 142 | }, 143 | ], 144 | "no-extra-boolean-cast": ["warn", { enforceForLogicalOperands: true }], 145 | "no-extra-semi": "warn", 146 | "no-multi-spaces": ["warn", { ignoreEOLComments: true }], 147 | "no-throw-literal": "error", 148 | "no-trailing-spaces": "warn", 149 | "no-useless-escape": "warn", 150 | "no-unused-vars": ["warn", { args: "none" }], 151 | "nonblock-statement-body-position": ["warn", "beside"], 152 | "one-var": ["warn", "never"], 153 | "operator-linebreak": [ 154 | "warn", 155 | "before", 156 | { 157 | overrides: { "=": "after", "+=": "after", "-=": "after" }, 158 | }, 159 | ], 160 | "prefer-template": "warn", 161 | "quote-props": ["warn", "as-needed", { keywords: false }], 162 | quotes: ["warn", "double", { avoidEscape: true, allowTemplateLiterals: false }], 163 | semi: "warn", 164 | "space-before-blocks": ["warn", "always"], 165 | "space-before-function-paren": [ 166 | "warn", 167 | { 168 | anonymous: "always", 169 | named: "never", 170 | asyncArrow: "always", 171 | }, 172 | ], 173 | "spaced-comment": "warn", 174 | }, 175 | 176 | globals: { 177 | globalThis: false, 178 | GURPS: false, 179 | JournalTextPageSheet: false, 180 | ProseMirror: false, 181 | TomSelect: false, 182 | Tour: false, 183 | }, 184 | 185 | overrides: [ 186 | { 187 | files: ["./*.js", "./*.cjs", "./*.mjs"], 188 | env: { 189 | node: true, 190 | }, 191 | }, 192 | ], 193 | }; 194 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: mclemente 2 | ko_fi: mclemente 3 | custom: https://www.paypal.com/donate/?hosted_button_id=UVFV99HDGE5F8 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | labels: ["bug"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Use this form to report an issue with Polyglot 9 | - type: textarea 10 | id: what-happened 11 | attributes: 12 | label: What happened? 13 | description: Also tell us, what did you expect to happen? 14 | placeholder: Tell us what you see! 15 | validations: 16 | required: true 17 | - type: textarea 18 | id: repro-steps 19 | attributes: 20 | label: Reproduction Steps 21 | description: Keep them simple, include screenshots as needed. Note what System(s) you tested in, if relevant. 22 | placeholder: To encounter the bug, first open up... 23 | validations: 24 | required: true 25 | - type: input 26 | id: game-system 27 | attributes: 28 | label: Which game system, and which version, are you using? 29 | placeholder: "e.g. dnd5e 2.4.1" 30 | validations: 31 | required: true 32 | - type: input 33 | id: polyglot-version 34 | attributes: 35 | label: Which Polyglot version are you using? 36 | placeholder: "e.g. 2.3.28" 37 | validations: 38 | required: true 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Request a Feature 3 | labels: ["enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Use this form to request a new Feature or an update to an existing Feature on Polyglot 9 | - type: textarea 10 | id: user-experience 11 | attributes: 12 | label: User Experience 13 | description: What problem does this solve? What should it function like? 14 | placeholder: In order to help with bulk creation of documents, I would like a new button... 15 | validations: 16 | required: true 17 | - type: checkboxes 18 | id: checkboxes 19 | attributes: 20 | label: Have you read the Wiki? 21 | description: "Are you sure you're not suggesting something that hasn't [already been implemented](https://github.com/mclemente/fvtt-module-polyglot/wiki#features) or that doesn't break [core Foundry behavior](https://github.com/mclemente/fvtt-module-polyglot/wiki#understanding-core-behavior)?" 22 | options: 23 | - label: "Yes" 24 | required: true 25 | validations: 26 | required: true 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/system-support.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: System support 3 | about: Request to support a system 4 | title: '' 5 | labels: enhancement, system support 6 | assignees: '' 7 | 8 | --- 9 | 10 | **System Name:** 11 | e.g. D&D 5e 12 | 13 | **System Repository or Foundry VTT link:** 14 | e.g. https://gitlab.com/foundrynet/dnd5e or https://foundryvtt.com/packages/dnd5e/ 15 | 16 | **Does the system has the languages set up on Foundry?** 17 | It's generally on modules/config.js file 18 | 19 | **Does the system uses languages as items?** 20 | Similar to how WFRP and SWADE do. 21 | 22 | **[Optional] If it isn't straightforward, how do I add a language to a character?** 23 | e.g. DCC system doesn't inform you that you need to change your sheet template to add languages. 24 | 25 | **Additional context** 26 | Add any other context about the system here. 27 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Johannes Loher 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Checks 6 | 7 | on: 8 | - push 9 | - pull_request 10 | 11 | env: 12 | node_version: 16 13 | 14 | jobs: 15 | lint: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v4 20 | 21 | - name: Install node 22 | uses: actions/setup-node@v4.0.0 23 | with: 24 | node-version: ${{ env.node_version }} 25 | 26 | - name: Cache Node.js modules 27 | uses: actions/cache@v3 28 | with: 29 | path: .npm 30 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 31 | restore-keys: | 32 | ${{ runner.OS }}-node- 33 | ${{ runner.OS }}- 34 | 35 | - name: Install dependencies 36 | run: npm ci --cache .npm --prefer-offline 37 | 38 | - name: Lint 39 | run: npm run lint 40 | 41 | build: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - name: Checkout code 45 | uses: actions/checkout@v4 46 | 47 | - name: Install node 48 | uses: actions/setup-node@v4.0.0 49 | with: 50 | node-version: ${{ env.node_version }} 51 | 52 | - name: Cache Node.js modules 53 | uses: actions/cache@v3 54 | with: 55 | path: .npm 56 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 57 | restore-keys: | 58 | ${{ runner.OS }}-node- 59 | ${{ runner.OS }}- 60 | 61 | - name: Install dependencies 62 | run: npm ci --cache .npm --prefer-offline 63 | 64 | - name: Build 65 | run: npm run build 66 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Johannes Loher 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | name: Release 6 | 7 | on: 8 | release: 9 | types: [published] 10 | 11 | env: 12 | package_type: module 13 | node_version: 16 14 | 15 | jobs: 16 | lint: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v4 21 | 22 | - name: Install node 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: ${{ env.node_version }} 26 | 27 | - name: Cache Node.js modules 28 | uses: actions/cache@v3 29 | with: 30 | path: .npm 31 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 32 | restore-keys: | 33 | ${{ runner.OS }}-node- 34 | ${{ runner.OS }}- 35 | 36 | - name: Install dependencies 37 | run: npm ci --cache .npm --prefer-offline 38 | 39 | - name: Lint 40 | run: npm run lint 41 | 42 | build: 43 | runs-on: ubuntu-latest 44 | steps: 45 | - name: Checkout code 46 | uses: actions/checkout@v4 47 | 48 | - name: Install node 49 | uses: actions/setup-node@v4 50 | with: 51 | node-version: ${{ env.node_version }} 52 | 53 | - name: Cache Node.js modules 54 | uses: actions/cache@v3 55 | with: 56 | path: .npm 57 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 58 | restore-keys: | 59 | ${{ runner.OS }}-node- 60 | ${{ runner.OS }}- 61 | 62 | - name: Install dependencies 63 | run: npm ci --cache .npm --prefer-offline 64 | 65 | - name: Extract tag version number 66 | id: get_version 67 | uses: battila7/get-version-action@v2 68 | 69 | - name: Substitute Manifest and Download Links For Versioned Ones 70 | id: sub_manifest_link_version 71 | uses: microsoft/variable-substitution@v1 72 | with: 73 | files: "src/${{ env.package_type }}.json" 74 | env: 75 | version: ${{ steps.get_version.outputs.version-without-v }} 76 | url: https://github.com/${{ github.repository }} 77 | manifest: https://github.com/${{ github.repository }}/releases/latest/download/${{ env.package_type }}.json 78 | download: https://github.com/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/${{ env.package_type }}.zip 79 | 80 | - name: Build 81 | run: npm run build 82 | 83 | - name: Archive production artifacts 84 | uses: actions/upload-artifact@v4 85 | with: 86 | name: dist 87 | path: dist 88 | 89 | publish: 90 | needs: 91 | - lint 92 | - build 93 | runs-on: ubuntu-latest 94 | steps: 95 | - name: Checkout code 96 | uses: actions/checkout@v4 97 | 98 | - name: Download production artifacts for publication 99 | uses: actions/download-artifact@v4 100 | with: 101 | name: dist 102 | path: dist 103 | 104 | - name: Create zip file 105 | working-directory: ./dist 106 | run: zip -r ../${{ env.package_type }}.zip . 107 | 108 | - name: Create release 109 | id: create_version_release 110 | uses: ncipollo/release-action@v1 111 | with: 112 | allowUpdates: true 113 | name: ${{ github.event.release.name }} 114 | token: ${{ secrets.GITHUB_TOKEN }} 115 | artifacts: "./dist/${{ env.package_type }}.json, ./${{ env.package_type }}.zip" 116 | tag: ${{ github.event.release.tag_name }} 117 | body: ${{ github.event.release.body }} 118 | 119 | - name: Get Module ID 120 | id: moduleID 121 | uses: notiz-dev/github-action-json-property@release 122 | with: 123 | path: "./dist/${{ env.package_type }}.json" 124 | prop_path: "id" 125 | 126 | - name: Get mininum 127 | id: minimum 128 | uses: notiz-dev/github-action-json-property@release 129 | with: 130 | path: "./dist/${{ env.package_type }}.json" 131 | prop_path: "compatibility.minimum" 132 | 133 | - name: Get verified 134 | id: verified 135 | uses: notiz-dev/github-action-json-property@release 136 | with: 137 | path: "./dist/${{ env.package_type }}.json" 138 | prop_path: "compatibility.verified" 139 | 140 | - name: Extract tag version number 141 | id: get_version 142 | uses: battila7/get-version-action@v2 143 | 144 | - name: Foundry Release API 145 | uses: fjogeleit/http-request-action@v1 146 | with: 147 | url: "https://api.foundryvtt.com/_api/packages/release_version" 148 | method: "POST" 149 | customHeaders: '{"Content-Type": "application/json", "Authorization" : "${{ secrets.FOUNDRY_KEY }}"}' 150 | data: '{"id": "${{ steps.moduleID.outputs.prop }}", "release": {"version": "${{ steps.get_version.outputs.version-without-v }}", "manifest": "https://github.com/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/${{ env.package_type }}.json", "notes": "https://github.com/${{ github.repository }}/releases/tag/${{ github.event.release.tag_name }}/", "compatibility" : {"minimum": "${{ steps.minimum.outputs.prop }}", "verified": "${{ steps.verified.outputs.prop }}"}}}' 151 | preventFailureOnNoResponse: true 152 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Johannes Loher 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | # IDE 6 | .idea/ 7 | .vs/ 8 | 9 | # Node Modules 10 | node_modules/ 11 | npm-debug.log 12 | 13 | # yarn2 14 | .yarn/* 15 | !.yarn/patches 16 | !.yarn/releases 17 | !.yarn/plugins 18 | !.yarn/sdks 19 | !.yarn/versions 20 | .pnp.* 21 | 22 | # Local configuration 23 | foundryconfig.json 24 | 25 | # Distribution files 26 | dist 27 | 28 | # ESLint 29 | .eslintcache 30 | 31 | # Junit results 32 | junit.xml 33 | -------------------------------------------------------------------------------- /.gulp.json: -------------------------------------------------------------------------------- 1 | { 2 | "flags": { 3 | "gulpfile": "gulpfile.mjs" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | module.json 3 | 4 | **/*.js 5 | **/*.cjs 6 | **/*.mjs 7 | **/fonts.css 8 | **/_fonts.scss -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 4, 4 | "useTabs": true, 5 | "overrides": [ 6 | { 7 | "files": "**/*.{hbs}", 8 | "options": { 9 | "parser": "glimmer" 10 | } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | ## Building 4 | 5 | ### Prerequisites 6 | 7 | In order to build this module, recent versions of `node` and `npm` are 8 | required. Most likely, using `yarn` also works, but only `npm` is officially 9 | supported. We recommend using the latest lts version of `node`. If you use `nvm` 10 | to manage your `node` versions, you can simply run 11 | 12 | ``` 13 | nvm install 14 | ``` 15 | 16 | in the project's root directory. 17 | 18 | You also need to install the project's dependencies. To do so, run 19 | 20 | ``` 21 | npm install 22 | ``` 23 | 24 | ### Building 25 | 26 | You can build the project by running 27 | 28 | ``` 29 | npm run build 30 | ``` 31 | 32 | Alternatively, you can run 33 | 34 | ``` 35 | npm run build:watch 36 | ``` 37 | 38 | to watch for changes and automatically build as necessary. 39 | 40 | ### Linking the built project to Foundry VTT 41 | 42 | In order to provide a fluent development experience, it is recommended to link 43 | the built module to your local Foundry VTT installation's data folder. In 44 | order to do so, first add a file called `foundryconfig.json` to the project root 45 | with the following content: 46 | 47 | ``` 48 | { 49 | "dataPath": ["/absolute/path/to/your/FoundryVTT"] 50 | } 51 | ``` 52 | 53 | (if you are using Windows, make sure to use `\` as a path separator instead of 54 | `/`) 55 | 56 | Then run 57 | 58 | ``` 59 | npm run link-project 60 | ``` 61 | 62 | On Windows, creating symlinks requires administrator privileges, so 63 | unfortunately you need to run the above command in an administrator terminal for 64 | it to work. 65 | 66 | You can also link to multiple data folders by specifying multiple paths in the 67 | `dataPath` array. 68 | 69 | ## System Support 70 | 71 | If you want to add support for a system, be sure to check the [API page](../../wiki/API). 72 | 73 | The guide assumes you're contributing the code to another module or system. If you want to contribute to this project, you will still need to create a subclass, but you should add it to [LanguageProvider.js](/module/LanguageProvider.js) and its name to the import list on [api.js](src/module/api.js). 74 | 75 | # Translations 76 | 77 | 78 | Translation status 79 | 80 | 81 | Polyglot is available in the following languages: 82 | 83 | - Czech, thanks to [KarelZavicak](https://github.com/KarelZavicak) 84 | - English 85 | - Finnish, thanks to [Demian Wright](https://github.com/DemianWright) 86 | - French, thanks to [sladecraven](https://github.com/sladecraven) 87 | - German, thanks to [Nyhles](https://github.com/Nyhles) 88 | - Italian, thanks to [EldritchTranslator](https://github.com/EldritchTranslator) 89 | - Japanese, thanks to [BrotherSharper](https://github.com/BrotherSharper) 90 | - Korean, thanks to [drdwing](https://github.com/drdwing) 91 | - Polish, thanks to [MichalGolaszewski](https://github.com/MichalGolaszewski) 92 | - Portuguese (Brazil) 93 | - Spanish, thanks to [juanfrank](https://github.com/juanfrank), [lozalojo](https://github.com/lozalojo), [GoR](github.com/Git-GoR) 94 | - Swedish, thanks to [Jonas Karlsson](https://github.com/xdy) 95 | 96 | ## Contributing 97 | 98 | If you want to contribute with any translation, check out [Polyglot's Weblate page](https://weblate.foundryvtt-hub.com/engage/polyglot/). 99 | 100 | ### System Specific Translations 101 | 102 | Some translations are specific to a system (e.g. `COC7`, `SWADE`, and `WFRP4E`. When in doubt about its translation, check up with other translators of the system or the Babele module's translation. 103 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Matheus Pereira Clemente 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub release](https://img.shields.io/github/release-date/mclemente/fvtt-module-polyglot) 2 | ![GitHub release (latest by SemVer and asset)](https://img.shields.io/github/downloads/mclemente/fvtt-module-polyglot/latest/module.zip) 3 | 4 | [![ko-fi](https://img.shields.io/badge/ko--fi-Support%20Me-red?style=flat-square&logo=ko-fi)](https://ko-fi.com/mclemente) 5 | 6 | # Polyglot 7 | 8 | Talk to others using a language you can speak and scrambles text you can't understand, into several fantasy scripts. 9 | 10 | ## How to Use 11 | ### Set Up 12 | #### As a GM 13 | - Check the module settings to configure it according to your preferences. 14 | - Check the Tour under the Tour Management window. 15 | - Check the [wiki](https://github.com/mclemente/fvtt-module-polyglot/wiki) for more in-depth information. 16 | 17 | #### As a Player 18 | - Assign a character on the User Configuration window. 19 | 20 | ### Using 21 | - Select tokens to speak and read messages as them. 22 | - Right-click the chat selector to enable/disable speaking in a language. 23 | 24 | ## Attribution 25 | 26 | - `@Talwin Greenwood` on the FVTT discord, for the original idea for this module. 27 | - [@KaKaRoTo](https://github.com/kakaroto/) for the original PolyGlot module, which was licensed under [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). 28 | - [@ElizeuAngelo](https://github.com/elizeuangelo) for the 'fantasy languages' adaptation. 29 | - [@ironmonk88](https://github.com/ironmonk88) for the Translation Box. 30 | - [@manuelVo](https://github.com/manuelVo) for the API code. 31 | - [@Ghost](https://github.com/ghost-fvtt) for the Foundry Factory. 32 | 33 | ## Community Contribution 34 | 35 | See the [CONTRIBUTING](/CONTRIBUTING.md) file for information about how you can help this project. 36 | -------------------------------------------------------------------------------- /gulpfile.mjs: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Johannes Loher 2 | // SPDX-FileCopyrightText: 2022 David Archibald 3 | // 4 | // SPDX-License-Identifier: MIT 5 | 6 | import fs from "fs-extra"; 7 | import gulp from "gulp"; 8 | import prefix from "gulp-autoprefixer"; 9 | import sass from "gulp-dart-sass"; 10 | import sourcemaps from "gulp-sourcemaps"; 11 | import path from "node:path"; 12 | import buffer from "vinyl-buffer"; 13 | import source from "vinyl-source-stream"; 14 | import yargs from "yargs"; 15 | import { hideBin } from "yargs/helpers"; 16 | 17 | import rollupStream from "@rollup/stream"; 18 | 19 | import rollupConfig from "./rollup.config.mjs"; 20 | 21 | /********************/ 22 | /* CONFIGURATION */ 23 | /********************/ 24 | 25 | const packageId = "polyglot"; 26 | const sourceDirectory = "./src"; 27 | const distDirectory = "./dist"; 28 | const stylesDirectory = `${sourceDirectory}/styles`; 29 | const stylesExtension = "scss"; 30 | const sourceFileExtension = "js"; 31 | const staticFiles = ["assets", "fonts", "lang", "lib", "packs", "styles/fonts.css", "templates", "module.json"]; 32 | 33 | /********************/ 34 | /* BUILD */ 35 | /********************/ 36 | 37 | let cache; 38 | 39 | /** 40 | * Build the distributable JavaScript code 41 | */ 42 | function buildCode() { 43 | return rollupStream({ ...rollupConfig(), cache }) 44 | .on("bundle", (bundle) => { 45 | cache = bundle; 46 | }) 47 | .pipe(source(`${packageId}.js`)) 48 | .pipe(buffer()) 49 | .pipe(sourcemaps.init({ loadMaps: true })) 50 | .pipe(sourcemaps.write(".")) 51 | .pipe(gulp.dest(`${distDirectory}/module`)); 52 | } 53 | 54 | /** 55 | * Build style sheets 56 | */ 57 | function buildStyles() { 58 | return gulp.src([`${stylesDirectory}/**/*.${stylesExtension}`], { base: `${stylesDirectory}/` }) 59 | .pipe(sourcemaps.init({ loadMaps: true })) 60 | .pipe(sass({ outputStyle: "compressed" }).on("error", sass.logError)) 61 | .pipe(prefix({ cascade: false })) 62 | .pipe(sourcemaps.write(".")) 63 | .pipe(gulp.dest(`${distDirectory}/styles`)); 64 | } 65 | 66 | /** 67 | * Copy static files 68 | */ 69 | async function copyFiles() { 70 | for (const file of staticFiles) { 71 | if (fs.existsSync(`${sourceDirectory}/${file}`)) { 72 | await fs.copy(`${sourceDirectory}/${file}`, `${distDirectory}/${file}`); 73 | } 74 | } 75 | } 76 | 77 | function tomSelect() { 78 | return gulp.src([ 79 | "node_modules/tom-select/dist/js/tom-select.complete.min.js", 80 | "node_modules/tom-select/dist/js/tom-select.complete.min.js.map", 81 | "node_modules/tom-select/dist/css/tom-select.min.css", 82 | "node_modules/tom-select/dist/css/tom-select.min.css.map", 83 | ]).pipe(gulp.dest("dist/lib/tom-select"));; 84 | } 85 | 86 | /** 87 | * Watch for changes for each build step 88 | */ 89 | export function watch() { 90 | tomSelect(); 91 | gulp.watch(`${sourceDirectory}/**/*.${sourceFileExtension}`, { ignoreInitial: false }, buildCode); 92 | gulp.watch(`${stylesDirectory}/**/*.${stylesExtension}`, { ignoreInitial: false }, buildStyles); 93 | gulp.watch( 94 | staticFiles.map((file) => `${sourceDirectory}/${file}`), 95 | { ignoreInitial: false }, 96 | copyFiles, 97 | ); 98 | } 99 | 100 | export const build = gulp.series(clean, gulp.parallel(buildCode, buildStyles, tomSelect, copyFiles)); 101 | 102 | /********************/ 103 | /* CLEAN */ 104 | /********************/ 105 | 106 | /** 107 | * Remove built files from `dist` folder while ignoring source files 108 | */ 109 | export async function clean() { 110 | const files = [...staticFiles, "styles", "module"]; 111 | 112 | console.log(" ", "Files to clean:"); 113 | console.log(" ", files.join("\n ")); 114 | 115 | for (const filePath of files) { 116 | await fs.remove(`${distDirectory}/${filePath}`); 117 | } 118 | } 119 | 120 | /********************/ 121 | /* LINK */ 122 | /********************/ 123 | 124 | /** 125 | * Get the data paths of Foundry VTT based on what is configured in `foundryconfig.json` 126 | */ 127 | function getDataPaths() { 128 | const config = fs.readJSONSync("foundryconfig.json"); 129 | const dataPath = config?.dataPath; 130 | 131 | if (dataPath) { 132 | const dataPaths = Array.isArray(dataPath) ? dataPath : [dataPath]; 133 | 134 | return dataPaths.map((dataPath) => { 135 | if (typeof dataPath !== "string") { 136 | throw new Error(`Property dataPath in foundryconfig.json is expected to be a string or an array of strings, but found ${dataPath}`); 137 | } 138 | if (!fs.existsSync(path.resolve(dataPath))) { 139 | throw new Error(`The dataPath ${dataPath} does not exist on the file system`); 140 | } 141 | return path.resolve(dataPath); 142 | }); 143 | } else { 144 | throw new Error("No dataPath defined in foundryconfig.json"); 145 | } 146 | } 147 | 148 | /** 149 | * Link build to User Data folder 150 | */ 151 | export async function link() { 152 | let destinationDirectory; 153 | if (fs.existsSync(path.resolve(sourceDirectory, "module.json"))) { 154 | destinationDirectory = "modules"; 155 | } else { 156 | throw new Error("Could not find module.json"); 157 | } 158 | 159 | const linkDirectories = getDataPaths().map((dataPath) => path.resolve(dataPath, "Data", destinationDirectory, packageId)); 160 | 161 | const argv = yargs(hideBin(process.argv)).option("clean", { 162 | alias: "c", 163 | type: "boolean", 164 | default: false, 165 | }).argv; 166 | const clean = argv.c; 167 | 168 | for (const linkDirectory of linkDirectories) { 169 | if (clean) { 170 | console.log(`Removing build in ${linkDirectory}.`); 171 | 172 | await fs.remove(linkDirectory); 173 | } else if (!fs.existsSync(linkDirectory)) { 174 | console.log(`Linking dist to ${linkDirectory}.`); 175 | await fs.ensureDir(path.resolve(linkDirectory, "..")); 176 | await fs.symlink(path.resolve(distDirectory), linkDirectory); 177 | } else { 178 | console.log(`Skipped linking to ${linkDirectory}, as it already exists.`); 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "gulp build", 4 | "build:watch": "gulp watch", 5 | "link-project": "gulp link", 6 | "clean": "gulp clean", 7 | "clean:link": "gulp link --clean", 8 | "lint": "eslint --ext .js,.cjs,.mjs .", 9 | "lint:fix": "eslint --ext .js,.cjs,.mjs --fix .", 10 | "postinstall": "husky install" 11 | }, 12 | "devDependencies": { 13 | "@rollup/plugin-node-resolve": "^15.2.1", 14 | "@rollup/stream": "^3.0.0", 15 | "@typhonjs-fvtt/eslint-config-foundry.js": "^0.8.0", 16 | "eslint": "^8.49.0", 17 | "fs-extra": "^11.1.1", 18 | "gulp": "^5.0.0", 19 | "gulp-autoprefixer": "^9.0.0", 20 | "gulp-dart-sass": "^1.1.0", 21 | "gulp-sourcemaps": "^3.0.0", 22 | "husky": "^8.0.3", 23 | "lint-staged": "^14.0.1", 24 | "rollup": "^2.79.2", 25 | "tom-select": "^2.4.3", 26 | "vinyl-buffer": "^1.0.1", 27 | "vinyl-source-stream": "^2.0.0", 28 | "yargs": "^17.7.2" 29 | }, 30 | "lint-staged": { 31 | "*.(js|cjs|mjs)": "eslint --fix", 32 | "*.(html|hbs|json|yml|css)": "prettier --write" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Johannes Loher 2 | // SPDX-FileCopyrightText: 2022 David Archibald 3 | // 4 | // SPDX-License-Identifier: MIT 5 | 6 | import { nodeResolve } from "@rollup/plugin-node-resolve"; 7 | 8 | export default () => ({ 9 | input: "src/module/polyglot.js", 10 | output: { 11 | dir: "dist/module", 12 | format: "es", 13 | sourcemap: true, 14 | }, 15 | plugins: [nodeResolve()], 16 | }); 17 | -------------------------------------------------------------------------------- /src/fonts/ArCiela.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/ArCiela.ttf -------------------------------------------------------------------------------- /src/fonts/Aztec.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Aztec.ttf -------------------------------------------------------------------------------- /src/fonts/Barazhad.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Barazhad.otf -------------------------------------------------------------------------------- /src/fonts/Celestial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Celestial.ttf -------------------------------------------------------------------------------- /src/fonts/Daedra.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Daedra.otf -------------------------------------------------------------------------------- /src/fonts/DarkEldar.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/DarkEldar.ttf -------------------------------------------------------------------------------- /src/fonts/Davek.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Davek.otf -------------------------------------------------------------------------------- /src/fonts/Dethek.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Dethek.otf -------------------------------------------------------------------------------- /src/fonts/ElderFutharkFS.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/ElderFutharkFS.ttf -------------------------------------------------------------------------------- /src/fonts/Eltharin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Eltharin.ttf -------------------------------------------------------------------------------- /src/fonts/Espruar.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Espruar.otf -------------------------------------------------------------------------------- /src/fonts/FingerAlphabet.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/FingerAlphabet.ttf -------------------------------------------------------------------------------- /src/fonts/Floki.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Floki.ttf -------------------------------------------------------------------------------- /src/fonts/HighDrowic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/HighDrowic.otf -------------------------------------------------------------------------------- /src/fonts/HighschoolRunes.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/HighschoolRunes.ttf -------------------------------------------------------------------------------- /src/fonts/Infernal.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Infernal.ttf -------------------------------------------------------------------------------- /src/fonts/Iokharic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Iokharic.otf -------------------------------------------------------------------------------- /src/fonts/JungleSlang.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/JungleSlang.ttf -------------------------------------------------------------------------------- /src/fonts/Kargi.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Kargi.ttf -------------------------------------------------------------------------------- /src/fonts/KremlinPremier.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/KremlinPremier.ttf -------------------------------------------------------------------------------- /src/fonts/MageScript.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/MageScript.otf -------------------------------------------------------------------------------- /src/fonts/MarasEye.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/MarasEye.otf -------------------------------------------------------------------------------- /src/fonts/MeroiticDemotic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/MeroiticDemotic.ttf -------------------------------------------------------------------------------- /src/fonts/MiroslavNormal.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/MiroslavNormal.ttf -------------------------------------------------------------------------------- /src/fonts/MusiQwik.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/MusiQwik.ttf -------------------------------------------------------------------------------- /src/fonts/NyStormning.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/NyStormning.otf -------------------------------------------------------------------------------- /src/fonts/OldeEnglish.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/OldeEnglish.ttf -------------------------------------------------------------------------------- /src/fonts/OldeEspruar.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/OldeEspruar.otf -------------------------------------------------------------------------------- /src/fonts/OldeThorass.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/OldeThorass.otf -------------------------------------------------------------------------------- /src/fonts/Ophidian.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Ophidian.otf -------------------------------------------------------------------------------- /src/fonts/Oriental.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Oriental.ttf -------------------------------------------------------------------------------- /src/fonts/OrkGlyphs.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/OrkGlyphs.ttf -------------------------------------------------------------------------------- /src/fonts/Pulsian.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Pulsian.ttf -------------------------------------------------------------------------------- /src/fonts/Qijomi.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Qijomi.otf -------------------------------------------------------------------------------- /src/fonts/Reanaarian.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Reanaarian.otf -------------------------------------------------------------------------------- /src/fonts/Rellanic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Rellanic.otf -------------------------------------------------------------------------------- /src/fonts/Saurian.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Saurian.ttf -------------------------------------------------------------------------------- /src/fonts/ScrapbookChinese.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/ScrapbookChinese.ttf -------------------------------------------------------------------------------- /src/fonts/Semphari.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Semphari.otf -------------------------------------------------------------------------------- /src/fonts/Skaven.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Skaven.ttf -------------------------------------------------------------------------------- /src/fonts/Tengwar.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Tengwar.ttf -------------------------------------------------------------------------------- /src/fonts/Thassilonian.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Thassilonian.ttf -------------------------------------------------------------------------------- /src/fonts/Thorass.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Thorass.otf -------------------------------------------------------------------------------- /src/fonts/Tuzluca.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Tuzluca.ttf -------------------------------------------------------------------------------- /src/fonts/Valmaric.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/Valmaric.ttf -------------------------------------------------------------------------------- /src/fonts/_licenses.md: -------------------------------------------------------------------------------- 1 | # Licensing 2 | 3 | The following fonts are owned by Pixel Sagas, check out their [website](http://www.pixelsagas.com/): 4 | 5 | - Barazhad 6 | - Celestial 7 | - Daedra 8 | - Davek 9 | - Dethek 10 | - Espruar 11 | - HighDrowic 12 | - Kargi 13 | - Iokharic 14 | - MageScript 15 | - MarasEye 16 | - OldeEspruar 17 | - OldeThorass 18 | - Ophidian 19 | - Qijomi 20 | - Reanaarian 21 | - Rellanic 22 | - Semphari 23 | - Thorass 24 | 25 | The following font was created by TenkaDigi: 26 | 27 | - Infernal (Fan Art) 28 | 29 | The follow font was created by Helena Jole: 30 | 31 | - ScrapbookChinese 32 | 33 | The following font was created by Levi: 34 | 35 | - Aztec 36 | 37 | The following font is under [1001Fonts Free For Personal Use License (FFP)](https://www.1001fonts.com/licenses/ffp.html): 38 | 39 | - Dragon Alphabet 40 | 41 | The following font is under [GNU GENERAL PUBLIC LICENSE v3](https://www.gnu.org/licenses/gpl-3.0.en.html): 42 | 43 | - KremlinPremier 44 | 45 | The following font is under [SIL OPEN FONT LICENSE Version 1.1](https://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web): 46 | 47 | - [MusiQwik](https://www.fontspace.com/musiqwik-font-f3722). Copyright (c) 2003, Robert Allgeyer. 48 | - [Ny Stormning](https://www.fontspace.com/ny-stormning-font-f23289). Copyright (c) 2016, Mew Too, Robert Jablonski (Cannot Into Space Fonts) (cannotintospacefonts@gmail.com). 49 | 50 | The following are under [CC BY-SA 3](https://creativecommons.org/licenses/by-sa/3.0/): 51 | 52 | - [Ar Ciela](http://hymmnoserver.uguu.ca/). Hymmnos and HYMMNOSERVER were created by Akira Tsuchiya. 53 | - Elder Futhark FS 54 | 55 | The following does not accompanied license terms, were OPL or their license have expired: 56 | 57 | - AnglosaxonRunes 58 | - DarkEldar 59 | - Eltharin 60 | - FingerAlphabet 61 | - Floki 62 | - HighschoolRunes 63 | - JungleSlang 64 | - MeroiticDemotic 65 | - MiroslavNormal 66 | - Pulsian (Fan Art by Echiceroo) 67 | - Skaven 68 | - Tengwar (Greifswalder) 69 | - OldeEnglish 70 | - Oriental 71 | - OrkGlyphs 72 | - Thassilonian (Fan Art) 73 | - Tuzluca 74 | - Valmaric -------------------------------------------------------------------------------- /src/fonts/dragon_alphabet.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mclemente/fvtt-module-polyglot/3cd2c098ca53f2231998805c63215b56586619bf/src/fonts/dragon_alphabet.ttf -------------------------------------------------------------------------------- /src/fonts/licenses/aztec.txt: -------------------------------------------------------------------------------- 1 | This font is made by Levi and may be used free of charge for non-commercial projects. Please contact me if you plan to use it for other purposes. It also may be distributed free of charge on any websites provided this file is intact. 2 | Contact: 3 | url: http://www.geocities.com/noimage_2001/ 4 | email: halmoslevi@yahoo.com 5 | -------------------------------------------------------------------------------- /src/fonts/licenses/dragon alphabet.txt: -------------------------------------------------------------------------------- 1 | 1001Fonts Free For Personal Use License (FFP) 2 | 3 | Preamble 4 | In this license, 'dragon_alphabet' refers to the given .zip file, which may contain one or numerous fonts. These fonts can be of any type (.ttf, .otf, ...) and together they form a 'font family' or in short a 'typeface'. 5 | 6 | 1. Copyright 7 | dragon_alphabet is the intellectual property of its respective author, provided it is original, and is protected by copyright laws in many parts of the world. 8 | 9 | 2. Personal Use 10 | dragon_alphabet may be downloaded and used free of charge for personal use, as long as the usage is not racist or illegal. Personal use refers to all usage that does not generate financial income in a business manner, for instance: 11 | 12 | - personal scrapbooking for yourself 13 | - recreational websites and blogs for friends and family 14 | - prints such as flyers, posters, t-shirts for churches, charities, and non-profit organizations 15 | 16 | 3. Commercial Use 17 | Commercial use is not allowed without prior written permission from the respective author. Please contact the author to ask for commercial licensing. Commercial use refers to usage in a business environment, including: 18 | 19 | - business cards, logos, advertising, websites, mobile apps for companies 20 | - t-shirts, books, apparel that will be sold for money 21 | - flyers, posters for events that charge admission 22 | - freelance graphic design work 23 | - anything that will generate direct or indirect income 24 | 25 | 4. Modification 26 | dragon_alphabet may not be modified, altered, adapted or built upon without written permission by its respective author. This pertains all files within the downloadable font zip-file. 27 | 28 | 5. Conversion 29 | dragon_alphabet may be converted to other formats such as WOFF, SVG or EOT webfonts, as long as the font is not modified in any other way, such as changing names or altering individual glyphs. 30 | 31 | 6. Distribution 32 | While dragon_alphabet may freely be copied and passed along to other individuals for private use as its original downloadable zip-file, it may not be sold or published without written permission by its respective author. 33 | 34 | 7. Embedding 35 | dragon_alphabet may be embedded into an application such as a web- or mobile app, as long as the application is of personal use and does not distribute dragon_alphabet, such as offering it as a download. 36 | 37 | 8. Disclaimer 38 | dragon_alphabet is offered 'as is' without any warranty. 1001fonts.com and the respective author of dragon_alphabet shall not be liable for any damage derived from using this typeface. By using dragon_alphabet you agree to the terms of this license. -------------------------------------------------------------------------------- /src/fonts/licenses/elder futhark fs.txt: -------------------------------------------------------------------------------- 1 | The FontStruction “Elder Futhark *FS” 2 | (https://fontstruct.com/fontstructions/show/1527205) by Doug Peters is licensed 3 | under a Creative Commons Attribution Share Alike license 4 | (http://creativecommons.org/licenses/by-sa/3.0/). 5 | -------------------------------------------------------------------------------- /src/fonts/licenses/infernal.txt: -------------------------------------------------------------------------------- 1 | DUNGEONS & DRAGONS, D&D, Wizards of the Coast, Forgotten Realms, the dragon ampersand, all other Wizards of the Coast product names, and their respective logos are trademarks of Wizards of the Coast in the USA and other countries. 2 | 3 | This font is a fanmade, unofficial resource derived from the version of the Infernal script provided in the Dungeons & Dragons 5th Edition module "Baldur's Gate: Descent into Avernus" on page 256. 4 | 5 | This font was created in memory of Neale Davidson, a fantastic contributor to the online community of Dungeons & Dragons who created several popular versions of scripts provided in previous edition materials. If you appreciate this font, I would encourage you to donate to his wife's PayPal, which can be found on pixelsagas.com/ 6 | 7 | Shareware Usage Terms 8 | 9 | The Infernal font is free to use for personal, non-commercial purposes. No payment is necessary to use the Infernal font for personal use, and there is no limit to the amount of prints, pages, or other medium to be produced using them. However, you cannot offer the font for commercial sale, or offer for direct download. The inclusion othe font name and/or site URL in the credits or documentation when it is used is appreciated, but this is not mandatory. 10 | 11 | Payment 12 | 13 | Payment is not required for the use of the Infernal font. 14 | 15 | Support 16 | 17 | No support is provided for this font, questions or comments may be directed to Tenka Digi on DeviantArt ( https://www.deviantart.com/tenkadigi ), though response is not guarunteed. 18 | 19 | Tenka Digi expressly disclaims any warranty for the font. The font and any related documentation is provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties or merchantability, fitness for a particular purpose, or non-infringement. The entire risk arising out of use or performance of the font remains with the user. 20 | 21 | No Liability For Consequential Damages. 22 | 23 | In no event shall Tenka Digi be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use this product, even if Tenka Digi has been advised of the possibility of such damages. 24 | 25 | 3) MISCELLANEOUS 26 | 27 | Should the user have any questions concerning this document or you desire to contact Neale Davidson for any reason, please email tenkadigi@hotmail.com . 28 | 29 | Governing Law 30 | 31 | This agreement is governed by and subject to the laws of the United States of America. 32 | -------------------------------------------------------------------------------- /src/fonts/licenses/kremlin premier.txt: -------------------------------------------------------------------------------- 1 | BoltCutterDesign True Type Fonts/graphics 2 | Copyright (C) 2008 BCD/MFA 3 | 4 | This program/graphic is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. It may not be sold/resold individualy or 8 | in a compilation. 9 | 10 | This notice must accompany the font/graphic upon distribution/redistribution. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | http://www.gnu.org/copyleft/gpl.html 21 | 22 | boltcutterdesign@yahoo.com 23 | -------------------------------------------------------------------------------- /src/fonts/licenses/ny stormning.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Mew Too, Robert Jablonski (Cannot Into Space Fonts) (cannotintospacefonts@gmail.com), 2 | with Reserved Font Name Ny Stormning. 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /src/fonts/licenses/pixel sagas.txt: -------------------------------------------------------------------------------- 1 | Font License 2 | Shareware/ Font License 3 | 4 | Pixel Sagas Freeware Fonts EULA (End User License Agreement) and Software Inclusion Agreement 5 | 6 | “Purchaser” and “User” may be used interchangeably in this agreement. 7 | 8 | “Pixel Sagas” and “Neale Davidson” may be used interchangeably in this agreement. These all refer to the intellectual and legal property of Neale Davidson. 9 | 10 | Usage 11 | 12 | Pixel Saga’s Shareware Fonts are free to use for personal, non-commercial purposes. No payment is necessary to use Pixel Saga’s Freeware Fonts for personal use, and there is no limit to the amount of prints, pages, or other medium to be produced using them. However, you cannot offer the font for commercial sale, or offer for direct download. The inclusion of the font name and/or site URL in the credits or documentation when it is used is appreciated, but this is not mandatory. 13 | 14 | Payment 15 | 16 | Payment is not required for the use of Pixel Saga’s Shareware Fonts. Commercial use requires a modest fee which can be paid through the pixelsagas.com web site through Paypal.com’s services. The transaction receipt for any shareware “commercial license” purchase will suffice as proof of license. 17 | 18 | Support 19 | 20 | Font installation help is available at http://www.pixelsagas.com. If you experience problems with any Pixel Saga’s Freeware font (such as spacing issues or missing characters), please verify that you have the correct and current version of the fonts. In the case of Freeware fonts, downloading the font directly from the Pixel Sagas site will ensure that the font files have not been altered. 21 | 22 | Software Inclusion Agreement 23 | 24 | Pixel Saga’s software products are protected by copyright laws and International copyright treaties, as well as other intellectual property laws and treaties. All Pixel Saga’s software products are licensed, not sold. 25 | 26 | 1) GRANT OF LICENSE 27 | 28 | This document grants the user the following rights: 29 | 30 | Installation and Use. The user may install and use an unlimited number of copies of the software product. The user may not offer Pixel Sagas freeware fonts for direct download unless the user has received explicit, written permission from Neale Davidson. Otherwise please direct users to the http://www.pixelsagas.com website. Pixel Sagas freeware fonts may, however, be embedded for web, publication, or general software use. 31 | 32 | 2) WARRANTIES 33 | 34 | None 35 | 36 | Pixel Sagas expressly disclaims any warranty for the software product. The software product and any related documentation is provided “as is” without warranty of any kind, either express or implied, including, without limitation, the implied warranties or merchantability, fitness for a particular purpose, or non-infringement. The entire risk arising out of use or performance of the software product remains with the user. 37 | 38 | No Liability For Consequential Damages. 39 | 40 | In no event shall Neale Davidson or Pixel Sagas be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use this product, even if Pixel Sagas has been advised of the possibility of such damages. 41 | 42 | 3) MISCELLANEOUS 43 | 44 | Should the user have any questions concerning this document or you desire to contact Neale Davidson for any reason, please email jaynz@pixelsagas.com . 45 | 46 | Governing Law 47 | 48 | This agreement is governed by and subject to the laws of the United States of America. -------------------------------------------------------------------------------- /src/lang/cs.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT.CustomLanguages.title": "Vlastní Jazyky", 3 | "POLYGLOT.CustomLanguages.hint": "Specifikuj seznam vlastních, čárkou oddělených jazyků, které se přidají do systému.", 4 | "POLYGLOT.ComprehendLanguages.title": "Kouzlo Porozumění Jazykům", 5 | "POLYGLOT.ComprehendLanguages.hint": "Kouzlo jako např. Porozumění Jazykům z D&D. Vlož vlastní jazyk, který jsi specifikoval. Nebude možné jím mluvit nebo psát, ale umožní porozumět všem ostatním jazykům.", 6 | "POLYGLOT.Truespeech.title": "Kouzlo Jazyků", 7 | "POLYGLOT.Truespeech.hint": "Jako např. kouzlo Jazyky z D&D. Vlož vlastní jazyk, který jsi specifikoval. Ten, kdo jim mluvím bude rozumět všem mluveným jazykům (neumí číst Žurnály) a rozumí mu všechna stvoření.", 8 | "POLYGLOT.DefaultLanguage.title": "Základní Jazyk", 9 | "POLYGLOT.DefaultLanguage.hint": "Název základního jazyka. Nech prázdný pro ponechání systémového základu.", 10 | "POLYGLOT.ScrambleGM.title": "Zašifrovat pro GM", 11 | "POLYGLOT.ScrambleGM.hint": "Deaktivuj tuto volbu, aby se vždy zobrazil text pro GM (podívej se na barvu glóbu, aby jsi zjistil, zda token rozumí).", 12 | "POLYGLOT.toggleRuneText.title": "Přepnout Runový Text v Žurnálu", 13 | "POLYGLOT.toggleRuneText.hint": "Přepne viditelnost\"Run\" v Žurnálu.", 14 | "POLYGLOT.RandomizeRunes.title": "Náhodné Runy", 15 | "POLYGLOT.RandomizeRunes.hint": "Zapnutí této volby způsobí, že šifrovaný text se objeví pokaždé jinak, i v případě, že se jedná o tu samou zprávu.", 16 | "POLYGLOT.ExportFonts.title": "Udělat fonty dostupné", 17 | "POLYGLOT.ExportFonts.hint": "Udělá Polyglot fonty dostupné k použití ve Foundry (např. v Kreslení).", 18 | "POLYGLOT.DisplayTranslated.title": "Zobrazit překladový box", 19 | "POLYGLOT.DisplayTranslated.hint": "Pro jazyky, které jsou přeloženy v chatovém okně, zobraz originální text a pod ním překlad.", 20 | "POLYGLOT.HideTranslation.title": "Schovej hráčům Globus a text \"Přeloženo z\"", 21 | "POLYGLOT.HideTranslation.hint": "Schová Globus a text \"Přeloženo z\" ze zpráv hráčů. Ideální, pokud nechceš hráčům ukázat, kterým jazykem hovoříš.", 22 | "POLYGLOT.AllowOOC.title": "Šifrování v OOC zprávách chatu", 23 | "POLYGLOT.AllowOOC.hint": "Dovolí GM šifrovat text, když posílá Out Of Character zprávy", 24 | "POLYGLOT.Translation": "Překlad", 25 | "POLYGLOT.TranslatedFrom": "Přeloženo z ", 26 | "POLYGLOT.LanguageLabel": "Jazyk", 27 | "POLYGLOT.ToggleRunes": "Přepnout Runy", 28 | "POLYGLOT.Runes": "Runy", 29 | "POLYGLOT.Generic": { 30 | "Language": "Jazyk" 31 | }, 32 | "POLYGLOT.WFRP4E.LanguageSkills": "Jazyk", 33 | "POLYGLOT": { 34 | "source": { 35 | "forgevtt": "Forge", 36 | "data": "Data", 37 | "s3": "Amazon S3" 38 | }, 39 | "enableAllFonts": { 40 | "title": "Přidání písem do nastavení písma a jazyka" 41 | }, 42 | "DND5E": { 43 | "SpecialLanguages.title": "Nahradit speciální jazyky" 44 | }, 45 | "LanguageSettings": "Nastavení jazyka", 46 | "ChatSettings": "Nastavení chatu", 47 | "Languages.title": "Jazyky", 48 | "Font": "Písmo", 49 | "Fonts": "Písma", 50 | "FontSize": "Velikost písma (%)", 51 | "directory": { 52 | "name": "Adresář vlastních písem" 53 | }, 54 | "logographicalFontToggle.title": "Logografická písma", 55 | "ReplaceLanguages.title": "Nahrazení jazyků systému", 56 | "LanguageRegex": { 57 | "title": "Jazyk RegEx" 58 | }, 59 | "FontSettings": "Nastavení Písma", 60 | "DefaultAlphabet": "Základní Abeceda", 61 | "Languages.hint": "Změní abecedu použitou pro jazyky", 62 | "KnownLanguages": "Známé Jazyky", 63 | "UnknownLanguages": "Neznámé Jazyky", 64 | "GeneralSettings": "Obecné Nastavení", 65 | "General": "Obecné", 66 | "AlphabeticOnly": "Pouze Abecedně" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/lang/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "I18N": { 3 | "LANGUAGE": "Español", 4 | "MAINTAINERS": "@Viriato139ac#0342, Juanfrank" 5 | }, 6 | "POLYGLOT": { 7 | "DefaultAlphabet": "Alfabeto por defecto", 8 | "FontSettings": "Ajustes de fuentes", 9 | "LanguageSettings": "Ajustes de idiomas", 10 | "ChatSettings": "Ajustes del chat", 11 | "Languages.title": "Idiomas", 12 | "Languages.hint": "Cambia el alfabeto de los idiomas.", 13 | "Font": "Fuente", 14 | "Fonts": "Fuentes", 15 | "FontSize": "Tamaño de fuente (%)", 16 | "AllowOOC.hint": "Determina qué usuarios tendrán sus mensajes codificados al utilizar el chat como jugador. OOC = Out of character (como jugador, o fuera del personaje).", 17 | "AllowOOC.title": "Codificar mensajes OOC del chat", 18 | "AllowOOCOptions": { 19 | "a": "Todos", 20 | "b": "Solo GM", 21 | "c": "Solo jugadores", 22 | "d": "Ninguno" 23 | }, 24 | "ComprehendLanguages.hint": "Define un idioma que permite al hablante entender todos los idiomas, pero que no puede ser escrito ni hablado.", 25 | "ComprehendLanguages.title": "Hechizo Comprender Idiomas", 26 | "CustomLanguages.hint": "Define una lista de idiomas personalizados, separados mediante coma, para que sean añadidos al sistema.", 27 | "CustomLanguages.title": "Idiomas personalizados", 28 | "DefaultLanguage.hint": "Nombre del idioma que se selecciona por defecto. Dejar en blanco para utilizar el valor por defecto del sistema.", 29 | "DefaultLanguage.title": "Idioma por defecto", 30 | "DisplayTranslated.hint": "Para los idiomas que se traducen en el chat, muestra el texto original y a continuación la traducción.", 31 | "DisplayTranslated.title": "Mostrar traducciones", 32 | "enableAllFonts": { 33 | "choices": { 34 | "0": "Ninguno", 35 | "1": "Fuentes de Polyglot", 36 | "2": "Fuentes adicionales del programa Base", 37 | "3": "Ambos" 38 | }, 39 | "hint": "Añade las fuentes de las opciones seleccionadas a los Ajustes de Fuente e Idioma.", 40 | "title": "Añadir fuentes a los ajustes de los módulos" 41 | }, 42 | "ExportFonts.hint": "Añade las fuentes de Polyglot al menú de Fuentes Adicionales del programa Base. Si se desactiva esta opción, se eliminarán todas las fuentes de Polyglot del menú.", 43 | "ExportFonts.title": "Añade las fuentes de Polyglot al programa Base", 44 | "HideTranslation.hint": "Oculta el globo y el texto \"Traducido del\" en el chat a los jugadores. Útil para cuando no se quiere que los jugadores sepan qué idioma se está hablando. Requiere recargar la página.", 45 | "HideTranslation.title": "Ocultar a los jugadores los globos y el texto \"Traducido del\"", 46 | "IgnoreJournalFontSize": { 47 | "title": "Diario: Usar tamaño de fuente normal", 48 | "hint": "Ignora el tamaño de las fuentes de Polyglot en los diarios, haciendo que tengan el mismo tamaño que tendría el texto normal. Útil para ocasiones en las que el formato del diario es importante." 49 | }, 50 | "JournalHighlight": { 51 | "hint": "Define la opacidad del resaltado de las fuentes en el diario.", 52 | "title": "Opacidad del resaltado en los diarios (%)" 53 | }, 54 | "JournalHighlightColor": { 55 | "hint": "Define el color de resaltado de las fuentes en el diario.", 56 | "title": "Color de resaltado de los disarios" 57 | }, 58 | "LanguageProvider": { 59 | "name": "Proveedor de ajustes de idioma", 60 | "hint": "Seleccione quien provee información de alfabetos e idiomas. Se pueden habilitar más proveedores instalando módulos y sistemas. Las opciones que aparecen más abajo dependerán del proveedor seleccionado. ⚠️ Si cambia el proveedor, deberá guardar los cambios y volver a abrir la ventana de configuración.", 61 | "choices": { 62 | "module": "[Módulo] {name}", 63 | "native": "Genérico", 64 | "system": "[Sistema] {name}" 65 | } 66 | }, 67 | "languageDataPath": { 68 | "title": "Ruta de idioma", 69 | "hint": "Si el sistema tiene idiomas configurados en los datos de los actores que no se cargan bien, es posible que estén usando otra ruta. Introduzca la ruta en los datos al atributo correcto (p.e. actor.system.languages o actor.system.speak). Este ajuste tiene prioridad sobre los ajustes de RegEx de idioma. Requiere reinicio." 70 | }, 71 | "literacyDataPath": { 72 | "title": "Ruta de alfabetización", 73 | "hint": "Lo mismo que el ajuste de la ruta de idioma, pero aplicado a la lectura de diarios. Se necesita rellenar el ajuste de ruta de idioma. Requiere reinicio." 74 | }, 75 | "LanguageRegex": { 76 | "title": "RegEx de idioma", 77 | "hint": "Se puede usar para cambiar el término de búsqueda en los objetos de \"Idioma\" a otro diferente, como \"Lengua\"." 78 | }, 79 | "logographicalFontToggle.hint": "Reduce a la mitad el tamaño de las frases que usen fuentes logográficas (p. ej. caracteres japoneses o chinos).", 80 | "logographicalFontToggle.title": "Fuentes logográficas", 81 | "RandomizeRunes.hint": "Determina el tipo de aleatoriedad (RNG) utilizada para generar una frase. ⚠️ La opción \"Ninguno\" solamente admite caracteres alfanuméricos (sin acentos).", 82 | "RandomizeRunes.title": "Aleatorizar las runas", 83 | "RandomizeRunesOptions": { 84 | "a": "Por defecto", 85 | "b": "Frases únicas", 86 | "c": "Ninguna ⚠️" 87 | }, 88 | "ReplaceLanguages.hint": "Reemplaza el idioma por defecto del sistema por sus idiomas personalizados. El primer idioma personalizado de la lista se convertirá en el nuevo idioma por defecto.", 89 | "ReplaceLanguages.title": "Reemplazar idiomas del sistema", 90 | "RuneRegex": { 91 | "title": "Aleatorizar solo alfanuméricos", 92 | "hint": "Hace que la aleatoriedad ignore los caracteres no alfanuméricos (p. ej. !,.;:?#$\"'). Esto puede causar que algunos de estos caracteres se muestren como un cuadrado (□) en algunas fuentes." 93 | }, 94 | "ScrambleGM.title": "Codificar para el GM", 95 | "ScrambleGM.hint": "No traducir el texto para el DJ (remítase al color del globo para ver la perspectiva del icono). Requiere recargar la página.", 96 | "Truespeech.title": "Hechizo Idiomas", 97 | "Truespeech.hint": "Define un idioma que permite al hablante entender todos los idiomas hablados (no puede leer Diarios), y que es entendido por todas las criaturas.", 98 | "Translation": "Traducción", 99 | "TranslatedFrom": "Traducido del ", 100 | "LanguageLabel": "Idioma", 101 | "AlphabetLabel": "Alfabeto", 102 | "LatinAlphabet": "Alfabeto latino", 103 | "ToggleRunes": "Activar/desactivar runas", 104 | "Runes": "Runas", 105 | "UESRPG.Language": "Idioma", 106 | "Generic": { 107 | "Language": "Idioma" 108 | }, 109 | "COC7": { 110 | "LanguageOwn": "Lengua propia", 111 | "LanguageAny": "Otras lenguas", 112 | "LanguageOther": "Otras lenguas", 113 | "LanguageSpec": "Lengua" 114 | }, 115 | "DND5E": { 116 | "SpecialLanguages.title": "Reemplazar idiomas especiales", 117 | "SpecialLanguages.hint": "Nombre del idioma que reemplazará \"idiomas\" tales como \"todos los idiomas que supo en vida\"." 118 | }, 119 | "SWADE": { 120 | "LanguageSkills": "Idioma" 121 | }, 122 | "WFRP4E": { 123 | "LanguageSkills": "Idioma" 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/lang/fi.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT": { 3 | "LanguageSettings": "Kielten asetukset", 4 | "ChatSettings": "Keskusteluasetukset", 5 | "CustomLanguages.title": "Mukautetut kielet", 6 | "ComprehendLanguages.title": "Kaikkitietävä kieli", 7 | "ComprehendLanguages.hint": "Aseta kieli, jonka puhuja ymmärtää kaikkia muita kieliä, mutta jota ei voi puhua eikä kirjoittaa.", 8 | "directory": { 9 | "name": "Mukautettu fonttikansio", 10 | ".hint": "Valitse fonttitiedostoja sisältävä kansio, joka ei ole modules-kansiossa." 11 | }, 12 | "source": { 13 | "s3": "S3", 14 | "forgevtt": "Forge" 15 | }, 16 | "Truespeech.title": "Kaikkipuheen kieli", 17 | "JournalHighlight.title": "Korostuksen peitto (%)", 18 | "JournalHighlight.hint": "Määrittää muistiinpanon fonttien päälle tulevan korostuksen peiton.", 19 | "logographicalFontToggle.title": "Logografiset fontit", 20 | "logographicalFontToggle.hint": "Puolittaa logografisia fontteja (esim. japanilaiset, kiinalaiset merkit) käyttävien lauseiden pituuden.", 21 | "DefaultLanguage.title": "Oletuskieli", 22 | "DefaultLanguage.hint": "Valittavan oletuskielen nimi. Pidä tyhjänä, jos haluat käyttää järjestelmän oletusarvoa.", 23 | "ReplaceLanguages.title": "Korvaa järjestelmän kielet", 24 | "ScrambleGM.title": "PJ näkee sekoitetut viestit", 25 | "ScrambleGM.hint": "Älä käännä tekstiä PJ:lle (katso maapallon väristä, mitä pelinappula ymmärtää). Vaatii uudelleenlataamisen.", 26 | "Generic": { 27 | "Language": "Kieli" 28 | }, 29 | "enableAllFonts": { 30 | "choices": { 31 | "0": "Ei mitään", 32 | "2": "Ytimen ylimääräiset fontit", 33 | "3": "Molemmat", 34 | "1": "Polyglot fontit" 35 | }, 36 | "title": "Lisää Foundryn fontteja {settingMenuLabel} asetuksiin", 37 | "hint": "Lisää Foundryn fontteja kohtiin {setting1} ja {setting2}." 38 | }, 39 | "RandomizeRunesOptions": { 40 | "a": "Oletus", 41 | "b": "Uniikit fraasit", 42 | "c": "Ei mitään ⚠️" 43 | }, 44 | "ExportFonts.title": "Lisää Polyglotin fontit ytimeen", 45 | "ExportFonts.hint": "Lisää Polyglotin fontit ytimen {settingMenuLabel} -valikkoon. Kytke asetus pois päältä poistaaksesi kaikki Polyglotin fontit valikosta.", 46 | "DisplayTranslated.title": "Näytön käännökset", 47 | "DefaultAlphabet": "Oletusaakkosto", 48 | "FontSettings": "Fonttien asetukset", 49 | "Languages.title": "Kielet", 50 | "Font": "Fontti", 51 | "Fonts": "Fontit", 52 | "FontSize": "Fonttikoko (%)", 53 | "CustomLanguages.hint": "Kirjoita luettelo järjestelmään lisättävistä mukautetuista kielistä. Ne on erotettava toisistaan pilkuilla tai puolipisteillä.", 54 | "Truespeech.hint": "Aseta kieli, jonka puhuja ymmärtää kaikkia puhuttuja kieliä (ei voi lukea muistiinpanoja) ja jota kaikki olennot ymmärtävät.", 55 | "UESRPG.Language": "Kieli", 56 | "ReplaceLanguages.hint": "Korvaa järjestelmän oletuskielet mukauttamallasi kielillä. Luettelon ensimmäisestä kielestä tulee uusi oletuskieli.", 57 | "RandomizeRunes.hint": "Tämä määrittää, minkä tyyppistä satunnaislukugeneraattoria käytetään fraasin luomiseen. ⚠️ Vaihtoehto \"Ei mitään\" tukee vain aakkosnumeerisia merkkejä (ei aksentteja).", 58 | "SWADE": { 59 | "LanguageSkills": "Kieli", 60 | "AdditionalLanguageStat": { 61 | "hint": "On mahdollista kohdistaa lisäominaisuuteen (joka asetetaan SWADE Settings Configuratorissa). Sinun on syötettävä Stat-avain (merkkikokoriippuvainen). Huomaa, että tämä asetus ohittaa asetuksen {setting}.", 62 | "title": "Kielen Stat-avain" 63 | }, 64 | "AdditionalLiterateStat": { 65 | "title": "Lukutaidon Stat-avain", 66 | "hint": "Muistiinpanoja on mahdollista rajoittaa lisäämällä lisäominaisuus. Sinun on kirjoitettava Stat-avain (merkkikokoriippuvainen). Tämä asetus on ei riipu asetuksesta {setting}." 67 | } 68 | }, 69 | "WFRP4E": { 70 | "LanguageSkills": "Kieli" 71 | }, 72 | "DND5E": { 73 | "SpecialLanguages.title": "Korvaa erikoiset kielet", 74 | "SpecialLanguages.hint": "Kielen nimi, joka korvaa \"kielet\" kuten \"kaikki kielet, jotka se osasi elämässään\"." 75 | }, 76 | "COC7": { 77 | "LanguageSpec": "Kieli", 78 | "LanguageOwn": "Kieli", 79 | "LanguageAny": "Kieli", 80 | "LanguageOther": "Kieli" 81 | }, 82 | "DisplayTranslated.hint": "Näytä alkuperäinen teksti ja käännös sen alapuolella keskusteluikkunassa käännetyille kielille.", 83 | "HideTranslation.title": "Piilota ilmaisimet pelaajilta", 84 | "AllowOOCOptions": { 85 | "b": "Vain PJ", 86 | "c": "Vain pelaajat", 87 | "d": "Ei mitään", 88 | "a": "Kaikki" 89 | }, 90 | "LanguageProvider": { 91 | "choices": { 92 | "module": "[Moduuli] {name}", 93 | "native": "Yleinen", 94 | "system": "[Järjestelmä] {name}" 95 | }, 96 | "name": "Kieliasetusten tarjoaja", 97 | "hint": "Valitse, kuka tarjoaa kielitietoja aakkosista ja kielistä. Pelijärjestelmät ja asennetut moduulit voivat tarjota lisää kielipalvelujen tarjoajia. Alla olevat vaihtoehdot riippuvat tässä valitusta kielipalveluntarjoajasta. ⚠️ Jos vaihdat palveluntarjoajaa, sinun on tallennettava ja avattava nämä asetukset uudelleen." 98 | }, 99 | "LanguageRegex": { 100 | "title": "Kielen RegEx", 101 | "hint": "Tällä voit vaihtaa esineissä käytetyn termin \"Kieli\" joksikin muuksi, kuten \"Puhe\"." 102 | }, 103 | "LanguageLabel": "Kieli", 104 | "AlphabetLabel": "Aakkosto", 105 | "LatinAlphabet": "Latinalaiset aakkoset", 106 | "HideTranslation.hint": "Piilottaa maapallon ja Käännetty kielestä -tekstin pelaajille lähetetyistä keskusteluviesteistä. Hyödyllinen silloin, kun et halua näyttää pelaajille, mitä kieltä puhut. Vaatii uudelleenlatauksen.", 107 | "Languages.hint": "Muuttaa kielissä käytettävää aakkostoa.", 108 | "TranslatedFrom": "Käännetty kielestä ", 109 | "Translation": "Käännös", 110 | "AllowOOC.hint": "Valitse, minkä käyttäjien viestit salataan. PUP = pelin ulkopuolinen puhe.", 111 | "AllowOOC.title": "Salaa PUP-viestit", 112 | "GeneralSettings": "Yleiset asetukset", 113 | "languageDataPath": { 114 | "hint": "Jos järjestelmässäsi on asetettuja kieliä hahmojen tietoihin ja niitä ei ladata oikein, se saattaa käyttää toista resurssipolkua. Syötä resurssipolku oikeaan attribuuttiin (esim. actor.system.languages tai actor.system.speak). Tämä asetus on ensisijainen {setting}-asetukseen nähden. Vaatii uudelleenlatauksen.", 115 | "title": "Kielen resurssipolku" 116 | }, 117 | "RuneRegex": { 118 | "hint": "Jättää muut kuin aakkosnumeeriset merkit (esim. !,.;:?#$\"') huomioimatta satunnaistamisessa. Tämä saattaa aiheuttaa sen, että jotkin näistä merkeistä näkyvät neliönä (□) joissakin fonteissa.", 119 | "title": "Satunnaista vain aakkosnumeeriset merkit" 120 | }, 121 | "General": "Yleinen", 122 | "Omniglot": { 123 | "title": "Kaikkikielen kieli", 124 | "hint": "Aseta kieli, jonka puhuja ymmärtää ja puhuu kaikkia muita kieliä." 125 | }, 126 | "IgnoreJournalFontSize": { 127 | "hint": "Jättää huomiotta Polyglotin fonttien koon muistiinpanoissa, jolloin niiden koko on sama kuin normaalin tekstin. Hyödyllinen silloin, kun muistiinpanon muotoilulla on merkitystä.", 128 | "title": "Käytä tavallista fonttikokoa" 129 | }, 130 | "JournalHighlightColor": { 131 | "hint": "Määrittää muistiinpanon fonttien päälle tulevan korostuksen peiton.", 132 | "title": "Korostusväri" 133 | }, 134 | "literacyDataPath": { 135 | "title": "Lukutaidon resurssipolku", 136 | "hint": "Sama kuin asetus {setting}, mutta muistiinpanojen lukemista varten. Tämä asetus edellyttää asetusta {setting}. Vaatii uudelleenlatauksen." 137 | }, 138 | "RandomizeRunes.title": "Satunnaista riimut", 139 | "ToggleRunes": "Vaihda riimut päälle/pois", 140 | "Runes": "Riimut", 141 | "AlphabeticOnly": "Vain aakkoselliset", 142 | "Logographical": "Logografinen" 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/lang/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT": { 3 | "LanguageSettings": "Impostazioni lingua", 4 | "ChatSettings": "Impostazioni chat", 5 | "Languages.title": "Lingue", 6 | "FontSize": "Dimensione dei caratteri (%)", 7 | "CustomLanguages.title": "Lingue personalizzate", 8 | "CustomLanguages.hint": "Definisci una lista di lingue personalizzate, separate da virgole, da aggiungere al sistema.", 9 | "ComprehendLanguages.title": "Incantesimo Comprensione dei Linguaggi", 10 | "source": { 11 | "data": "Dati", 12 | "s3": "S3", 13 | "forgevtt": "Forge" 14 | }, 15 | "Truespeech.title": "Incantesimo Lingue", 16 | "Truespeech.hint": "Determina una lingua che fa capire a chi la conosce tutte le lingue parlate (non fa leggere i Diari) e che può essere capita da tutte le creature.", 17 | "JournalHighlight.title": "Opacità dell'evidenziatore nei Diari (%)", 18 | "DefaultLanguage.title": "Lingua predefinita", 19 | "DefaultLanguage.hint": "Nome del linguaggio predefinito da selezionare. Se vuoto, usa il predefinito di sistema.", 20 | "ReplaceLanguages.title": "Sostituisci le lingue di sistema", 21 | "ScrambleGM.title": "Rimescola i messaggi per il GM", 22 | "ScrambleGM.hint": "Non tradurre i testi per il GM (fai riferimento al colore del mappamondo per capire se il token comprende). Richiede il ricaricamento.", 23 | "enableAllFonts": { 24 | "hint": "Aggiungi i font alle impostazioni di font e lingua.", 25 | "choices": { 26 | "0": "Nessuno", 27 | "2": "Font aggiuntivi di base", 28 | "3": "Entrambi", 29 | "1": "Font di Polyglot" 30 | }, 31 | "title": "Aggiungi font alle impostazioni di font e lingua" 32 | }, 33 | "logographicalFontToggle.hint": "Dimezza la dimensione di frasi che usano font logografici (esempio: giapponese, cinese).", 34 | "logographicalFontToggle.title": "Font logografici", 35 | "directory": { 36 | ".hint": "Indica una cartella al di fuori della cartella \"modules\" che contiene i file dei font.", 37 | "name": "Cartella dei font personalizzati" 38 | }, 39 | "Fonts": "Font", 40 | "Font": "Font", 41 | "FontSettings": "Impostazioni font", 42 | "RandomizeRunes.title": "Randomizza le rune", 43 | "RandomizeRunesOptions": { 44 | "a": "Default", 45 | "b": "Frasi uniche", 46 | "c": "Nessuno ⚠️" 47 | }, 48 | "ExportFonts.title": "Aggiungi i font di Polyglot a quelli base", 49 | "ExportFonts.hint": "Aggiungi i font di Polyglot al menù di Font Addizionali.", 50 | "DisplayTranslated.title": "Mostra traduzioni", 51 | "HideTranslation.title": "Nascondi indicatori ai Giocatori", 52 | "HideTranslation.hint": "Nasconde il Mappamondo e il testo \"Tradotto da\" nei messaggi in chat ai giocatori. Perfetto per quando vuoi nascondere loro che lingua stai parlando.", 53 | "AllowOOC.title": "Rimescola i messaggi OOC in chat", 54 | "AllowOOC.hint": "Scegli che utenti hanno i messaggi rimescolati. OOC = Fuori personaggio (Out of Character).", 55 | "AllowOOCOptions": { 56 | "a": "Tutti", 57 | "b": "Solo GM", 58 | "c": "Solo Giocatori", 59 | "d": "Nessuno" 60 | }, 61 | "LanguageProvider": { 62 | "name": "Fonte delle impostazioni delle lingue", 63 | "choices": { 64 | "module": "[Modulo] {name}", 65 | "native": "Generico", 66 | "system": "[Sistema] {name}" 67 | }, 68 | "hint": "Seleziona la fonte delle informazioni per gli alfabeti e le lingue. Altre fonti possono essere rese disponibili tramite sistemi e moduli installati. Le opzioni sottostanti dipendono dalla fonte stabilita qui. ⚠️ Se cambi la fonte, devi salvare e riaprire queste impostazioni." 69 | }, 70 | "LanguageRegex": { 71 | "title": "RegEx lingua", 72 | "hint": "Puoi usare questa impostazione per cambiare il termine cercato tra gli oggetti da \"Lingua\" a qualcos'altro, come \"Linguaggio\"." 73 | }, 74 | "Translation": "Traduzione", 75 | "DefaultAlphabet": "Alfabeto predefinito", 76 | "Languages.hint": "Cambia l'alfabeto usato per le lingue. Ripristinare le impostazioni predefinite ricaricherà la pagina.", 77 | "ComprehendLanguages.hint": "Determina una lingua che fa comprendere a chi la conosce tutte le altre lingue, ma che non può essere parlata o scritta.", 78 | "JournalHighlight.hint": "Definisci l'opacità dell'evidenziamento in un Dario.", 79 | "ReplaceLanguages.hint": "Sostituisce le lingue predefinite del sistema con le tue lingue personalizzate. La prima della lista diventerà la nuova lingua predefinita.", 80 | "RandomizeRunes.hint": "Questo determina che tipo di RNG viene usato per generare una frase. ⚠️ L'opzione \"Nessuno\" supporta solo caratteri alfanumerici (no accenti).", 81 | "DisplayTranslated.hint": "Per le lingue che sono tradotte nella chat, mostra il testo originale con la traduzione sotto.", 82 | "Generic": { 83 | "Language": "Lingua" 84 | }, 85 | "UESRPG.Language": "Lingua", 86 | "Runes": "Rune", 87 | "ToggleRunes": "Attiva / disattiva rune", 88 | "LatinAlphabet": "Alfabeto latino", 89 | "AlphabetLabel": "Alfabeto", 90 | "LanguageLabel": "Lingua", 91 | "TranslatedFrom": "Tradotto dal ", 92 | "SWADE": { 93 | "LanguageSkills": "Lingua" 94 | }, 95 | "DND5E": { 96 | "SpecialLanguages.hint": "Nome della lingua che rimpiazzerà \"lingue\" come \"tutte le lingue conosciute in vita\".", 97 | "SpecialLanguages.title": "Sostituisci lingue speciali" 98 | }, 99 | "COC7": { 100 | "LanguageSpec": "Lingua", 101 | "LanguageOther": "Lingua", 102 | "LanguageAny": "Lingua", 103 | "LanguageOwn": "Lingua" 104 | }, 105 | "WFRP4E": { 106 | "LanguageSkills": "Lingua" 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/lang/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT": { 3 | "DefaultAlphabet": "標準文字", 4 | "FontSettings": "フォント設定", 5 | "LanguageSettings": "言語設定", 6 | "ChatSettings": "チャット設定", 7 | "Languages.title": "言語", 8 | "Languages.hint": "言語のアルファベットを変更します。セーブ後に再読み込みが必要です。デフォルトに戻すと自動で再読み込みされます。", 9 | "Fonts": "フォント", 10 | "CustomLanguages.title": "カスタム言語", 11 | "CustomLanguages.hint": "システムに追加するカスタム言語のリストをカンマ区切りで指定します。", 12 | "ComprehendLanguages.title": "コンプリヘンド・ランゲージズ呪文", 13 | "ComprehendLanguages.hint": "D&Dにおけるコンプリヘンド・ランゲージズに相当する呪文。設定済のカスタム言語を入力します。その習得者は話したり書いたりはできませんが、すべての言語が理解できるようになります。", 14 | "Truespeech.title": "タンズ呪文", 15 | "Truespeech.hint": "D&Dにおけるタンズに相当する呪文。設定済のカスタム言語を入力します。その話者はすべての“話し言葉”を理解し(つまり資料は読めない)、すべてのクリーチャーが理解できる発言が行えるようになります。", 16 | "DefaultLanguage.title": "デフォルトの言語", 17 | "DefaultLanguage.hint": "デフォルト選択される言語の名称を入力します。空にすると、システムのデフォルトが使用されます。", 18 | "ReplaceLanguages.title": "システム言語を置き換える", 19 | "ReplaceLanguages.hint": "システムのデフォルト言語をカスタム言語に置き換えます。リストの最初の言語が新しいデフォルト言語になります。", 20 | "ScrambleGM.title": "GMもスクランブル化する", 21 | "ScrambleGM.hint": "無効にすると、GMはテキストの内容を常に確認できるようになります。選択したコマが言語を理解しているかは、翻訳アイコン(地球儀マーク)の色を確認する必要があります。", 22 | "enableAllFonts.title": "言語設定ですべてのフォントを追加する", 23 | "enableAllFonts.hint": "言語設定でPolyglotフォントが使用できるようなります。", 24 | "RandomizeRunes.title": "ルーンのランダム化", 25 | "RandomizeRunes.hint": "有効にすると、同じメッセージを繰り返し発言したとしても、スクランブル後のテキストが別の文字列になります。", 26 | "ExportFonts.title": "フォントを使用可能にする", 27 | "ExportFonts.hint": "PolyglotフォントをFoundryのシステム(例えば図形描画ツールなど)で使用できるようなります。", 28 | "DisplayTranslated.title": "翻訳ボックスを表示する", 29 | "DisplayTranslated.hint": "チャットログ内で翻訳が行われるとき、翻訳文と原文が併記されるようになります。", 30 | "HideTranslation.title": "翻訳アイコンと翻訳元の表示を隠す", 31 | "HideTranslation.hint": "チャットに表示される翻訳アイコン(地球儀マーク)と、翻訳ボックス内に表示される「翻訳元」の表示をプレイヤーに隠します。何の言語を話しているかをプレイヤーに伏せたいときに適しています。", 32 | "AllowOOC.title": "OOCチャットのスクランブル化", 33 | "AllowOOC.hint": "キャラクターの発言ではないメッセージ(OOC:Out Of Character)であっても、GMは言語をスクランブルできるようになります。", 34 | "AllowOOCOptions": { 35 | "a": "全員", 36 | "b": "GMのみ", 37 | "c": "プレイヤーのみ", 38 | "d": "なし" 39 | }, 40 | "LanguageProvider": { 41 | "name": "言語設定の提供元", 42 | "hint": "アルファベットや言語情報の提供元を選択できるようになりました。ゲームシステムやインストールされたモジュールによって、より多くの提供元が利用できます。以下のオプションは、ここで選択した言語の提供元によって変化します。⚠️提供元を変更したときは、保存後に再度設定を開き直す必要があります。", 43 | "choices": { 44 | "module": "[モジュール] {name}", 45 | "native": "標準設定", 46 | "system": "[システム] {name}" 47 | } 48 | }, 49 | "Translation": "翻訳", 50 | "TranslatedFrom": "翻訳元:", 51 | "LanguageLabel": "言語", 52 | "AlphabetLabel": "文字体系", 53 | "LatinAlphabet": "ラテン文字", 54 | "ToggleRunes": "ルーンの切替", 55 | "Runes": "ルーン", 56 | "Generic": { 57 | "Language": "言語" 58 | }, 59 | "UESRPG.Language": "言語", 60 | "COC7": { 61 | "LanguageOwn": "言語", 62 | "LanguageAny": "言語", 63 | "LanguageOther": "言語", 64 | "LanguageSpec": "言語" 65 | }, 66 | "SWADE": { 67 | "LanguageSkills": "言語" 68 | }, 69 | "WFRP4E": { 70 | "LanguageSkills": "言語" 71 | }, 72 | "enableAllFonts": { 73 | "choices": { 74 | "1": "Polyglotのフォント", 75 | "2": "コアの追加フォント", 76 | "0": "なし", 77 | "3": "両方" 78 | } 79 | }, 80 | "FontSize": "フォントサイズ(%)", 81 | "Font": "フォント" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/lang/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT": { 3 | "DefaultAlphabet": "기본 문자", 4 | "FontSettings": "글꼴 설정", 5 | "LanguageSettings": "언어 설정", 6 | "ChatSettings": "채팅 설정", 7 | "Languages.title": "언어", 8 | "Languages.hint": "언어에 사용될 알파벳을 변경한다. 기본값으로 재설정하면 새로고침된다.", 9 | "Fonts": "글꼴", 10 | "CustomLanguages.title": "사용자 지정 언어", 11 | "CustomLanguages.hint": "시스템에 추가할 사용자 정의 언어. 쉼표(,)로 구분하여 목록을 정의한다.", 12 | "ComprehendLanguages.title": "언어 변환 주문", 13 | "ComprehendLanguages.hint": "D&D의 언어 변환 주문과 같이, 설정한 사용자 지정 언어를 입력하면 말하거나 쓰진 못하지만 다른 언어를 이해할 수 있게 해준다.", 14 | "Truespeech.title": "언어 구사 주문", 15 | "Truespeech.hint": "D&D의 언어 구사 주문과 같이, 설정한 사용자 지정 언어를 입력하면 화자는 언어를 듣고 이해할 수 있으며(저널은 읽지 못함), 모든 생물의 언어를 이해할 수 있다.", 16 | "JournalHighlight.title": "저널 하이라이트 불투명도(%)", 17 | "JournalHighlight.hint": "저널의 글씨 위 하이라이트 표시의 불투명도를 정의한다.", 18 | "logographicalFontToggle.title": "로고그래픽 폰트", 19 | "logographicalFontToggle.hint": "로고그래픽 폰트(e.g.:일본어, 한자)를 사용하여 구절의 크기를 절반으로 줄인다.", 20 | "DefaultLanguage.title": "기본 언어", 21 | "DefaultLanguage.hint": "선택할 기본 언어의 이름이다. 시스템 기본값을 사용하려면 비워둘 것.", 22 | "ReplaceLanguages.title": "시스템 언어 대체", 23 | "ReplaceLanguages.hint": "시스템의 기본 언어를 사용자 지정 언어로 바꾼다. 목록의 첫번째 언어가 새 기본 언어가 된다.", 24 | "ScrambleGM.title": "GM에게 스크램블", 25 | "ScrambleGM.hint": "GM에게 텍스트를 항상 표시하려면 이 옵션을 비활성화한다. 토큰이 이해하는지는 지구본 색 참조.", 26 | "enableAllFonts.title": "모든 글꼴 사용", 27 | "enableAllFonts.hint": "언어 설정에서 Polyglot 글꼴을 사용가능하게 한다.", 28 | "RandomizeRunes.title": "룬 임의화", 29 | "RandomizeRunes.hint": "이 옵션을 활성화하면 동일한 메시지가 반복되더라도 스크램블 텍스트가 다르게 나타난다.", 30 | "RandomizeRunesOptions": { 31 | "a": "기본값", 32 | "b": "고유 문구", 33 | "c": "없음 ⚠️" 34 | }, 35 | "ExportFonts.title": "글꼴 사용 가능", 36 | "ExportFonts.hint": "Polyglot 글꼴을 Foundry에서 사용할 수 있도록 한다(예: 그리기 도구).", 37 | "DisplayTranslated.title": "번역 상자 표시", 38 | "DisplayTranslated.hint": "채팅창에서 번역된 언어의 경우 원본 텍스트 밑에 번역을 아래에 표시한다.", 39 | "HideTranslation.title": "지구본을 숨기고 \"다음 언어로부터 번역됨\" 텍스트를 플레이어에게 보임", 40 | "HideTranslation.hint": "지구본을 숨기고 \"다음 언어로부터 번역됨\" 채팅 메시지를 플레이어에게 보여준다. 플레이어에게 어떤 언어를 사용하는지 보여주고 싶지 않을 때 이상적이다.", 41 | "AllowOOC.title": "OOC 채팅 메시지 스크램블", 42 | "AllowOOC.hint": "GM이 OOC 메시지를 보낼 때 스크램블 할 수 있도록 한다.", 43 | "AllowOOCOptions": { 44 | "a": "모두", 45 | "b": "GM만", 46 | "c": "PL만", 47 | "d": "없음" 48 | }, 49 | "LanguageProvider": { 50 | "name": "언어 설정 공급자", 51 | "hint": "문자 및 언어 정보를 제공하는 공급자를 선택한다. 게임 시스템과 설치된 모듈을 통해 더 많은 언어 공급자를 이용할 수 있다. 아래 옵션은 여기서 선택한 언어 공급자에 따라 달라진다. ⚠️공급자를 변경할 경우 설정을 저장하고 다시 열어야 한다.", 52 | "choices": { 53 | "module": "[모듈] {name}", 54 | "native": "일반적", 55 | "system": "[시스템] {name}" 56 | } 57 | }, 58 | "Translation": "번역", 59 | "TranslatedFrom": "다음 언어로부터 번역됨: ", 60 | "LanguageLabel": "언어", 61 | "AlphabetLabel": "문자", 62 | "LatinAlphabet": "라틴 알파벳", 63 | "ToggleRunes": "룬 토글", 64 | "Runes": "룬", 65 | "Generic": { 66 | "Language": "언어" 67 | }, 68 | "UESRPG.Language": "언어", 69 | "COC7": { 70 | "LanguageOwn": "언어", 71 | "LanguageAny": "언어", 72 | "LanguageOther": "언어", 73 | "LanguageSpec": "언어" 74 | }, 75 | "SWADE": { 76 | "LanguageSkills": "언어" 77 | }, 78 | "WFRP4E": { 79 | "LanguageSkills": "언어" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/lang/sv.json: -------------------------------------------------------------------------------- 1 | { 2 | "POLYGLOT": { 3 | "Languages.hint": "Ändrar alfabetet som används för språken. Återställning till standardinställningarna laddar om.", 4 | "enableAllFonts": { 5 | "choices": { 6 | "0": "Ingen", 7 | "1": "Polyglot's Teckensnitt", 8 | "2": "Foundry's Extrafonter", 9 | "3": "Bägge" 10 | }, 11 | "title": "Lägg till teckensnitt i teckensnitts- och språkinställningarna", 12 | "hint": "Lägg till teckensnitt i teckensnitts- och språkinställningarna." 13 | }, 14 | "LanguageProvider": { 15 | "choices": { 16 | "module": "[Modul] {name}", 17 | "native": "Generisk", 18 | "system": "[System] {name}" 19 | }, 20 | "name": "Provider av språkinställningar", 21 | "hint": "Välj vem som tillhandahåller språkinformation för alfabet och språk. Fler språkleverantörer kan göras tillgängliga via spelsystem och installerade moduler. Alternativen nedan beror på vilken språkleverantör som väljs här. ⚠️ Om du byter leverantör har du för att spara och öppna dessa inställningar igen." 22 | }, 23 | "UESRPG.Language": "Språk", 24 | "COC7": { 25 | "LanguageOwn": "Språk", 26 | "LanguageAny": "Språk", 27 | "LanguageOther": "Språk", 28 | "LanguageSpec": "Språk" 29 | }, 30 | "DND5E": { 31 | "SpecialLanguages.title": "Ersätt specialspråk", 32 | "SpecialLanguages.hint": "Namnet på språket som kommer att ersätta \"språk\" som \"alla språk det kunde i livet\"." 33 | }, 34 | "SWADE": { 35 | "LanguageSkills": "Språk" 36 | }, 37 | "WFRP4E": { 38 | "LanguageSkills": "Språk" 39 | }, 40 | "Runes": "Runor", 41 | "Generic": { 42 | "Language": "Språk" 43 | }, 44 | "DefaultAlphabet": "Standardalfabet", 45 | "FontSettings": "Teckensnittsinställningar", 46 | "LanguageSettings": "Språkinställningar", 47 | "ChatSettings": "Chatinställningar", 48 | "Languages.title": "Språk", 49 | "Font": "Teckensnitt", 50 | "Fonts": "Teckensnitt", 51 | "FontSize": "Teckenstorlek (%)", 52 | "CustomLanguages.title": "Anpassade språk", 53 | "CustomLanguages.hint": "Definiera en lista över anpassade, kommaseparerade språk att lägga till i systemet.", 54 | "ComprehendLanguages.title": "Magiformeln Förstå Språk", 55 | "ComprehendLanguages.hint": "Sätt ett språk vars talare förstår alla andra språk, men som inte kan talas eller skrivas.", 56 | "Truespeech.title": "Tala i tungor", 57 | "Truespeech.hint": "Sätt ett språk vars talare förstår alla talade språk (kan inte läsa jJurnaler) och som förstås av alla varelser.", 58 | "JournalHighlight.title": "Journalmarkering Opacitet (%)", 59 | "JournalHighlight.hint": "Definierar opaciteten för markeringen över teckensnitt på journalen.", 60 | "logographicalFontToggle.title": "Logografiska teckensnitt", 61 | "logographicalFontToggle.hint": "Halverar storleken på fraser med hjälp av logografiska teckensnitt (t.ex. japanska, kinesiska tecken).", 62 | "DefaultLanguage.title": "Standardspråk", 63 | "DefaultLanguage.hint": "Namnet på standardspråket att välja. Lämna tomt för att använda systemets standard.", 64 | "ReplaceLanguages.title": "Ersätt systemets språk", 65 | "ReplaceLanguages.hint": "Ersätter systemets standardspråk med dina anpassade språk. Det första språket på listan blir det nya standardspråket.", 66 | "ScrambleGM.title": "Förvräng meddelanden för SL", 67 | "ScrambleGM.hint": "Översätt inte texten för SL (se globens färg för att se vad spelfigur förstår). Kräver omladdning.", 68 | "RandomizeRunes.title": "Randomisera runor", 69 | "RandomizeRunes.hint": "Detta avgör vilken typ av slumpgenerator som används för att generera en fras. ⚠️ Alternativet \"Ingen\" stöder endast alfanumeriska tecken (inga accenter).", 70 | "RandomizeRunesOptions": { 71 | "a": "Standard", 72 | "b": "Unika fraser", 73 | "c": "Inga ⚠️" 74 | }, 75 | "ExportFonts.title": "Lägg till Polyglots teckensnitt till Foundry", 76 | "ExportFonts.hint": "Lägg till Polyglots teckensnitt till Foundry meny för ytterligare teckensnitt.", 77 | "DisplayTranslated.title": "Visa översättningar", 78 | "DisplayTranslated.hint": "För språk som är översatta i chattfönstret, visa originaltexten och en översättning nedan.", 79 | "HideTranslation.title": "Dölj indikatorer från spelare", 80 | "AllowOOC.title": "Förvräng OOC Chat Messages", 81 | "AllowOOC.hint": "Välj vems användare som ska få sina meddelanden förvrängda. OOC = Utan karaktär.", 82 | "AllowOOCOptions": { 83 | "a": "Alla", 84 | "b": "Endast GM", 85 | "c": "Endast spelare", 86 | "d": "Ingen" 87 | }, 88 | "LanguageRegex": { 89 | "title": "Språkregex", 90 | "hint": "Du kan använda detta för att ändra termen som söks på objekt från \"Språk\" till något annat, som \"Tungomål\". Den här inställningen är mer användbar för icke-engelsktalande." 91 | }, 92 | "Translation": "Översättning", 93 | "TranslatedFrom": "Översatt från ", 94 | "LanguageLabel": "Språk", 95 | "LatinAlphabet": "Latinska alfabetet", 96 | "ToggleRunes": "Växla runor", 97 | "HideTranslation.hint": "Döljer globen och texten \"Översatt från\" i chattmeddelanden till spelare. Perfekt för när du inte vill visa spelare vilket språk du talar. Kräver omladdning.", 98 | "AlphabetLabel": "Alfabet" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/module.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "polyglot", 3 | "title": "Polyglot", 4 | "description": "Talk to others using a language you can speak and scrambles text you can't understand, in several fantasy scripts.", 5 | "authors": [ 6 | { 7 | "name": "Matheus Clemente", 8 | "discord": "mclemente#5524", 9 | "ko-fi": "mclemente" 10 | } 11 | ], 12 | "compatibility": { 13 | "minimum": "13", 14 | "verified": "13" 15 | }, 16 | "esmodules": ["module/polyglot.js"], 17 | "scripts": ["lib/tom-select/tom-select.complete.min.js"], 18 | "styles": ["lib/tom-select/tom-select.min.css", "styles/fonts.css", "styles/polyglot.css"], 19 | "languages": [ 20 | { 21 | "lang": "en", 22 | "name": "English", 23 | "path": "lang/en.json" 24 | }, 25 | { 26 | "lang": "pt-BR", 27 | "name": "Português (Brasil)", 28 | "path": "lang/pt-BR.json" 29 | }, 30 | { 31 | "lang": "es", 32 | "name": "Español", 33 | "path": "lang/es.json" 34 | }, 35 | { 36 | "lang": "ko", 37 | "name": "Korean", 38 | "path": "lang/ko.json" 39 | }, 40 | { 41 | "lang": "fr", 42 | "name": "French", 43 | "path": "lang/fr.json" 44 | }, 45 | { 46 | "lang": "cs", 47 | "name": "Česky", 48 | "path": "lang/cs.json" 49 | }, 50 | { 51 | "lang": "ja", 52 | "name": "日本語", 53 | "path": "lang/ja.json" 54 | }, 55 | { 56 | "lang": "pl", 57 | "name": "Polski", 58 | "path": "lang/pl.json" 59 | }, 60 | { 61 | "lang": "it", 62 | "name": "Italiano", 63 | "path": "lang/it.json" 64 | }, 65 | { 66 | "lang": "fi", 67 | "name": "Suomi", 68 | "path": "lang/fi.json" 69 | }, 70 | { 71 | "lang": "sv", 72 | "name": "Svenska", 73 | "path": "lang/sv.json" 74 | }, 75 | { 76 | "lang": "de", 77 | "name": "Deutsch", 78 | "path": "lang/de.json" 79 | }, 80 | { 81 | "lang": "cn", 82 | "name": "中文", 83 | "path": "lang/zh_Hans.json" 84 | } 85 | ], 86 | "url": "This is auto replaced", 87 | "version": "This is auto replaced", 88 | "manifest": "This is auto replaced", 89 | "download": "This is auto replaced" 90 | } 91 | -------------------------------------------------------------------------------- /src/module/api.js: -------------------------------------------------------------------------------- 1 | import * as providers from "./providers/_module.js"; 2 | import { providerKeys } from "./providers/_shared.js"; 3 | import { addSetting } from "./settings.js"; 4 | 5 | export class PolyglotAPI { 6 | constructor() { 7 | this.providers = {}; 8 | this.polyglot = null; 9 | } 10 | 11 | init() { 12 | // Assumes the first class in the file is the actual LanguageProvider class. This is better than adding an if-clause in the loop 13 | const supportedSystems = Object.keys(providers) 14 | .filter((provider) => provider !== "LanguageProvider") 15 | .map((provider) => provider.replace("LanguageProvider", "")) 16 | .join("|"); 17 | const systemsRegex = new RegExp(`^(${supportedSystems})$`); 18 | let providerString = game.system.id; 19 | if (!systemsRegex.test(game.system.id)) { 20 | providerString = providerKeys[game.system.id] || "Generic"; 21 | } 22 | 23 | const providerId = `native${providerString !== "Generic" ? `.${providerString}` : ""}`; 24 | this.providers[providerId] = new providers[`${providerString}LanguageProvider`](providerId); 25 | } 26 | 27 | get languageProvider() { 28 | return this.polyglot.languageProvider; 29 | } 30 | 31 | /** 32 | * @param {String} provider 33 | */ 34 | set languageProvider(provider) { 35 | this.polyglot.languageProvider = this.providers[provider]; 36 | } 37 | 38 | attach() { 39 | game.polyglot.api = this; 40 | this.polyglot = game.polyglot; 41 | } 42 | 43 | defaultProvider() { 44 | /** providerIds should always be sorted the same way so this should achieve a stable default. */ 45 | const providerIds = Object.keys(this.providers); 46 | let defaultValue = providerIds[0]; 47 | 48 | const module = providerIds.find((key) => key.startsWith("module.")); 49 | if (module) defaultValue = module; 50 | 51 | const gameSystem = providerIds.find((key) => key.startsWith("system.") || key.includes(game.system.id)); 52 | if (gameSystem) defaultValue = gameSystem; 53 | 54 | addSetting("languageProvider", { 55 | // Has no name or hint 56 | config: false, 57 | type: String, 58 | default: defaultValue, 59 | onChange: (s) => { 60 | this.languageProvider = this.providers[s]; 61 | }, 62 | }); 63 | } 64 | 65 | updateProvider() { 66 | // If the configured provider is registered use that one. If not use the default provider 67 | const configuredProvider = game.settings.get("polyglot", "languageProvider"); 68 | const fallbackProvider = game.settings.settings.get("polyglot.languageProvider").default; 69 | this.polyglot.languageProvider = this.providers[configuredProvider] || this.providers[fallbackProvider]; 70 | } 71 | 72 | /** 73 | * @param {String} moduleId 74 | * @param {providers.LanguageProvider} languageProvider 75 | */ 76 | registerModule(moduleId, languageProvider) { 77 | const module = game.modules.get(moduleId); 78 | if (!module) { 79 | console.warn( 80 | `Polyglot | A module tried to register with the id "${moduleId}". However no active module with this id was found. This api registration call was ignored. If you are the author of that module please check that the id passed to "registerModule" matches the id in your manifest exactly.`, 81 | ); 82 | return; 83 | } 84 | if (moduleId === "polyglot") { 85 | console.warn( 86 | `Polyglot | A module tried to register with the id "${moduleId}", which is not allowed. This api registration call was ignored. If you're the author of the module please use the id of your own module as it's specified in your manifest to register to this api.`, 87 | ); 88 | return; 89 | } 90 | 91 | this.#register(`module.${module.id}`, languageProvider); 92 | } 93 | 94 | /** 95 | * @param {providers.LanguageProvider} languageProvider 96 | */ 97 | registerSystem(languageProvider) { 98 | this.#register(`system.${game.system.id}`, languageProvider); 99 | } 100 | 101 | /** 102 | * @param {String} id 103 | * @param {providers.LanguageProvider} languageProvider 104 | */ 105 | #register(id, languageProvider) { 106 | const providerInstance = new languageProvider(id); 107 | this.providers[providerInstance.id] = providerInstance; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/module/forms/FontSettings.js: -------------------------------------------------------------------------------- 1 | export class PolyglotFontSettings extends FormApplication { 2 | /** 3 | * Default Options for this FormApplication 4 | */ 5 | static get defaultOptions() { 6 | const classes = ["sheet", "polyglot", "polyglot-font-settings"]; 7 | if (game.system.id === "wfrp4e") { 8 | classes.push(game.system.id); 9 | } 10 | return foundry.utils.mergeObject(super.defaultOptions, { 11 | id: "polyglot-font-form", 12 | title: "Polyglot Font Settings", 13 | template: "./modules/polyglot/templates/FontSettings.hbs", 14 | classes, 15 | width: 780, 16 | height: 680, 17 | closeOnSubmit: true, 18 | resizable: true, 19 | }); 20 | } 21 | 22 | getData() { 23 | const fonts = game.settings.get("polyglot", "Alphabets"); 24 | this.fonts = {}; 25 | 26 | for (let key in fonts) { 27 | this.fonts[key] = { 28 | label: key, 29 | family: fonts[key].fontFamily, 30 | size: game.polyglot.CustomFontSizes[key] || "100", 31 | alphabeticOnly: fonts[key]?.alphabeticOnly || false, 32 | logographical: fonts[key]?.logographical || false, 33 | }; 34 | } 35 | 36 | return { 37 | fonts: this.fonts, 38 | }; 39 | } 40 | 41 | async activateListeners(html) { 42 | super.activateListeners(html); 43 | 44 | const changeFontSize = async (event) => { 45 | if (!event.target.hasFocus) return; 46 | let size = event.target.value; 47 | if (event.type !== "change") { 48 | size -= event.originalEvent.deltaY / 10; 49 | } 50 | if (size < 50) return; 51 | const parent = event.target.parentElement; 52 | const font = parent.previousElementSibling.textContent; 53 | parent.nextElementSibling.nextElementSibling.nextElementSibling.style.fontSize = `${size}%`; 54 | this.fonts[font].size = size; 55 | }; 56 | const changeFontAlphabetic = async (event) => { 57 | const parent = event.target.parentElement; 58 | const font = parent.previousElementSibling.previousElementSibling.textContent; 59 | this.fonts[font].alphabeticOnly = event.target.checked; 60 | }; 61 | const changeFontLogographical = async (event) => { 62 | const parent = event.target.parentElement; 63 | const font = parent.previousElementSibling.previousElementSibling.previousElementSibling.textContent; 64 | this.fonts[font].logographical = event.target.checked; 65 | }; 66 | 67 | html.find(".alphabeticOnly").on("change", changeFontAlphabetic); 68 | html.find(".logographical").on("change", changeFontLogographical); 69 | 70 | html.find(".selectatr").on("focus", (event) => { 71 | event.target.hasFocus = true; 72 | }); 73 | html.find(".selectatr").on("blur", (event) => { 74 | event.target.hasFocus = false; 75 | }); 76 | html.find(".selectatr").on("change", changeFontSize); 77 | html.find(".selectatr").on("wheel", changeFontSize); 78 | html.find("button").on("click", async (event) => { 79 | if (event.currentTarget?.dataset?.action === "reset") { 80 | const defaultAlphabets = new game.polyglot.languageProvider.constructor().fonts; 81 | game.polyglot.languageProvider.fonts = defaultAlphabets; 82 | await game.settings.set("polyglot", "Alphabets", game.polyglot.languageProvider.fonts); 83 | const defaultCustomFontSizes = game.settings.settings.get("polyglot.CustomFontSizes").default; 84 | await game.settings.set("polyglot", "CustomFontSizes", defaultCustomFontSizes); 85 | this.close(); 86 | SettingsConfig.reloadConfirm({ world: true }); 87 | } 88 | }); 89 | } 90 | 91 | async _updateObject() { 92 | const customFontSizes = {}; 93 | for (const [key, font] of Object.entries(this.fonts)) { 94 | customFontSizes[key] = font.size; 95 | game.polyglot.languageProvider.fonts[key].alphabeticOnly = font.alphabeticOnly; 96 | game.polyglot.languageProvider.fonts[key].logographical = font.logographical; 97 | } 98 | let current = game.settings.get("polyglot", "Alphabets"); 99 | await game.settings.set("polyglot", "Alphabets", game.polyglot.languageProvider.fonts); 100 | current = game.settings.get("polyglot", "CustomFontSizes"); 101 | game.polyglot.CustomFontSizes = customFontSizes; 102 | await game.settings.set("polyglot", "CustomFontSizes", game.polyglot.CustomFontSizes); 103 | const changes = !foundry.utils.isEmpty(foundry.utils.diffObject(current, game.polyglot.languageProvider.fonts)) 104 | || !foundry.utils.isEmpty(foundry.utils.diffObject(current, customFontSizes)); 105 | if (changes) SettingsConfig.reloadConfirm({ world: true }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/module/forms/GeneralSettings.js: -------------------------------------------------------------------------------- 1 | export class PolyglotGeneralSettings extends FormApplication { 2 | static get defaultOptions() { 3 | const classes = ["sheet", "polyglot", "polyglot-general-settings"]; 4 | if (game.system.id === "wfrp4e") { 5 | classes.push(game.system.id); 6 | } 7 | return foundry.utils.mergeObject(super.defaultOptions, { 8 | id: "polyglot-general-form", 9 | title: "Polyglot General Settings", 10 | template: "./modules/polyglot/templates/GeneralSettings.hbs", 11 | classes, 12 | tabs: [{ navSelector: ".tabs", contentSelector: ".content", initial: "font" }], 13 | width: 600, 14 | height: "auto", 15 | closeOnSubmit: true, 16 | }); 17 | } 18 | 19 | _prepSetting(key, flag = false) { 20 | const settingData = game.settings.settings.get(`polyglot.${key}`); 21 | if (!flag && settingData.polyglotHide) return; 22 | 23 | const { button, choices, default: def, hasTextarea, hint, isColor, name, range, type } = settingData; 24 | let select = []; 25 | if (choices !== undefined) { 26 | const type = foundry.utils.getType(choices); 27 | if (type === "Object") select = Object.entries(choices).map(([key, value]) => ({ key, value })); 28 | else if (type === "Array") select = choices; 29 | } 30 | 31 | let settingType = type.name; 32 | if (button) { 33 | settingType = "Button"; 34 | } else if (range) { 35 | settingType = "Range"; 36 | } else if (choices) { 37 | settingType = "Select"; 38 | } else if (isColor) { 39 | settingType = "Color"; 40 | } else if (hasTextarea) { 41 | settingType = "Textarea"; 42 | } 43 | 44 | return { 45 | id: key, 46 | value: flag ? (game.user.flags?.polyglot?.[key] ?? def) : game.settings.get("polyglot", key), 47 | name, 48 | hint, 49 | type: settingType, 50 | range, 51 | select, 52 | }; 53 | } 54 | 55 | _prepFlag(key) { 56 | return this._prepSetting(key, true); 57 | } 58 | 59 | async resetToDefault(key) { 60 | const defaultValue = game.settings.settings.get(`polyglot.${key}`).default; 61 | await game.settings.set("polyglot", key, defaultValue); 62 | } 63 | 64 | getData() { 65 | const isGM = game.user.isGM; 66 | let data = {}; 67 | if (isGM) { 68 | data = { 69 | tabs: { 70 | font: { 71 | icon: "fas fa-cogs", 72 | name: "POLYGLOT.Fonts", 73 | }, 74 | journal: { 75 | icon: "fas fa-book-open", 76 | name: "SIDEBAR.TabJournal", 77 | }, 78 | languages: { 79 | icon: "fas fa-globe", 80 | name: "POLYGLOT.Languages.title", 81 | }, 82 | chat: { 83 | icon: "fas fa-comments", 84 | name: "CHAT.Chat", 85 | }, 86 | }, 87 | settings: { 88 | font: { 89 | // Font Settings 90 | RuneRegex: this._prepSetting("RuneRegex"), 91 | enableAllFonts: this._prepSetting("enableAllFonts"), 92 | exportFonts: this._prepSetting("exportFonts"), 93 | }, 94 | journal: { 95 | // Journal 96 | IgnoreJournalFontSize: this._prepSetting("IgnoreJournalFontSize"), 97 | JournalHighlightColor: this._prepSetting("JournalHighlightColor"), 98 | JournalHighlight: this._prepSetting("JournalHighlight"), 99 | }, 100 | languages: { 101 | // Languages 102 | replaceLanguages: this._prepSetting("replaceLanguages"), 103 | defaultLanguage: this._prepSetting("defaultLanguage"), 104 | customLanguages: this._prepSetting("customLanguages"), 105 | omniglot: this._prepSetting("omniglot"), 106 | comprehendLanguages: this._prepSetting("comprehendLanguages"), 107 | truespeech: this._prepSetting("truespeech"), 108 | }, 109 | chat: { 110 | // Chat 111 | enableChatFeatures: this._prepSetting("enableChatFeatures") 112 | }, 113 | }, 114 | }; 115 | if (game.settings.get("polyglot", "enableChatFeatures")) { 116 | data.settings.chat = { 117 | ...data.settings.chat, 118 | "display-translated": this._prepSetting("display-translated"), 119 | hideTranslation: this._prepSetting("hideTranslation"), 120 | allowOOC: this._prepSetting("allowOOC"), 121 | runifyGM: this._prepSetting("runifyGM"), 122 | }; 123 | } 124 | } else { 125 | data = { 126 | tabs: { 127 | languages: { 128 | icon: "fas fa-globe", 129 | name: "POLYGLOT.Languages.title", 130 | }, 131 | }, 132 | settings: { 133 | languages: { 134 | defaultLanguage: this._prepFlag("defaultLanguage"), 135 | }, 136 | }, 137 | }; 138 | } 139 | 140 | for (const s in data.settings) { 141 | // eslint-disable-next-line no-unused-vars 142 | data.settings[s] = Object.fromEntries( 143 | Object.entries(data.settings[s]).filter(([key, value]) => value !== undefined), 144 | ); 145 | } 146 | 147 | return data; 148 | } 149 | 150 | async activateListeners(html) { 151 | super.activateListeners(html); 152 | html.find("button").on("click", async (event) => { 153 | const dataset = event.currentTarget?.dataset; 154 | if (dataset?.action === "reset") { 155 | let keys = [ 156 | "defaultLanguage" 157 | ]; 158 | if (game.user.isGM) { 159 | keys = [ 160 | "RuneRegex", 161 | "enableAllFonts", 162 | "exportFonts", 163 | "IgnoreJournalFontSize", 164 | "JournalHighlightColor", 165 | "JournalHighlight", 166 | "replaceLanguages", 167 | "defaultLanguage", 168 | "customLanguages", 169 | "omniglot", 170 | "comprehendLanguages", 171 | "truespeech", 172 | "enableChatFeatures", 173 | "display-translated", 174 | "hideTranslation", 175 | "allowOOC", 176 | "runifyGM", 177 | ]; 178 | await Promise.all( 179 | keys.map(async (key) => { 180 | await this.resetToDefault(key); 181 | }), 182 | ); 183 | } else { 184 | await Promise.all( 185 | keys.map(async (key) => { 186 | await game.user.unsetFlag("polyglot", key); 187 | }), 188 | ); 189 | } 190 | this.close(); 191 | } else if (dataset?.key) { 192 | const key = dataset.key; 193 | game.polyglot.languageProvider.settings?.[key].button?.(event); 194 | } 195 | }); 196 | html.find(".form-group button[name]").on("click", async (event) => { 197 | const name = event.currentTarget.name; 198 | game.polyglot.languageProvider.settings?.[name].button?.(event); 199 | }); 200 | } 201 | 202 | async _updateObject(event, formData) { 203 | let requiresClientReload = false; 204 | let requiresWorldReload = false; 205 | for (let [k, v] of Object.entries(foundry.utils.flattenObject(formData))) { 206 | let s = game.settings.settings.get(`polyglot.${k}`); 207 | let current = game.user.isGM ? game.settings.get(s.namespace, s.key) : game.user.getFlag("polyglot", k); 208 | if (v === current) continue; 209 | requiresClientReload ||= (s.scope !== CONST.SETTING_SCOPES.WORLD) && s.requiresReload; 210 | requiresWorldReload ||= (s.scope === CONST.SETTING_SCOPES.WORLD) && s.requiresReload; 211 | if (game.user.isGM) { 212 | await game.settings.set(s.namespace, s.key, v); 213 | } else { 214 | await game.user.setFlag("polyglot", k, v); 215 | } 216 | } 217 | if (requiresClientReload || requiresWorldReload) { 218 | SettingsConfig.reloadConfirm({ world: requiresWorldReload }); 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/module/forms/LanguageSettings.js: -------------------------------------------------------------------------------- 1 | export class PolyglotLanguageSettings extends FormApplication { 2 | /** 3 | * Default Options for this FormApplication 4 | */ 5 | static get defaultOptions() { 6 | const classes = ["sheet", "polyglot", "polyglot-language-settings"]; 7 | if (game.system.id === "wfrp4e") { 8 | classes.push(game.system.id); 9 | } 10 | return foundry.utils.mergeObject(super.defaultOptions, { 11 | id: "polyglot-language-form", 12 | title: "Polyglot Language Settings", 13 | template: "./modules/polyglot/templates/LanguageSettings.hbs", 14 | classes, 15 | width: 600, 16 | height: 680, 17 | closeOnSubmit: true, 18 | resizable: true, 19 | }); 20 | } 21 | 22 | getData() { 23 | const data = {}; 24 | const selectedProvider = game.polyglot.languageProvider.id; 25 | // Insert all speed providers into the template data 26 | data.providers = Object.values(game.polyglot.api.providers).map((languageProvider) => { 27 | const provider = {}; 28 | provider.id = languageProvider.id; 29 | let dotPosition = provider.id.indexOf("."); 30 | if (dotPosition === -1) dotPosition = provider.id.length; 31 | const type = provider.id.substring(0, dotPosition); 32 | const id = provider.id.substring(dotPosition + 1); 33 | if (type === "native") { 34 | let title = id === game.system.id ? game.system.title : id; 35 | provider.selectTitle = (`${game.i18n.localize("POLYGLOT.LanguageProvider.choices.native")} ${title}`).trim(); 36 | } else { 37 | const name = type === "module" ? game.modules.get(id).title : game.system.title; 38 | provider.selectTitle = game.i18n.format(`POLYGLOT.LanguageProvider.choices.${type}`, { name }); 39 | } 40 | provider.isSelected = provider.id === selectedProvider; 41 | return provider; 42 | }); 43 | 44 | data.providerSelection = { 45 | id: "languageProvider", 46 | name: game.i18n.localize("POLYGLOT.LanguageProvider.name"), 47 | hint: game.i18n.localize("POLYGLOT.LanguageProvider.hint"), 48 | type: String, 49 | choices: data.providers.reduce((choices, provider) => { 50 | choices[provider.id] = provider.selectTitle; 51 | return choices; 52 | }, {}), 53 | value: selectedProvider, 54 | isCheckbox: false, 55 | isSelect: true, 56 | isRange: false, 57 | }; 58 | 59 | this.languageProvider = data.providerSelection.value; 60 | 61 | function prepSetting(key) { 62 | const { name, hint } = game.settings.settings.get(`polyglot.${key}`); 63 | const value = game.settings.get("polyglot", `${key}`); 64 | return { value, name, hint }; 65 | } 66 | 67 | const asArray = Object.entries(game.settings.get("polyglot", "Languages")).sort(); 68 | 69 | const { name, hint } = game.settings.settings.get("polyglot.Languages"); 70 | const filtered = asArray.filter(([key]) => { 71 | return ( 72 | key !== game.polyglot.omniglot 73 | && key !== game.polyglot.comprehendLanguages 74 | && key !== game.polyglot.truespeech 75 | ); 76 | }); 77 | const value = Object.fromEntries(filtered); 78 | 79 | const languages = { 80 | name, 81 | hint, 82 | value, 83 | }; 84 | 85 | const alphabets = prepSetting("Alphabets"); 86 | 87 | return { 88 | data, 89 | languages, 90 | alphabets, 91 | rng: { 92 | default: "POLYGLOT.RandomizeRunesOptions.a", 93 | unique: "POLYGLOT.RandomizeRunesOptions.b", 94 | none: "POLYGLOT.RandomizeRunesOptions.c" 95 | } 96 | }; 97 | } 98 | 99 | async activateListeners(html) { 100 | super.activateListeners(html); 101 | html.find(".polyglot-languageProvider").on("change", (event) => { 102 | const languagesList = html.find(".polyglot-languages-list")[0]; 103 | const languagesWarning = html.find(".polyglot-languages-warn")[0]; 104 | const shouldDisplayLanguages = this.languageProvider === event.target.value; 105 | languagesList.style.display = shouldDisplayLanguages ? "block" : "none"; 106 | languagesWarning.style.display = shouldDisplayLanguages ? "none" : "block"; 107 | }); 108 | html.find(".polyglot-alphabet").each(function () { 109 | const font = this.previousSibling.previousSibling.children[0].value; // selectatr's value 110 | this.style.font = game.polyglot.languageProvider.fonts[font]; 111 | }); 112 | html.find(".selectatr").on("change", (event) => { 113 | const font = event.target.value; 114 | const parentElement = event.target.parentElement; 115 | const nextSibling = parentElement.nextSibling; 116 | if (nextSibling && nextSibling.nextSibling) { 117 | const elementToChange = nextSibling.nextSibling; 118 | const alphabet = game.polyglot.languageProvider.fonts[font]; 119 | elementToChange.style.font = alphabet; 120 | } 121 | }); 122 | html.find("button").on("click", async (event) => { 123 | if (event.currentTarget?.dataset?.action === "reset") { 124 | const current = game.settings.get("polyglot", "Languages"); 125 | await game.settings.set("polyglot", "Languages", {}); 126 | const defaultProvider = new game.polyglot.languageProvider.constructor(); 127 | defaultProvider.getLanguages(); 128 | const diff = foundry.utils.diffObject(defaultProvider.languages, current); 129 | await game.settings.set("polyglot", "Languages", defaultProvider.languages); 130 | if (Object.keys(diff).length) SettingsConfig.reloadConfirm({ world: true }); 131 | this.close(); 132 | } 133 | }); 134 | } 135 | 136 | /** 137 | * Executes on form submission 138 | * @param {Event} ev - the form submission event 139 | * @param {Object} formData - the form data 140 | */ 141 | async _updateObject(ev, formData) { 142 | const languageProvider = game.settings.get("polyglot", "languageProvider"); 143 | if (languageProvider !== formData.languageProvider) { 144 | await game.settings.set("polyglot", "languageProvider", formData.languageProvider); 145 | game.polyglot.api.updateProvider(); 146 | await game.settings.set("polyglot", "Alphabets", game.polyglot.languageProvider.fonts); 147 | await game.settings.set("polyglot", "Languages", game.polyglot.languageProvider.languages); 148 | } else { 149 | const languages = foundry.utils.expandObject(formData).languages; 150 | const current = game.settings.get("polyglot", "Languages"); 151 | const diff = foundry.utils.diffObject(current, languages); 152 | if (!Object.keys(diff).length) return; 153 | game.polyglot.languageProvider.languages = languages; 154 | await game.settings.set("polyglot", "Languages", languages); 155 | } 156 | SettingsConfig.reloadConfirm({ world: true }); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/module/libs/colorPicker.js: -------------------------------------------------------------------------------- 1 | // Color Picker by kaelad02 2 | // License: MIT 3 | // Documentation: https://github.com/kaelad02/adv-reminder/blob/54207ec1ef0500439e57521f15956c07e4c02af4/src/settings.js#L91-L104 4 | 5 | export function colorPicker(settingId, html, settingValue) { 6 | const colorPickerElement = document.createElement("input"); 7 | colorPickerElement.setAttribute("type", "color"); 8 | colorPickerElement.setAttribute("data-edit", settingId); 9 | colorPickerElement.value = settingValue; 10 | 11 | // Add color picker 12 | const stringInputElement = html[0].querySelector(`input[name="${settingId}"]`); 13 | stringInputElement.classList.add("color"); 14 | stringInputElement.after(colorPickerElement); 15 | } 16 | -------------------------------------------------------------------------------- /src/module/libs/libWrapper.js: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro 3 | 4 | "use strict"; 5 | 6 | // A shim for the libWrapper library 7 | export let libWrapper = undefined; 8 | 9 | export const VERSIONS = [1, 12, 2]; 10 | export const TGT_SPLIT_RE = new RegExp("([^.[]+|\\[('([^'\\\\]|\\\\.)+?'|\"([^\"\\\\]|\\\\.)+?\")\\])", "g"); 11 | export const TGT_CLEANUP_RE = new RegExp("(^\\['|'\\]$|^\\[\"|\"\\]$)", "g"); 12 | 13 | // Main shim code 14 | Hooks.once("init", () => { 15 | // Check if the real module is already loaded - if so, use it 16 | if (globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) { 17 | libWrapper = globalThis.libWrapper; 18 | return; 19 | } 20 | 21 | // Fallback implementation 22 | libWrapper = class { 23 | static get is_fallback() { 24 | return true; 25 | } 26 | 27 | static get WRAPPER() { 28 | return "WRAPPER"; 29 | } 30 | 31 | static get MIXED() { 32 | return "MIXED"; 33 | } 34 | 35 | static get OVERRIDE() { 36 | return "OVERRIDE"; 37 | } 38 | 39 | static register(package_id, target, fn, type = "MIXED", { chain = undefined, bind = [] } = {}) { 40 | const is_setter = target.endsWith("#set"); 41 | target = !is_setter ? target : target.slice(0, -4); 42 | const split = target.match(TGT_SPLIT_RE).map((x) => x.replace(/\\(.)/g, "$1").replace(TGT_CLEANUP_RE, "")); 43 | const root_nm = split.splice(0, 1)[0]; 44 | 45 | let obj; let fn_name; 46 | if (split.length === 0) { 47 | obj = globalThis; 48 | fn_name = root_nm; 49 | } else { 50 | const _eval = eval; 51 | fn_name = split.pop(); 52 | obj = split.reduce((x, y) => x[y], globalThis[root_nm] ?? _eval(root_nm)); 53 | } 54 | 55 | let iObj = obj; 56 | let descriptor = null; 57 | while (iObj) { 58 | descriptor = Object.getOwnPropertyDescriptor(iObj, fn_name); 59 | if (descriptor) break; 60 | iObj = Object.getPrototypeOf(iObj); 61 | } 62 | if (!descriptor || descriptor?.configurable === false) throw new Error( 63 | `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`, 64 | ); 65 | 66 | let original = null; 67 | const wrapper = 68 | chain ?? (type.toUpperCase?.() !== "OVERRIDE" && type !== 3) 69 | ? function (...args) { 70 | return fn.call(this, original.bind(this), ...bind, ...args); 71 | } 72 | : function (...args) { 73 | return fn.call(this, ...bind, ...args); 74 | }; 75 | if (!is_setter) { 76 | if (descriptor.value) { 77 | original = descriptor.value; 78 | descriptor.value = wrapper; 79 | } else { 80 | original = descriptor.get; 81 | descriptor.get = wrapper; 82 | } 83 | } else { 84 | if (!descriptor.set) throw new Error(`libWrapper Shim: '${target}' does not have a setter`); 85 | original = descriptor.set; 86 | descriptor.set = wrapper; 87 | } 88 | 89 | descriptor.configurable = true; 90 | Object.defineProperty(obj, fn_name, descriptor); 91 | } 92 | }; 93 | }); 94 | -------------------------------------------------------------------------------- /src/module/polyglot.js: -------------------------------------------------------------------------------- 1 | import { PolyglotAPI } from "./api.js"; 2 | import { Polyglot } from "./logic.js"; 3 | import { preloadTemplates } from "./preloadTemplates.js"; 4 | import { LanguageProvider } from "./providers/_module.js"; 5 | import { 6 | registerProviderSettings, 7 | registerSettings, 8 | renderPolyglotGeneralSettingsHandler, 9 | renderSettingsConfigHandler, 10 | } from "./settings.js"; 11 | import { registerTours } from "./tour.js"; 12 | 13 | Hooks.once("init", () => { 14 | CONFIG.TinyMCE.content_css.push("/modules/polyglot/styles/polyglot.css"); 15 | registerSettings(); 16 | const api = new PolyglotAPI(); 17 | api.init(); 18 | game.polyglot = new Polyglot(); 19 | game.polyglot.init(); 20 | api.attach(); 21 | Hooks.callAll("polyglot.init", LanguageProvider); 22 | api.defaultProvider(); 23 | api.updateProvider(); 24 | game.polyglot.languageProvider.init(); 25 | return preloadTemplates(); 26 | }); 27 | 28 | Hooks.once("i18nInit", () => { 29 | game.polyglot.languageProvider.i18nInit(); 30 | }); 31 | 32 | Hooks.on("setup", async () => { 33 | if (game.user.isGM && game.user.character) { 34 | console.warn( 35 | `Polyglot | ${game.i18n.format("POLYGLOT.GameMasterHasAssignedCharacter", { 36 | GM: game.i18n.localize("USER.RoleGamemaster"), 37 | })}`, 38 | ); 39 | } 40 | registerProviderSettings(); 41 | registerTours(); 42 | await game.polyglot.languageProvider.setup(); 43 | }); 44 | Hooks.on("ready", () => { 45 | game.polyglot.ready(); 46 | Hooks.callAll("polyglot.ready", LanguageProvider); 47 | game.polyglot.languageProvider.ready(); 48 | }); 49 | Hooks.on("renderSettingsConfig", renderSettingsConfigHandler); 50 | Hooks.on("renderPolyglotGeneralSettings", renderPolyglotGeneralSettingsHandler); 51 | -------------------------------------------------------------------------------- /src/module/preloadTemplates.js: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 Johannes Loher 2 | // 3 | // SPDX-License-Identifier: MIT 4 | 5 | export async function preloadTemplates() { 6 | const templatePaths = [ 7 | "modules/polyglot/templates/partials/settings.hbs", 8 | "modules/polyglot/templates/FontSettings.hbs", 9 | "modules/polyglot/templates/GeneralSettings.hbs", 10 | "modules/polyglot/templates/LanguageSettings.hbs", 11 | ]; 12 | 13 | return foundry.applications.handlebars.loadTemplates(templatePaths); 14 | } 15 | -------------------------------------------------------------------------------- /src/module/providers/_module.js: -------------------------------------------------------------------------------- 1 | 2 | export { default as LanguageProvider } from "./templates/Base.js"; 3 | export { default as GenericLanguageProvider } from "./templates/Generic.js"; 4 | 5 | export { default as a5eLanguageProvider } from "./a5e.js"; 6 | export { default as ariaLanguageProvider } from "./aria.js"; 7 | export { default as arsLanguageProvider } from "./ars.js"; 8 | export { default as coc7LanguageProvider } from "./coc7.js"; 9 | export { default as cyberpunkRedLanguageProvider } from "./cyberpunk-red-core.js"; 10 | export { default as d35eLanguageProvider } from "./d35e.js"; 11 | export { default as darkHeresyLanguageProvider } from "./dark-heresy.js"; 12 | export { default as dccLanguageProvider } from "./dcc.js"; 13 | export { default as demonlordLanguageProvider } from "./demonlord.js"; 14 | export { default as dnd4eLanguageProvider } from "./dnd4e.js"; 15 | export { default as dnd5eLanguageProvider } from "./dnd5e.js"; 16 | export { default as dsa5LanguageProvider } from "./dsa5.js"; 17 | export { default as earthdawn4eLanguageProvider } from "./earthdawn4e.js"; 18 | export { default as fggLanguageProvider } from "./fgg.js"; 19 | export { default as gurpsLanguageProvider } from "./gurps.js"; 20 | export { default as oseLanguageProvider } from "./ose.js"; 21 | export { default as pf1LanguageProvider } from "./pf1.js"; 22 | export { default as pf2eLanguageProvider } from "./pf2e.js"; 23 | export { default as sfrpgLanguageProvider } from "./sfrpg.js"; 24 | export { default as shadowrun5eLanguageProvider } from "./shadowrun5e.js"; 25 | export { default as splittermondLanguageProvider } from "./splittermond.js"; 26 | export { default as sw5eLanguageProvider } from "./sw5e.js"; 27 | export { default as swadeLanguageProvider } from "./swade.js"; 28 | export { default as tormenta20LanguageProvider } from "./tormenta20.js"; 29 | export { default as uesrpgLanguageProvider } from "./uesrpg-d100.js"; 30 | export { default as wfrp4eLanguageProvider } from "./wfrp4e.js"; 31 | export { default as wwnLanguageProvider } from "./wwn.js"; 32 | 33 | -------------------------------------------------------------------------------- /src/module/providers/_shared.js: -------------------------------------------------------------------------------- 1 | /** Providers whose systems use "-"" in their names */ 2 | export const providerKeys = { 3 | "cyberpunk-red-core": "cyberpunkRed", 4 | "dark-heresy": "darkHeresy", 5 | "uesrpg-d100": "uesrpg", 6 | }; 7 | -------------------------------------------------------------------------------- /src/module/providers/a5e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class a5eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | aarakocra: { 6 | font: "Olde Thorass", 7 | }, 8 | abyssal: { 9 | font: "Infernal", 10 | }, 11 | aquan: { 12 | font: "Dethek", 13 | }, 14 | auran: { 15 | font: "Dethek", 16 | }, 17 | celestial: { 18 | font: "Celestial", 19 | }, 20 | common: { 21 | font: "Thorass", 22 | }, 23 | deep: { 24 | font: "Ar Ciela", 25 | }, 26 | draconic: { 27 | font: "Iokharic", 28 | }, 29 | druidic: { 30 | font: "Jungle Slang", 31 | }, 32 | dwarvish: { 33 | font: "Dethek", 34 | }, 35 | elvish: { 36 | font: "Espruar", 37 | }, 38 | giant: { 39 | font: "Dethek", 40 | }, 41 | gith: { 42 | font: "Pulsian", 43 | }, 44 | gnoll: { 45 | font: "Kargi", 46 | }, 47 | gnomish: { 48 | font: "Dethek", 49 | }, 50 | goblin: { 51 | font: "Dethek", 52 | }, 53 | halfling: { 54 | font: "Thorass", 55 | }, 56 | ignan: { 57 | font: "Dethek", 58 | }, 59 | infernal: { 60 | font: "Infernal", 61 | }, 62 | orc: { 63 | font: "Dethek", 64 | }, 65 | primordial: { 66 | font: "Dethek", 67 | }, 68 | sylvan: { 69 | font: "Olde Espruar", 70 | }, 71 | terran: { 72 | font: "Dethek", 73 | }, 74 | cant: { 75 | font: "Thorass", 76 | }, 77 | undercommon: { 78 | font: "High Drowic", 79 | }, 80 | }; 81 | 82 | /** 83 | * Get an actor's languages 84 | * @param {Document} actor 85 | * @returns [Set, Set] 86 | */ 87 | getUserLanguages(actor) { 88 | const knownLanguages = new Set(); 89 | const literateLanguages = new Set(); 90 | 91 | const langs = actor.system.proficiencies?.languages; 92 | if (!langs) return [knownLanguages, literateLanguages]; 93 | 94 | langs.forEach((lang) => { 95 | if (this.languages[lang]) knownLanguages.add(lang); 96 | }); 97 | 98 | return [knownLanguages, literateLanguages]; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/module/providers/aria.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class ariaLanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | kohestien: { 9 | font: "Tuzluca", 10 | }, 11 | aqab: { 12 | font: "Ar Ciela", 13 | }, 14 | staum: { 15 | font: "Floki", 16 | }, 17 | osmanlien: { 18 | font: "Eltharin", 19 | }, 20 | mon: { 21 | font: "Valmaric", 22 | }, 23 | nok: { 24 | font: "Dark Eldar", 25 | }, 26 | carredass: { 27 | font: "Celestial", 28 | }, 29 | blanc: { 30 | font: "Ork Glyphs", 31 | }, 32 | knigien: { 33 | font: "Tengwar", 34 | }, 35 | esperan: { 36 | font: "Thassilonian", 37 | }, 38 | altabiancais: { 39 | font: "Espruar", 40 | }, 41 | altanegrais: { 42 | font: "Espruar", 43 | }, 44 | }; 45 | 46 | getUserLanguages(actor) { 47 | let knownLanguages = new Set(); 48 | let literateLanguages = new Set(); 49 | knownLanguages.add(game.i18n.localize("ARIA.languages.Common")); 50 | for (let lang of actor.items) { 51 | if (lang.system.language) knownLanguages.add(lang.name.toLowerCase()); 52 | } 53 | return [knownLanguages, literateLanguages]; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/module/providers/ars.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class arsLanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | LanguageRegex: { 7 | type: String, 8 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 9 | } 10 | }; 11 | } 12 | 13 | async getLanguages() { 14 | this.languages = {}; 15 | if (this.replaceLanguages) return; 16 | if (game.modules.get("osric-compendium")?.active) { 17 | const langs = {}; 18 | const osricPack = game.packs.get("osric-compendium.items"); 19 | const osricItemList = await osricPack.getIndex(); 20 | const languagesSetting = game.settings.get("polyglot", "Languages"); 21 | let myRegex = new RegExp(`(?:Language:|${game.settings.get("polyglot", "LanguageRegex")}:)\\s*(.+)`, "i"); 22 | for (let item of osricItemList) { 23 | if (myRegex.test(item.name)) { 24 | let label = item.name.match(myRegex)[1].trim(); 25 | let key = label.toLowerCase(); 26 | if (!label) continue; 27 | langs[key] = { 28 | label, 29 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 30 | rng: languagesSetting[key]?.rng ?? "default", 31 | }; 32 | } 33 | } 34 | this.languages = langs; 35 | } 36 | } 37 | 38 | getUserLanguages(actor) { 39 | let knownLanguages = new Set(); 40 | let literateLanguages = new Set(); 41 | let myRegex = new RegExp(`(?:Language:|${game.settings.get("polyglot", "LanguageRegex")}:)\\s*(.+)`, "i"); 42 | for (let item of actor.items) { 43 | // adding only the descriptive language name, not "Language: XYZ" 44 | if (myRegex.test(item.name)) knownLanguages.add(item.name.match(myRegex)[1].trim().toLowerCase()); 45 | } 46 | return [knownLanguages, literateLanguages]; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/module/providers/coc7.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class coc7LanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | LanguageRegex: { 7 | type: String, 8 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 9 | }, 10 | }; 11 | } 12 | 13 | getUserLanguages(actor) { 14 | let knownLanguages = new Set(); 15 | let literateLanguages = new Set(); 16 | for (let item of actor.items) { 17 | const match = item.name.match(`${game.settings.get("polyglot", "LanguageRegex")}\\s*\\((.+)\\)`, "i") 18 | || item.name.match(`${game.i18n.localize("POLYGLOT.COC7.LanguageOwn")}\\s*\\((.+)\\)`, "i") 19 | || item.name.match(`${game.i18n.localize("POLYGLOT.COC7.LanguageAny")}\\s*\\((.+)\\)`, "i") 20 | || item.name.match(`${game.i18n.localize("POLYGLOT.COC7.LanguageOther")}\\s*\\((.+)\\)`, "i"); 21 | // adding only the descriptive language name, not "Language (XYZ)" 22 | if (match) knownLanguages.add(match[1].trim().toLowerCase()); 23 | else { 24 | switch (item.system.specialization) { 25 | case "LanguageSpec": 26 | case "Language": 27 | case "Language (Own)": 28 | case "Language (Other)": 29 | case game.i18n.localize("POLYGLOT.COC7.LanguageOwn"): 30 | case game.i18n.localize("POLYGLOT.COC7.LanguageAny"): 31 | case game.i18n.localize("POLYGLOT.COC7.LanguageOther"): 32 | case game.i18n.localize("CoC7.language"): 33 | knownLanguages.add(item.name.trim().toLowerCase()); 34 | break; 35 | default: 36 | break; 37 | } 38 | } 39 | } 40 | return [knownLanguages, literateLanguages]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/module/providers/cyberpunk-red-core.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class cyberpunkRedLanguageProvider extends LanguageProvider { 4 | defaultFont = "Olde English"; 5 | 6 | languages = { 7 | streetslang: { 8 | font: "Olde English", 9 | }, 10 | arabic: { 11 | font: "Ar Ciela", 12 | }, 13 | bengali: { 14 | font: "Olde English", 15 | }, 16 | berber: { 17 | font: "Olde English", 18 | }, 19 | burmese: { 20 | font: "Ar Ciela", 21 | }, 22 | cantonese: { 23 | font: "Oriental", 24 | }, 25 | chinese: { 26 | font: "Oriental", 27 | }, 28 | cree: { 29 | font: "Olde English", 30 | }, 31 | creole: { 32 | font: "Olde English", 33 | }, 34 | dari: { 35 | font: "Olde English", 36 | }, 37 | dutch: { 38 | font: "Olde English", 39 | }, 40 | english: { 41 | font: "Olde English", 42 | }, 43 | farsi: { 44 | font: "Ar Ciela", 45 | }, 46 | filipino: { 47 | font: "Ar Ciela", 48 | }, 49 | finnish: { 50 | font: "Kremlin Premier", 51 | }, 52 | french: { 53 | font: "Olde English", 54 | }, 55 | german: { 56 | font: "Miroslav Normal", 57 | }, 58 | guarani: { 59 | font: "Olde English", 60 | }, 61 | hausa: { 62 | font: "Olde English", 63 | }, 64 | hawaiian: { 65 | font: "Olde English", 66 | }, 67 | hebrew: { 68 | font: "Olde English", 69 | }, 70 | hindi: { 71 | font: "Ar Ciela", 72 | }, 73 | indonesian: { 74 | font: "Ar Ciela", 75 | }, 76 | italian: { 77 | font: "Olde English", 78 | }, 79 | japanese: { 80 | font: "Oriental", 81 | }, 82 | khmer: { 83 | font: "Ar Ciela", 84 | }, 85 | korean: { 86 | font: "Oriental", 87 | }, 88 | lingala: { 89 | font: "Olde English", 90 | }, 91 | malayan: { 92 | font: "Ar Ciela", 93 | }, 94 | mandarin: { 95 | font: "Oriental", 96 | }, 97 | maori: { 98 | font: "Olde English", 99 | }, 100 | mayan: { 101 | font: "Olde English", 102 | }, 103 | mongolian: { 104 | font: "Ar Ciela", 105 | }, 106 | navajo: { 107 | font: "Olde English", 108 | }, 109 | nepali: { 110 | font: "Ar Ciela", 111 | }, 112 | norwegian: { 113 | font: "Miroslav Normal", 114 | }, 115 | oromo: { 116 | font: "Olde English", 117 | }, 118 | pamanyungan: { 119 | font: "Olde English", 120 | }, 121 | polish: { 122 | font: "Kremlin Premier", 123 | }, 124 | portuguese: { 125 | font: "Olde English", 126 | }, 127 | quechua: { 128 | font: "Olde English", 129 | }, 130 | romanian: { 131 | font: "Kremlin Premier", 132 | }, 133 | russian: { 134 | font: "Kremlin Premier", 135 | }, 136 | sinhalese: { 137 | font: "Olde English", 138 | }, 139 | spanish: { 140 | font: "Olde English", 141 | }, 142 | swahili: { 143 | font: "Olde English", 144 | }, 145 | tahitian: { 146 | font: "Olde English", 147 | }, 148 | tamil: { 149 | font: "Olde English", 150 | }, 151 | turkish: { 152 | font: "Ar Ciela", 153 | }, 154 | twi: { 155 | font: "Olde English", 156 | }, 157 | ukrainian: { 158 | font: "Kremlin Premier", 159 | }, 160 | urdu: { 161 | font: "Ar Ciela", 162 | }, 163 | vietnamese: { 164 | font: "Ar Ciela", 165 | }, 166 | yoruba: { 167 | font: "Olde English", 168 | }, 169 | }; 170 | 171 | get settings() { 172 | return { 173 | LanguageRegex: { 174 | type: String, 175 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 176 | }, 177 | }; 178 | } 179 | 180 | async getLanguages() { 181 | const originalLanguages = { 182 | streetslang: "Streetslang", 183 | arabic: "Arabic", 184 | bengali: "Bengali", 185 | berber: "Berber", 186 | burmese: "Burmese", 187 | cantonese: "Cantonese", 188 | chinese: "Scrapbook Chinese", 189 | cree: "Cree", 190 | creole: "Creole", 191 | dari: "Dari", 192 | dutch: "Dutch", 193 | english: "English", 194 | farsi: "Farsi", 195 | filipino: "Filipino", 196 | finnish: "Finnish", 197 | french: "French", 198 | german: "German", 199 | guarani: "Guarani", 200 | hausa: "Hausa", 201 | hawaiian: "Hawaiian", 202 | hebrew: "Hebrew", 203 | hindi: "Hindi", 204 | indonesian: "Indonesian", 205 | italian: "Italian", 206 | japanese: "Japanese", 207 | khmer: "Khmer", 208 | korean: "Korean", 209 | lingala: "Lingala", 210 | malayan: "Malayan", 211 | mandarin: "Mandarin", 212 | maori: "Maori", 213 | mayan: "Mayan", 214 | mongolian: "Mongolian", 215 | navajo: "Navajo", 216 | nepali: "Nepali", 217 | norwegian: "Norwegian", 218 | oromo: "Oromo", 219 | pamanyungan: "Pama-nyungan", 220 | polish: "Polish", 221 | portuguese: "Portuguese", 222 | quechua: "Quechua", 223 | romanian: "Romanian", 224 | russian: "Russian", 225 | sinhalese: "Sinhalese", 226 | spanish: "Spanish", 227 | swahili: "Swahili", 228 | tahitian: "Tahitian", 229 | tamil: "Tamil", 230 | turkish: "Turkish", 231 | twi: "Twi", 232 | ukrainian: "Ukrainian", 233 | urdu: "Urdu", 234 | vietnamese: "Vietnamese", 235 | yoruba: "Yoruba", 236 | }; 237 | const langs = {}; 238 | const languagesSetting = game.settings.get("polyglot", "Languages"); 239 | for (let lang in originalLanguages) { 240 | const label = originalLanguages[lang]; 241 | if (!label) continue; 242 | langs[lang] = { 243 | label, 244 | font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont, 245 | rng: languagesSetting[lang]?.rng ?? "default", 246 | }; 247 | } 248 | this.languages = this.replaceLanguages ? {} : langs; 249 | } 250 | 251 | getUserLanguages(actor) { 252 | let knownLanguages = new Set(); 253 | let literateLanguages = new Set(); 254 | const languageRegex = game.settings.get("polyglot", "LanguageRegex"); 255 | let myRegex = new RegExp(`${languageRegex}\\s*\\((.+)\\)`, "i"); 256 | for (let item of actor.items) { 257 | if (item.type === "skill") { 258 | if (myRegex.test(item.name)) { 259 | knownLanguages.add(item.name.match(myRegex)[1].trim().toLowerCase()); 260 | } 261 | } 262 | } 263 | return [knownLanguages, literateLanguages]; 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/module/providers/d35e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class d35eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | aarakocra: { 9 | font: "Olde Thorass", 10 | }, 11 | abyssal: { 12 | font: "Infernal", 13 | }, 14 | aquan: { 15 | font: "Dethek", 16 | }, 17 | auran: { 18 | font: "Dethek", 19 | }, 20 | celestial: { 21 | font: "Celestial", 22 | }, 23 | deep: { 24 | font: "Ar Ciela", 25 | }, 26 | draconic: { 27 | font: "Iokharic", 28 | }, 29 | druidic: { 30 | font: "Jungle Slang", 31 | }, 32 | dwarven: { 33 | font: "Dethek", 34 | }, 35 | elven: { 36 | font: "Espruar", 37 | }, 38 | giant: { 39 | font: "Dethek", 40 | }, 41 | gith: { 42 | font: "tirsu", 43 | }, 44 | gnoll: { 45 | font: "Kargi", 46 | }, 47 | gnome: { 48 | font: "Dethek", 49 | }, 50 | goblin: { 51 | font: "Dethek", 52 | }, 53 | halfling: { 54 | font: "Thorass", 55 | }, 56 | ignan: { 57 | font: "Dethek", 58 | }, 59 | infernal: { 60 | font: "Infernal", 61 | }, 62 | orc: { 63 | font: "Dethek", 64 | }, 65 | primordial: { 66 | font: "Dethek", 67 | }, 68 | sylvan: { 69 | font: "Olde Espruar", 70 | }, 71 | terran: { 72 | font: "Dethek", 73 | }, 74 | cant: { 75 | font: "Thorass", 76 | }, 77 | treant: { 78 | font: "Olde Espruar", 79 | }, 80 | undercommon: { 81 | font: "High Drowic", 82 | }, 83 | }; 84 | } 85 | -------------------------------------------------------------------------------- /src/module/providers/dark-heresy.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class darkHeresyLanguageProvider extends LanguageProvider { 4 | languages = { 5 | lowGothic: { 6 | font: "Infernal", 7 | }, 8 | chapterRunes: { 9 | font: "", 10 | }, 11 | chaosMarks: { 12 | font: "", 13 | }, 14 | eldar: { 15 | font: "", 16 | }, 17 | highGothic: { 18 | font: "Infernal", 19 | }, 20 | imperialCodes: { 21 | font: "", 22 | }, 23 | mercenary: { 24 | font: "", 25 | }, 26 | necrontyr: { 27 | font: "", 28 | }, 29 | ork: { 30 | font: "Ork Glyphs", 31 | }, 32 | technaLingua: { 33 | font: "", 34 | }, 35 | tau: { 36 | font: "", 37 | }, 38 | underworld: { 39 | font: "", 40 | }, 41 | xenosMarkings: { 42 | font: "", 43 | }, 44 | }; 45 | 46 | getSystemDefaultLanguage() { 47 | return "lowGothic"; 48 | } 49 | 50 | async getLanguages() { 51 | if (this.replaceLanguages) { 52 | this.languages = {}; 53 | } else { 54 | const originalLanguages = { 55 | chapterRunes: "Chapter Runes", 56 | chaosMarks: "Chaos Marks", 57 | eldar: "Eldar", 58 | highGothic: "High Gothic", 59 | imperialCodes: "Imperial Codes", 60 | lowGothic: "Low Gothic", 61 | mercenary: "Mercenary", 62 | necrontyr: "Necrontyr", 63 | ork: "Ork", 64 | tau: "Tau", 65 | technaLingua: "Techna-Lingua", 66 | underworld: "Underworld", 67 | xenosMarkings: "Xenos Markings", 68 | }; 69 | const langs = {}; 70 | const languagesSetting = game.settings.get("polyglot", "Languages"); 71 | for (let lang in originalLanguages) { 72 | langs[lang] = { 73 | label: originalLanguages[lang], 74 | font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont, 75 | rng: languagesSetting[lang]?.rng ?? "default", 76 | }; 77 | } 78 | this.languages = langs; 79 | } 80 | } 81 | 82 | getUserLanguages(actor) { 83 | let knownLanguages = new Set(); 84 | let literateLanguages = new Set(); 85 | for (let lang in actor.system.skills.linguistics.specialities) { 86 | if (actor.system.skills.linguistics.specialities[lang].advance >= 0) knownLanguages.add(lang); 87 | } 88 | return [knownLanguages, literateLanguages]; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/module/providers/dcc.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class dccLanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | draconic: { 9 | font: "Iokharic", 10 | }, 11 | dwarvish: { 12 | font: "Dethek", 13 | }, 14 | elvish: { 15 | font: "Espruar", 16 | }, 17 | giant: { 18 | font: "Dethek", 19 | }, 20 | gnoll: { 21 | font: "Kargi", 22 | }, 23 | goblin: { 24 | font: "Dethek", 25 | }, 26 | halfling: { 27 | font: "Thorass", 28 | }, 29 | orc: { 30 | font: "Dethek", 31 | }, 32 | cant: { 33 | font: "Thorass", 34 | }, 35 | }; 36 | 37 | getUserLanguages(actor) { 38 | let knownLanguages = new Set(); 39 | let literateLanguages = new Set(); 40 | for (let lang of actor.system.details.languages.split(/[,;]/)) knownLanguages.add(lang.trim().toLowerCase()); 41 | return [knownLanguages, literateLanguages]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/module/providers/demonlord.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class demonlordLanguageProvider extends LanguageProvider { 4 | languages = { 5 | "Common Tongue": { 6 | font: "Thorass", 7 | }, 8 | "Dark Speech": { 9 | font: "Infernal", 10 | }, 11 | "High Archaic": { 12 | font: "Mage Script", 13 | }, 14 | Elvish: { 15 | font: "Espruar", 16 | }, 17 | Dwarfish: { 18 | font: "Dethek", 19 | }, 20 | "Dead Languages": { 21 | font: "Olde Thorass", 22 | }, 23 | "Secret Language": { 24 | font: "Thassilonian", 25 | }, 26 | Trollish: { 27 | font: "Ar Ciela", 28 | }, 29 | Centauri: { 30 | font: "High Drowic", 31 | }, 32 | Gnomish: { 33 | font: "High Drowic", 34 | }, 35 | Amrin: { 36 | font: "Thorass", 37 | }, 38 | Balgrennish: { 39 | font: "Tengwar", 40 | }, 41 | Bhali: { 42 | font: "Tengwar", 43 | }, 44 | Edene: { 45 | font: "Thorass", 46 | }, 47 | Erath: { 48 | font: "Thorass", 49 | }, 50 | Grennish: { 51 | font: "Tengwar", 52 | }, 53 | Kalasan: { 54 | font: "Thorass", 55 | }, 56 | Woad: { 57 | font: "Jungle Slang", 58 | }, 59 | Sylphen: { 60 | font: "High Drowic", 61 | }, 62 | Molekin: { 63 | font: "Barazhad", 64 | }, 65 | Naga: { 66 | font: "Barazhad", 67 | }, 68 | Yerath: { 69 | font: "Barazhad", 70 | }, 71 | }; 72 | 73 | requiresReady = true; 74 | 75 | getSystemDefaultLanguage() { 76 | return "Common Tongue"; 77 | } 78 | 79 | async getLanguages() { 80 | if (this.replaceLanguages) { 81 | this.languages = {}; 82 | return; 83 | } 84 | const demonlordPack = game.packs.get("demonlord.languages"); 85 | const demonlordItemList = await demonlordPack.getIndex(); 86 | const languagesSetting = game.settings.get("polyglot", "Languages"); 87 | for (let item of demonlordItemList) { 88 | const originalName = item?.flags?.babele?.originalName || item.name; 89 | this.languages[originalName] = { 90 | label: item.name, 91 | font: languagesSetting[originalName]?.font || this.languages[originalName]?.font || this.defaultFont, 92 | rng: languagesSetting[originalName]?.rng ?? "default", 93 | }; 94 | } 95 | } 96 | 97 | getUserLanguages(actor) { 98 | let knownLanguages = new Set(); 99 | let literateLanguages = new Set(); 100 | for (let item of actor.items) { 101 | if (item.type === "language") { 102 | const name = item?.flags?.babele?.originalName || item.name; 103 | if (item.system.speak) knownLanguages.add(name); 104 | if (item.system.read) literateLanguages.add(name); 105 | } 106 | } 107 | return [knownLanguages, literateLanguages]; 108 | } 109 | 110 | conditions(lang) { 111 | return game.polyglot.literateLanguages.has(lang); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/module/providers/dnd4e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class dnd4eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | abyssal: { 9 | font: "Barazhad", 10 | }, 11 | deep: { 12 | font: "Ar Ciela", 13 | }, 14 | draconic: { 15 | font: "Iokharic", 16 | }, 17 | dwarven: { 18 | font: "Davek", 19 | }, 20 | elven: { 21 | font: "Rellanic", 22 | }, 23 | giant: { 24 | font: "Davek", 25 | }, 26 | goblin: { 27 | font: "Davek", 28 | }, 29 | primordial: { 30 | font: "Davek", 31 | }, 32 | supernal: { 33 | font: "Celestial", 34 | }, 35 | }; 36 | 37 | addToConfig(key, lang) { 38 | CONFIG.DND4E.spoken[key] = lang; 39 | } 40 | 41 | removeFromConfig(key) { 42 | delete CONFIG.DND4E.spoken[key]; 43 | } 44 | 45 | async getLanguages() { 46 | const langs = {}; 47 | if (this.replaceLanguages) { 48 | CONFIG.DND4E.spoken = {}; 49 | } 50 | const languagesSetting = game.settings.get("polyglot", "Languages"); 51 | for (let lang in CONFIG.DND4E.spoken) { 52 | langs[lang] = { 53 | label: CONFIG.DND4E.spoken[lang], 54 | font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont, 55 | rng: languagesSetting[lang]?.rng ?? "default", 56 | }; 57 | } 58 | this.languages = langs; 59 | } 60 | 61 | getUserLanguages(actor) { 62 | let knownLanguages = new Set(); 63 | let literateLanguages = new Set(); 64 | for (let lang of actor.system.languages.spoken.value) { 65 | knownLanguages.add(lang); 66 | } 67 | // for (let lang of actor.system.languages.script.value) { 68 | // literateLanguages.add(lang); 69 | // } 70 | return [knownLanguages, literateLanguages]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/module/providers/dnd5e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class dnd5eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | aarakocra: { 6 | font: "Olde Thorass", 7 | }, 8 | abyssal: { 9 | font: "Infernal", 10 | }, 11 | aquan: { 12 | font: "Dethek", 13 | }, 14 | auran: { 15 | font: "Dethek", 16 | }, 17 | celestial: { 18 | font: "Celestial", 19 | }, 20 | common: { 21 | font: "Thorass", 22 | }, 23 | deep: { 24 | font: "Ar Ciela", 25 | }, 26 | draconic: { 27 | font: "Iokharic", 28 | }, 29 | druidic: { 30 | font: "Jungle Slang", 31 | }, 32 | dwarvish: { 33 | font: "Dethek", 34 | }, 35 | elvish: { 36 | font: "Espruar", 37 | }, 38 | giant: { 39 | font: "Dethek", 40 | }, 41 | gith: { 42 | font: "Pulsian", 43 | }, 44 | gnoll: { 45 | font: "Kargi", 46 | }, 47 | gnomish: { 48 | font: "Dethek", 49 | }, 50 | goblin: { 51 | font: "Dethek", 52 | }, 53 | halfling: { 54 | font: "Thorass", 55 | }, 56 | ignan: { 57 | font: "Dethek", 58 | }, 59 | infernal: { 60 | font: "Infernal", 61 | }, 62 | orc: { 63 | font: "Dethek", 64 | }, 65 | primordial: { 66 | font: "Dethek", 67 | }, 68 | sylvan: { 69 | font: "Olde Espruar", 70 | }, 71 | terran: { 72 | font: "Dethek", 73 | }, 74 | cant: { 75 | font: "Thorass", 76 | }, 77 | undercommon: { 78 | font: "High Drowic", 79 | }, 80 | }; 81 | 82 | get settings() { 83 | return { 84 | "DND5E.SpecialLanguages": { 85 | type: String, 86 | default: game.i18n.localize("DND5E.Language.Language.Common"), 87 | } 88 | }; 89 | } 90 | 91 | languageRarities = ["standard", "exotic"]; 92 | 93 | multiLanguages = { 94 | primordial: { 95 | parent: "exotic" 96 | } 97 | }; 98 | 99 | async getLanguages() { 100 | const languagesSetting = game.settings.get("polyglot", "Languages"); 101 | const langs = {}; 102 | if (this.replaceLanguages) { 103 | CONFIG.DND5E.languages = {}; 104 | this.languageRarities = []; 105 | this.multiLanguages = {}; 106 | } 107 | const systemLanguages = CONFIG.DND5E.languages; 108 | const getLang = (key, target) => { 109 | const processLanguage = (label) => { 110 | if (label) { 111 | langs[key] = { 112 | label, 113 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 114 | rng: languagesSetting[key]?.rng ?? "default", 115 | }; 116 | } 117 | }; 118 | 119 | if (key in this.multiLanguages) { 120 | processLanguage(game.i18n.localize(target[key].label)); 121 | } 122 | if (target[key].children) { 123 | Object.keys(target[key].children).forEach((kkey) => { 124 | getLang(kkey, target[key].children); 125 | }); 126 | } else { 127 | processLanguage(game.i18n.localize(target[key])); 128 | } 129 | }; 130 | Object.keys(systemLanguages).forEach((key) => { 131 | if (this.languageRarities.includes(key)) { 132 | Object.keys(systemLanguages[key].children).forEach((kkey) => { 133 | getLang(kkey, systemLanguages[key].children); 134 | }); 135 | } else { 136 | getLang(key, systemLanguages); 137 | } 138 | }); 139 | this.languages = langs; 140 | } 141 | 142 | getUserLanguages(actor) { 143 | let knownLanguages = new Set(); 144 | let literateLanguages = new Set(); 145 | if (actor.system?.traits?.languages) { 146 | for (let lang of actor.system.traits.languages.value) { 147 | if (this.languageRarities.includes(lang)) { 148 | for (let l in CONFIG.DND5E.languages[lang].children) { 149 | knownLanguages.add(l.trim().replace(/[\s']/g, "_")); 150 | } 151 | } else { 152 | knownLanguages.add(lang.trim().replace(/[\s']/g, "_")); 153 | } 154 | if (lang in this.multiLanguages) { 155 | const parent = this.multiLanguages[lang].parent; 156 | let languages; 157 | if (parent) { 158 | const parentChildren = CONFIG.DND5E.languages[parent].children; 159 | languages = parentChildren[lang].children; 160 | } else { 161 | languages = CONFIG.DND5E.languages[lang].children; 162 | } 163 | for (let l in languages) { 164 | knownLanguages.add(l.trim().replace(/[\s']/g, "_")); 165 | } 166 | } 167 | } 168 | if (actor.system.traits.languages.custom) { 169 | const defaultSpecialLanguage = game.settings 170 | .get("polyglot", "DND5E.SpecialLanguages") 171 | .trim() 172 | .toLowerCase(); 173 | // eslint-disable-next-line no-unsafe-optional-chaining 174 | for (let lang of actor.system.traits.languages?.custom.split(/[;]/)) { 175 | let key = lang.trim().toLowerCase(); 176 | try { 177 | if (/(usually common)|(in life)|(its creator)|(?<=any)(.*)(?=language)/i.test(key)) { 178 | knownLanguages.add(defaultSpecialLanguage); 179 | } else if (/(?<=usually)(.*)(?=\))/g.test(key)) { 180 | key = key.match(/(?<=usually)(.*)(?=\))/g)[0].trim(); 181 | knownLanguages.add(key); 182 | } else if (/(?<=understands)(.*)(?=but can't speak it)/g.test(key)) { 183 | key = key.match(/(?<=understands)(.*)(?=but can't speak it)/g)[0].trim(); 184 | knownLanguages.add(key); 185 | } else if (/(.*)(?=plus)/.test(key)) { 186 | key = key.match(/(.*)(?=plus)/)[0].trim(); 187 | knownLanguages.add(key); 188 | } else { 189 | knownLanguages.add(key); 190 | } 191 | } catch(err) { 192 | console.error( 193 | `Polyglot | Failed to get custom language "${key}" from actor "${actor.name}".`, 194 | err 195 | ); 196 | } 197 | } 198 | } 199 | } 200 | return [knownLanguages, literateLanguages]; 201 | } 202 | 203 | filterUsers(ownedActors) { 204 | const filtered = super.filterUsers(ownedActors); 205 | const party = game.settings.get("dnd5e", "primaryParty")?.actor; 206 | if (party?.system?.members.length) { 207 | const members = Array.from(party.system.members.ids); 208 | const users = filtered.filter((u) => ownedActors.some((actor) => members.includes(actor.id) && actor.testUserPermission(u, "OWNER"))); 209 | return users; 210 | } 211 | return filtered; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/module/providers/earthdawn4e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class earthdawn4eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | human: { 6 | font: "Thorass", 7 | }, 8 | dwarven: { 9 | font: "Dethek", 10 | }, 11 | elven: { 12 | font: "Espruar", 13 | }, 14 | windling: { 15 | font: "Olde Thorass", 16 | }, 17 | obsidiman: { 18 | font: "Dethek", 19 | }, 20 | troll: { 21 | font: "Jungle Slang", 22 | }, 23 | ork: { 24 | font: "Dethek", 25 | }, 26 | tskrang: { 27 | font: "Iokharic", 28 | }, 29 | }; 30 | 31 | get settings() { 32 | return { 33 | LanguageRegex: { 34 | type: String, 35 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 36 | }, 37 | LiteracyRegex: { 38 | type: String, 39 | default: game.i18n.localize("POLYGLOT.Generic.Read"), 40 | }, 41 | }; 42 | } 43 | 44 | async getLanguages() { 45 | const languagesSetting = game.settings.get("polyglot", "Languages"); 46 | for (let lang in this.languages) { 47 | this.languages[lang] = { 48 | label: game.i18n.localize(`earthdawn.l.language${lang.capitalize()}`), 49 | font: languagesSetting[lang]?.font || this.languages[lang]?.font || this.defaultFont, 50 | rng: languagesSetting[lang]?.rng ?? "default", 51 | }; 52 | } 53 | } 54 | 55 | getUserLanguages(actor) { 56 | let knownLanguages = new Set(); 57 | let literateLanguages = new Set(); 58 | for (let lang in actor.system.speak.languages) { 59 | if (actor.system.speak.languages[lang]) knownLanguages.add(lang); 60 | } 61 | for (let lang in actor.system.languages.write) { 62 | if (actor.system.write.languages[lang]) literateLanguages.add(lang); 63 | } 64 | if (actor.system.languages.other) { 65 | const languageRegex = game.settings.get("polyglot", "LanguageRegex"); 66 | const literacyRegex = game.settings.get("polyglot", "LiteracyRegex"); 67 | for (let lang of actor.system.languages.other.split(/[,;]/)) { 68 | const languageMatch = lang.match(`${languageRegex} \\((.+)\\)`, "i"); 69 | const literacyMatch = lang.match(`${literacyRegex} \\((.+)\\)`, "i"); 70 | if (languageMatch || literacyMatch) { 71 | if (languageMatch) knownLanguages.add(languageMatch[1].trim().toLowerCase()); 72 | else if (literacyMatch) literateLanguages.add(literacyMatch[1].trim().toLowerCase()); 73 | } else { 74 | knownLanguages.add(lang.trim().toLowerCase()); 75 | literateLanguages.add(lang.trim().toLowerCase()); 76 | } 77 | } 78 | } 79 | return [knownLanguages, literateLanguages]; 80 | } 81 | 82 | conditions(lang) { 83 | return game.polyglot.literateLanguages.has(lang); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/module/providers/fgg.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class fggLanguageProvider extends LanguageProvider { 4 | getUserLanguages(actor) { 5 | let knownLanguages = new Set(); 6 | let literateLanguages = new Set(); 7 | for (let lang of actor.system.languages.value) knownLanguages.add(lang.toLowerCase()); 8 | if (actor.system.languages.custom) { 9 | for (let lang of actor.system.languages.custom.split(/[,;]/)) knownLanguages.add(lang.trim().toLowerCase()); 10 | } 11 | return [knownLanguages, literateLanguages]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/module/providers/gurps.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class gurpsLanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | LanguageRegex: { 7 | type: String, 8 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 9 | }, 10 | }; 11 | } 12 | 13 | /** 14 | * Search through all of the advantages (including recursing into containers) looking for "Language" or translation. 15 | * Depending on the source, it can be two different patterns, Language: NAME (optionals) or Language (NAME) (optionals) 16 | * and the advantage names may or may not be translated, so we must search for both 17 | */ 18 | getUserLanguages(actor) { 19 | let knownLanguages = new Set(); 20 | let literateLanguages = new Set(); 21 | if (GURPS) { 22 | const languageRegex = game.settings.get("polyglot", "LanguageRegex"); 23 | // window.GURPS set when the GURPS game system is loaded 24 | let npat1 = ": +(?[^\\(]+)"; 25 | let npat2 = " +\\((?[^\\)]+)\\)"; 26 | GURPS.recurselist(actor.system.ads, (advantage) => { 27 | if (!this.updateForPattern( 28 | advantage, 29 | new RegExp(languageRegex + npat1, "i"), 30 | knownLanguages, 31 | literateLanguages 32 | )) if (!this.updateForPattern( 33 | advantage, 34 | new RegExp(languageRegex + npat2, "i"), 35 | knownLanguages, 36 | literateLanguages 37 | )) if (!this.updateForPattern( 38 | advantage, 39 | new RegExp(game.i18n.localize("GURPS.language") + npat1, "i"), 40 | knownLanguages, 41 | literateLanguages, 42 | true 43 | )) this.updateForPattern( 44 | advantage, 45 | new RegExp(game.i18n.localize("GURPS.language") + npat2, "i"), 46 | knownLanguages, 47 | literateLanguages, 48 | true 49 | ); 50 | }); 51 | } 52 | return [knownLanguages, literateLanguages]; 53 | } 54 | 55 | /** 56 | If we match on the Language name, search the name (or the notes) 57 | for indicators of spoken or written levels of comprehension in English, or translated 58 | */ 59 | updateForPattern(advantage, regex, knownLanguages, literateLanguages, langDetected = false) { 60 | let match = advantage.name.match(regex); 61 | if (match) { 62 | const lang = match.groups.name.trim().toLowerCase(); 63 | const wpat = new RegExp(game.i18n.localize("GURPS.written"), "i"); 64 | const spat = new RegExp(game.i18n.localize("GURPS.spoken"), "i"); 65 | let written = advantage.name.match(/written/i) || advantage.notes?.match(/written/i); 66 | if (!written) written = advantage.name.match(wpat) || advantage.notes?.match(wpat); 67 | let spoken = advantage.name.match(/spoken/i) || advantage.notes?.match(/spoken/i); 68 | if (!spoken) spoken = advantage.name.match(spat) || advantage.notes?.match(spat); 69 | if (written && spoken) { 70 | knownLanguages.add(lang); 71 | literateLanguages.add(lang); 72 | return true; 73 | } else if (written) { 74 | literateLanguages.add(lang); 75 | return true; 76 | } else if (spoken) { 77 | knownLanguages.add(lang); 78 | return true; 79 | } else if (langDetected) { // neither is specificaly identified, assume both if "Language" detected 80 | knownLanguages.add(lang); 81 | literateLanguages.add(lang); 82 | return true; 83 | } 84 | } 85 | return false; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/module/providers/ose.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class oseLanguageProvider extends LanguageProvider { 4 | languages = { 5 | Common: { 6 | label: "Common", 7 | font: "Thorass", 8 | rng: "default", 9 | }, 10 | Lawful: { 11 | label: "Lawful", 12 | font: "Celestial", 13 | rng: "default", 14 | }, 15 | Chaotic: { 16 | label: "Chaotic", 17 | font: "Barazhad", 18 | rng: "default", 19 | }, 20 | Neutral: { 21 | label: "Neutral", 22 | font: "Infernal", 23 | rng: "default", 24 | }, 25 | Bugbear: { 26 | label: "Bugbear", 27 | font: "Dethek", 28 | rng: "default", 29 | }, 30 | Doppelgänger: { 31 | label: "Doppelgänger", 32 | font: "Pulsian", 33 | rng: "default", 34 | }, 35 | Dragon: { 36 | label: "Dragon", 37 | font: "Iokharic", 38 | rng: "default", 39 | }, 40 | Dwarvish: { 41 | label: "Dwarvish", 42 | font: "Dethek", 43 | rng: "default", 44 | }, 45 | Elvish: { 46 | label: "Elvish", 47 | font: "Espruar", 48 | rng: "default", 49 | }, 50 | Gargoyle: { 51 | label: "Gargoyle", 52 | font: "High Drowic", 53 | rng: "default", 54 | }, 55 | Gnoll: { 56 | label: "Gnoll", 57 | font: "Kargi", 58 | rng: "default", 59 | }, 60 | Gnomish: { 61 | label: "Gnomish", 62 | font: "Tengwar", 63 | rng: "default", 64 | }, 65 | Goblin: { 66 | label: "Goblin", 67 | font: "Dethek", 68 | rng: "default", 69 | }, 70 | Halfling: { 71 | label: "Halfling", 72 | rng: "default", 73 | }, 74 | Harpy: { 75 | label: "Harpy", 76 | font: "Olde Thorass", 77 | rng: "default", 78 | }, 79 | Hobgoblin: { 80 | label: "Hobgoblin", 81 | font: "Dethek", 82 | rng: "default", 83 | }, 84 | Kobold: { 85 | label: "Kobold", 86 | font: "Iokharic", 87 | rng: "default", 88 | }, 89 | "Lizard Man": { 90 | label: "Lizard Man", 91 | font: "Iokharic", 92 | rng: "default", 93 | }, 94 | Medusa: { 95 | label: "Medusa", 96 | font: "High Drowic", 97 | rng: "default", 98 | }, 99 | Minotaur: { 100 | label: "Minotaur", 101 | font: "Olde Espruar", 102 | rng: "default", 103 | }, 104 | Ogre: { 105 | label: "Ogre", 106 | font: "Meroitic Demotic", 107 | rng: "default", 108 | }, 109 | Orcish: { 110 | label: "Orcish", 111 | font: "Dethek", 112 | rng: "default", 113 | }, 114 | Pixie: { 115 | label: "Pixie", 116 | font: "Olde Espruar", 117 | rng: "default", 118 | }, 119 | }; 120 | 121 | async getLanguages() { 122 | if (this.replaceLanguages) { 123 | this.languages = {}; 124 | return; 125 | } 126 | const languagesSetting = game.settings.get("polyglot", "Languages"); 127 | CONFIG.OSE.languages.forEach((key) => { 128 | this.languages[key] = { 129 | label: key, 130 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 131 | rng: languagesSetting[key]?.rng ?? "default", 132 | }; 133 | }); 134 | } 135 | 136 | getUserLanguages(actor) { 137 | let knownLanguages = new Set(); 138 | let literateLanguages = new Set(); 139 | for (let lang of actor.system.languages.value) knownLanguages.add(lang); 140 | return [knownLanguages, literateLanguages]; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/module/providers/pf1.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class pf1LanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | aboleth: { 9 | font: "Ar Ciela", 10 | }, 11 | abyssal: { 12 | font: "Barazhad", 13 | }, 14 | aklo: { 15 | font: "Ophidian", 16 | }, 17 | algollthu: { 18 | font: "Ar Ciela", 19 | }, 20 | anadi: { 21 | font: "Jungle Slang", 22 | }, 23 | aquan: { 24 | font: "Olde Thorass", 25 | }, 26 | arboreal: { 27 | font: "Olde Espruar", 28 | }, 29 | auran: { 30 | font: "Olde Thorass", 31 | }, 32 | azlanti: { 33 | font: "Tengwar", 34 | }, 35 | boggard: { 36 | font: "Semphari", 37 | }, 38 | caligni: { 39 | font: "High Drowic", 40 | }, 41 | celestial: { 42 | font: "Celestial", 43 | }, 44 | cyclops: { 45 | font: "Meroitic Demotic", 46 | }, 47 | daemonic: { 48 | font: "Infernal", 49 | }, 50 | dark: { 51 | font: "High Drowic", 52 | }, 53 | destrachan: { 54 | font: "Ar Ciela", 55 | }, 56 | draconic: { 57 | font: "Iokharic", 58 | }, 59 | drowsign: { 60 | font: "Finger Alphabet", 61 | }, 62 | druidic: { 63 | font: "Jungle Slang", 64 | }, 65 | dwarven: { 66 | font: "Dethek", 67 | }, 68 | dziriak: { 69 | font: "Pulsian", 70 | }, 71 | elven: { 72 | font: "Espruar", 73 | }, 74 | erutaki: { 75 | font: "Tuzluca", 76 | }, 77 | garundi: { 78 | font: "Qijomi", 79 | }, 80 | giant: { 81 | font: "Meroitic Demotic", 82 | }, 83 | gnoll: { 84 | font: "Kargi", 85 | }, 86 | gnome: { 87 | font: "Dethek", 88 | }, 89 | gnomish: { 90 | font: "Dethek", 91 | }, 92 | goblin: { 93 | font: "Kargi", 94 | }, 95 | grippli: { 96 | font: "Semphari", 97 | }, 98 | hallit: { 99 | font: "Tengwar", 100 | }, 101 | ignan: { 102 | font: "Dethek", 103 | }, 104 | iruxi: { 105 | font: "Semphari", 106 | }, 107 | jistkan: { 108 | font: "Valmaric", 109 | }, 110 | jotun: { 111 | font: "Meroitic Demotic", 112 | }, 113 | jyoti: { 114 | font: "Celestial", 115 | }, 116 | infernal: { 117 | font: "Infernal", 118 | }, 119 | kelish: { 120 | font: "Highschool Runes", 121 | }, 122 | mwangi: { 123 | font: "Tengwar", 124 | }, 125 | necril: { 126 | font: "High Drowic", 127 | }, 128 | orc: { 129 | font: "Dethek", 130 | }, 131 | orcish: { 132 | font: "Dethek", 133 | }, 134 | polyglot: { 135 | font: "Tengwar", 136 | }, 137 | protean: { 138 | font: "Barazhad", 139 | }, 140 | requian: { 141 | font: "Reanaarian", 142 | }, 143 | shoanti: { 144 | font: "Tengwar", 145 | }, 146 | skald: { 147 | font: "Valmaric", 148 | }, 149 | sphinx: { 150 | font: "Reanaarian", 151 | }, 152 | strix: { 153 | font: "Infernal", 154 | }, 155 | sylvan: { 156 | font: "Olde Espruar", 157 | }, 158 | shoony: { 159 | font: "Dethek", 160 | }, 161 | taldane: { 162 | font: "Tengwar", 163 | }, 164 | tengu: { 165 | font: "Oriental", 166 | }, 167 | terran: { 168 | font: "Dethek", 169 | }, 170 | thassilonian: { 171 | font: "Thassilonian", 172 | }, 173 | tien: { 174 | font: "Oriental", 175 | }, 176 | treant: { 177 | font: "Olde Espruar", 178 | }, 179 | undercommon: { 180 | font: "High Drowic", 181 | }, 182 | utopian: { 183 | font: "Maras Eye", 184 | }, 185 | varisian: { 186 | font: "Tengwar", 187 | }, 188 | vegepygmy: { 189 | font: "Kargi", 190 | }, 191 | vudrani: { 192 | font: "Qijomi", 193 | }, 194 | }; 195 | 196 | getUserLanguages(actor) { 197 | let knownLanguages = new Set(); 198 | let literateLanguages = new Set(); 199 | if (actor.system?.traits?.languages) { 200 | for (let lang of actor.system.traits.languages.total) { 201 | knownLanguages.add(lang); 202 | } 203 | if (actor.system.traits.languages.customTotal) { 204 | for (let lang of actor.system.traits.languages.customTotal) { 205 | const key = lang.trim().toLowerCase(); 206 | knownLanguages.add(key); 207 | } 208 | } 209 | } 210 | return [knownLanguages, literateLanguages]; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/module/providers/sfrpg.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class sfrpgLanguageProvider extends LanguageProvider { 4 | languages = { 5 | common: { 6 | font: "Thorass", 7 | }, 8 | abyssal: { 9 | font: "Barazhad", 10 | }, 11 | akito: { 12 | font: "Thorass", 13 | }, 14 | aklo: { 15 | font: "Ophidian", 16 | }, 17 | arkanen: { 18 | font: "Thorass", 19 | }, 20 | aquan: { 21 | font: "Olde Thorass", 22 | }, 23 | auran: { 24 | font: "Olde Thorass", 25 | }, 26 | azlanti: { 27 | font: "Tengwar", 28 | }, 29 | celestial: { 30 | font: "Celestial", 31 | }, 32 | draconic: { 33 | font: "Iokharic", 34 | }, 35 | drow: { 36 | font: "High Drowic", 37 | }, 38 | dwarven: { 39 | font: "Dethek", 40 | }, 41 | elven: { 42 | font: "Espruar", 43 | }, 44 | gnome: { 45 | font: "Dethek", 46 | }, 47 | goblin: { 48 | font: "Kargi", 49 | }, 50 | halfling: { 51 | font: "Thorass", 52 | }, 53 | ignan: { 54 | font: "Dethek", 55 | }, 56 | infernal: { 57 | font: "Infernal", 58 | }, 59 | kalo: { 60 | font: "Thorass", 61 | }, 62 | kasatha: { 63 | font: "Thorass", 64 | }, 65 | Nchaki: { 66 | font: "Thorass", 67 | }, 68 | orc: { 69 | font: "Dethek", 70 | }, 71 | sarcesian: { 72 | font: "Thorass", 73 | }, 74 | shirren: { 75 | font: "Thorass", 76 | }, 77 | shobhad: { 78 | font: "Thorass", 79 | }, 80 | terran: { 81 | font: "Olde Thorass", 82 | }, 83 | triaxian: { 84 | font: "Thorass", 85 | }, 86 | vercite: { 87 | font: "Thorass", 88 | }, 89 | vesk: { 90 | font: "Thorass", 91 | }, 92 | ysoki: { 93 | font: "Thorass", 94 | }, 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /src/module/providers/shadowrun5e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class shadowrun5eLanguageProvider extends LanguageProvider { 4 | defaultFont = "Olde English"; 5 | 6 | languages = { 7 | cityspeak: { 8 | label: "Cityspeak", 9 | font: "Olde English", 10 | }, 11 | spanish: { 12 | label: "Spanish", 13 | font: "Olde English", 14 | }, 15 | lakota: { 16 | label: "Lakota", 17 | font: "Olde English", 18 | }, 19 | dakota: { 20 | label: "Dakota", 21 | font: "Olde English", 22 | }, 23 | navajo: { 24 | label: "Navajo", 25 | font: "Olde English", 26 | }, 27 | russian: { 28 | label: "Russian", 29 | font: "Kremlin Premier", 30 | }, 31 | french: { 32 | label: "French", 33 | font: "Olde English", 34 | }, 35 | italian: { 36 | label: "Italian", 37 | font: "Olde English", 38 | }, 39 | german: { 40 | label: "German", 41 | font: "Olde English", 42 | }, 43 | aztlaner: { 44 | label: "Aztlaner Spanish", 45 | font: "Aztec", 46 | }, 47 | sperethiel: { 48 | label: "Sperethiel", 49 | font: "Espruar", 50 | }, 51 | orzet: { 52 | label: "Or'zet", 53 | font: "Ork Glyphs", 54 | }, 55 | english: { 56 | label: "English", 57 | font: "Olde English", 58 | }, 59 | japanese: { 60 | label: "Japanese", 61 | font: "Oriental", 62 | }, 63 | mandarin: { 64 | label: "Mandarin", 65 | font: "Scrapbook Chinese", 66 | }, 67 | }; 68 | 69 | getSystemDefaultLanguage() { 70 | return "cityspeak"; 71 | } 72 | 73 | getUserLanguages(actor) { 74 | let knownLanguages = new Set(); 75 | let literateLanguages = new Set(); 76 | for (let lang in actor.system.skills.language.value) { 77 | knownLanguages.add(actor.system.skills.language.value[lang].name.toLowerCase()); 78 | } 79 | return [knownLanguages, literateLanguages]; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/module/providers/splittermond.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class splittermondLanguageProvider extends LanguageProvider { 4 | getUserLanguages(actor) { 5 | let knownLanguages = new Set(); 6 | let literateLanguages = new Set(); 7 | const isLiterate = actor.items.filter((item) => item.name === "Literat" && item.type === "strength").length > 0; 8 | actor.items 9 | .filter((item) => item.type === "language") 10 | .forEach((item) => { 11 | const name = item.name.trim().toLowerCase(); 12 | knownLanguages.add(name); 13 | if (isLiterate) literateLanguages.add(name); 14 | }); 15 | return [knownLanguages, literateLanguages]; 16 | } 17 | 18 | conditions(lang) { 19 | return game.polyglot.literateLanguages.has(lang); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/module/providers/sw5e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class sw5eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | basic: { 6 | font: "Celestial", 7 | }, 8 | abyssin: { 9 | font: "Barazhad", 10 | }, 11 | aleena: { 12 | font: "Jungle Slang", 13 | }, 14 | antarian: { 15 | font: "Ar Ciela", 16 | }, 17 | anzellan: { 18 | font: "Valmaric", 19 | }, 20 | aqualish: { 21 | font: "Floki", 22 | }, 23 | arconese: { 24 | font: "Ork Glyphs", 25 | }, 26 | ardennian: { 27 | font: "Thorass", 28 | }, 29 | arkanian: { 30 | font: "Celestial", 31 | }, 32 | balosur: { 33 | font: "Ar Ciela", 34 | }, 35 | barabel: { 36 | font: "Dark Eldar", 37 | }, 38 | besalisk: { 39 | font: "Barazhad", 40 | }, 41 | binary: { 42 | font: "Celestial", 43 | }, 44 | bith: { 45 | font: "Skaven", 46 | }, 47 | bocce: { 48 | font: "Tuzluca", 49 | }, 50 | bothese: { 51 | font: "Infernal", 52 | }, 53 | catharese: { 54 | font: "Espruar", 55 | }, 56 | cerean: { 57 | font: "Olde Espruar", 58 | }, 59 | "chadra-fan": { 60 | font: "Infernal", 61 | }, 62 | chagri: { 63 | font: "Ophidian", 64 | }, 65 | cheunh: { 66 | font: "Ar Ciela", 67 | }, 68 | chevin: { 69 | font: "Eltharin", 70 | }, 71 | chironan: { 72 | font: "Saurian", 73 | }, 74 | clawdite: { 75 | font: "Reanaarian", 76 | }, 77 | codruese: { 78 | font: "Meroitic Demotic", 79 | }, 80 | colicoid: { 81 | font: "Thassilonian", 82 | }, 83 | dashadi: { 84 | font: "Iokharic", 85 | }, 86 | defel: { 87 | font: "Dark Eldar", 88 | }, 89 | devaronese: { 90 | font: "Iokharic", 91 | }, 92 | dosh: { 93 | font: "Iokharic", 94 | }, 95 | draethos: { 96 | font: "Pulsian", 97 | }, 98 | durese: { 99 | font: "Reanaarian", 100 | }, 101 | dug: { 102 | font: "Qijomi", 103 | }, 104 | ewokese: { 105 | font: "Skaven", 106 | }, 107 | falleen: { 108 | font: "Tengwar", 109 | }, 110 | felucianese: { 111 | font: "Skaven", 112 | }, 113 | gamorrese: { 114 | font: "Highschool Runes", 115 | }, 116 | gand: { 117 | font: "Reanaarian", 118 | }, 119 | geonosian: { 120 | font: "Maras Eye", 121 | }, 122 | givin: { 123 | font: "High Drowic", 124 | }, 125 | gran: { 126 | font: "Qijomi", 127 | }, 128 | gungan: { 129 | font: "Highschool Runes", 130 | }, 131 | hapan: { 132 | font: "Valmaric", 133 | }, 134 | harchese: { 135 | font: "Thassilonian", 136 | }, 137 | herglese: { 138 | font: "Ophidian", 139 | }, 140 | honoghran: { 141 | font: "Tuzluca", 142 | }, 143 | huttese: { 144 | font: "Thassilonian", 145 | }, 146 | iktotchese: { 147 | font: "Iokharic", 148 | }, 149 | ithorese: { 150 | font: "Dethek", 151 | }, 152 | jawaese: { 153 | font: "Valmaric", 154 | }, 155 | kaleesh: { 156 | font: "Infernal", 157 | }, 158 | kaminoan: { 159 | font: "Ar Ciela", 160 | }, 161 | karkaran: { 162 | font: "Ophidian", 163 | }, 164 | keldor: { 165 | font: "Meroitic Demotic", 166 | }, 167 | kharan: { 168 | font: "Ar Ciela", 169 | }, 170 | killik: { 171 | font: "Thassilonian", 172 | }, 173 | klatooinian: { 174 | font: "Thassilonian", 175 | }, 176 | kubazian: { 177 | font: "Olde Thorass", 178 | }, 179 | kushiban: { 180 | font: "Thorass", 181 | }, 182 | kyuzo: { 183 | font: "Barazhad", 184 | }, 185 | lannik: { 186 | font: "Semphari", 187 | }, 188 | lasat: { 189 | font: "Floki", 190 | }, 191 | lowickese: { 192 | font: "Qijomi", 193 | }, 194 | lurmese: { 195 | font: "Jungle Slang", 196 | }, 197 | mandoa: { 198 | font: "Kargi", 199 | }, 200 | miralukese: { 201 | font: "Miroslav Normal", 202 | }, 203 | mirialan: { 204 | font: "Miroslav Normal", 205 | }, 206 | moncal: { 207 | font: "Dark Eldar", 208 | }, 209 | mustafarian: { 210 | font: "Ork Glyphs", 211 | }, 212 | muun: { 213 | font: "Tengwar", 214 | }, 215 | nautila: { 216 | font: "Ophidian", 217 | }, 218 | ortolan: { 219 | font: "Thorass", 220 | }, 221 | pakpak: { 222 | font: "Olde Thorass", 223 | }, 224 | pyke: { 225 | font: "Meroitic Demotic", 226 | }, 227 | quarrenese: { 228 | font: "Ophidian", 229 | }, 230 | rakata: { 231 | font: "Iokharic", 232 | }, 233 | rattataki: { 234 | font: "Infernal", 235 | }, 236 | rishii: { 237 | font: "Maras Eye", 238 | }, 239 | rodese: { 240 | font: "Meroitic Demotic", 241 | }, 242 | ryn: { 243 | font: "Espruar", 244 | }, 245 | selkatha: { 246 | font: "Ophidian", 247 | }, 248 | semblan: { 249 | font: "Finger Alphabet", 250 | }, 251 | shistavanen: { 252 | font: "Pulsian", 253 | }, 254 | shyriiwook: { 255 | font: "Olde Espruar", 256 | }, 257 | sith: { 258 | font: "High Drowic", 259 | }, 260 | squibbian: { 261 | font: "Valmaric", 262 | }, 263 | sriluurian: { 264 | font: "Jungle Slang", 265 | }, 266 | "ssi-ruuvi": { 267 | font: "Maras Eye", 268 | }, 269 | sullustese: { 270 | font: "Highschool Runes", 271 | }, 272 | talzzi: { 273 | font: "Olde Thorass", 274 | }, 275 | tarasinese: { 276 | font: "Olde Espruar", 277 | }, 278 | thisspiasian: { 279 | font: "Ar Ciela", 280 | }, 281 | togorese: { 282 | font: "Floki", 283 | }, 284 | togruti: { 285 | font: "Pulsian", 286 | }, 287 | toydarian: { 288 | font: "Espruar", 289 | }, 290 | tusken: { 291 | font: "Semphari", 292 | }, 293 | "twi'leki": { 294 | font: "Tuzluca", 295 | }, 296 | ugnaught: { 297 | font: "Floki", 298 | }, 299 | umbaran: { 300 | font: "Jungle Slang", 301 | }, 302 | utapese: { 303 | font: "Eltharin", 304 | }, 305 | verpine: { 306 | font: "Thassilonian", 307 | }, 308 | vong: { 309 | font: "Valmaric", 310 | }, 311 | voss: { 312 | font: "Iokharic", 313 | }, 314 | yevethan: { 315 | font: "High Drowic", 316 | }, 317 | zabraki: { 318 | font: "Maras Eye", 319 | }, 320 | zygerrian: { 321 | font: "Floki", 322 | }, 323 | }; 324 | 325 | languageRarities = ["standard", "exotic"]; 326 | 327 | async getLanguages() { 328 | const languagesSetting = game.settings.get("polyglot", "Languages"); 329 | const langs = {}; 330 | if (this.replaceLanguages) { 331 | CONFIG.SW5E.languages = {}; 332 | } 333 | const systemLanguages = CONFIG.SW5E.languages; 334 | const getLang = (key, target) => { 335 | const processLanguage = (label) => { 336 | if (label) { 337 | langs[key] = { 338 | label, 339 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 340 | rng: languagesSetting[key]?.rng ?? "default", 341 | }; 342 | } 343 | }; 344 | 345 | if (target[key].children) { 346 | Object.keys(target[key].children).forEach((kkey) => { 347 | getLang(kkey, target[key].children); 348 | }); 349 | } else { 350 | processLanguage(game.i18n.localize(target[key])); 351 | } 352 | }; 353 | Object.keys(systemLanguages).forEach((key) => { 354 | if (this.languageRarities.includes(key)) { 355 | Object.keys(systemLanguages[key].children).forEach((kkey) => { 356 | getLang(kkey, systemLanguages[key].children); 357 | }); 358 | } else { 359 | getLang(key, systemLanguages); 360 | } 361 | }); 362 | this.languages = langs; 363 | } 364 | 365 | getSystemDefaultLanguage() { 366 | return "basic"; 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /src/module/providers/swade.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class swadeLanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | LanguageRegex: { 7 | type: String, 8 | default: game.i18n.localize("POLYGLOT.SWADE.LanguageSkills"), 9 | }, 10 | "SWADE.AdditionalLanguageStat": { 11 | hint: game.i18n.format("POLYGLOT.SWADE.AdditionalLanguageStat.hint", { 12 | setting: game.i18n.localize("POLYGLOT.LanguageRegex.title"), 13 | }), 14 | type: String, 15 | default: "", 16 | }, 17 | "SWADE.AdditionalLiterateStat": { 18 | hint: game.i18n.format("POLYGLOT.SWADE.AdditionalLiterateStat.hint", { 19 | setting: game.i18n.localize("POLYGLOT.SWADE.AdditionalLanguageStat.title"), 20 | }), 21 | type: String, 22 | default: "", 23 | }, 24 | }; 25 | } 26 | 27 | getUserLanguages(actor) { 28 | let knownLanguages = new Set(); 29 | let literateLanguages = new Set(); 30 | const additionalLanguageStat = game.settings.get("polyglot", "SWADE.AdditionalLanguageStat"); 31 | const additionalLiterateStat = game.settings.get("polyglot", "SWADE.AdditionalLiterateStat"); 32 | if (!additionalLanguageStat) { 33 | const languageRegex = game.settings.get("polyglot", "LanguageRegex"); 34 | let myRegex = new RegExp(`${languageRegex} \\((.+)\\)`, "i"); 35 | for (let item of actor.items) { 36 | const name = item?.flags?.babele?.originalName || item.name; 37 | if (myRegex.test(name)) knownLanguages.add(name.match(myRegex)[1].trim().toLowerCase()); 38 | } 39 | } else { 40 | const languages = actor.system?.additionalStats?.[additionalLanguageStat]?.value.split(/[,;]/) ?? []; 41 | for (let lang of languages) { 42 | lang = lang.trim(); 43 | knownLanguages.add(lang.toLowerCase()); 44 | this.addLanguage(lang); 45 | } 46 | } 47 | if (additionalLiterateStat) { 48 | const languages = actor.system?.additionalStats?.[additionalLiterateStat]?.value.split(/[,;]/) ?? []; 49 | for (let lang of languages) { 50 | lang = lang.trim(); 51 | literateLanguages.add(lang.toLowerCase()); 52 | this.addLanguage(lang); 53 | } 54 | } 55 | return [knownLanguages, literateLanguages]; 56 | } 57 | 58 | conditions(lang) { 59 | if (game.settings.get("polyglot", "SWADE.AdditionalLiterateStat")) return game.polyglot.literateLanguages.has(lang); 60 | return game.polyglot.knownLanguages.has(lang); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/module/providers/templates/Generic.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./Base.js"; 2 | 3 | export default class GenericLanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | languageDataPath: { 7 | hint: game.i18n.format("POLYGLOT.languageDataPath.hint", { 8 | setting: game.i18n.localize("POLYGLOT.LanguageRegex.title"), 9 | }), 10 | default: "", 11 | type: String, 12 | requiresReload: true, 13 | }, 14 | literacyDataPath: { 15 | hint: game.i18n.format("POLYGLOT.literacyDataPath.hint", { 16 | setting: game.i18n.localize("POLYGLOT.languageDataPath.title"), 17 | }), 18 | default: "", 19 | type: String, 20 | requiresReload: true, 21 | }, 22 | LanguageRegex: { 23 | type: String, 24 | default: game.i18n.localize("POLYGLOT.Generic.Language"), 25 | }, 26 | }; 27 | } 28 | 29 | async setup() { 30 | this.languageDataPath = game.settings.get("polyglot", "languageDataPath"); 31 | this.literacyDataPath = game.settings.get("polyglot", "literacyDataPath"); 32 | if (this.languageDataPath.startsWith("actor.")) this.languageDataPath = this.languageDataPath.slice(6); 33 | if (this.literacyDataPath.startsWith("actor.")) this.literacyDataPath = this.literacyDataPath.slice(6); 34 | super.setup(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/module/providers/tormenta20.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class tormenta20LanguageProvider extends LanguageProvider { 4 | languages = { 5 | comum: { 6 | font: "Thorass", 7 | }, 8 | abissal: { 9 | font: "Barazhad", 10 | }, 11 | anao: { 12 | font: "Dethek", 13 | }, 14 | aquan: { 15 | font: "Olde Thorass", 16 | }, 17 | auran: { 18 | font: "Olde Thorass", 19 | }, 20 | celestial: { 21 | font: "Celestial", 22 | }, 23 | draconico: { 24 | font: "Iokharic", 25 | }, 26 | elfico: { 27 | font: "Espruar", 28 | }, 29 | gigante: { 30 | font: "Meroitic Demotic", 31 | }, 32 | gnoll: { 33 | font: "Kargi", 34 | }, 35 | goblin: { 36 | font: "Kargi", 37 | }, 38 | ignan: { 39 | font: "Olde Thorass", 40 | }, 41 | infernal: { 42 | font: "Infernal", 43 | }, 44 | orc: { 45 | font: "Dethek", 46 | }, 47 | silvestre: { 48 | font: "Olde Espruar", 49 | }, 50 | terran: { 51 | font: "Olde Thorass", 52 | }, 53 | }; 54 | 55 | getSystemDefaultLanguage() { 56 | return "comum"; 57 | } 58 | 59 | async getLanguages() { 60 | const languagesSetting = game.settings.get("polyglot", "Languages"); 61 | const langs = {}; 62 | if (this.replaceLanguages) { 63 | CONFIG.T20.idiomas = {}; 64 | } 65 | Object.keys(CONFIG.T20.idiomas).forEach((key) => { 66 | const label = CONFIG.T20.idiomas[key]; 67 | if (label) { 68 | langs[key] = { 69 | label, 70 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 71 | rng: languagesSetting[key]?.rng ?? "default", 72 | }; 73 | } 74 | }); 75 | this.languages = langs; 76 | } 77 | 78 | getUserLanguages(actor) { 79 | let knownLanguages = new Set(); 80 | let literateLanguages = new Set(); 81 | for (let lang of actor.system.tracos.idiomas.value) knownLanguages.add(lang); 82 | return [knownLanguages, literateLanguages]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/module/providers/uesrpg-d100.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class uesrpgLanguageProvider extends LanguageProvider { 4 | languages = { 5 | cyrodilic: { 6 | font: "Thorass", 7 | }, 8 | aldmeri: { 9 | font: "Espruar", 10 | }, 11 | ayleidoon: { 12 | font: "Espruar", 13 | }, 14 | bosmeri: { 15 | font: "Mage Script", 16 | }, 17 | daedric: { 18 | font: "Daedra", 19 | }, 20 | dovah: { 21 | font: "Dragon Alphabet", 22 | }, 23 | dunmeri: { 24 | font: "High Drowic", 25 | }, 26 | dwemeris: { 27 | font: "Dethek", 28 | }, 29 | falmer: { 30 | font: "Ar Ciela", 31 | }, 32 | jel: { 33 | font: "Ophidian", 34 | }, 35 | nordic: { 36 | font: "Ny Stormning", 37 | }, 38 | taagra: { 39 | font: "Jungle Slang", 40 | }, 41 | yoku: { 42 | font: "Oriental", 43 | }, 44 | }; 45 | 46 | getSystemDefaultLanguage() { 47 | return "cyrodilic"; 48 | } 49 | 50 | async getLanguages() { 51 | const languagesSetting = game.settings.get("polyglot", "Languages"); 52 | const langs = {}; 53 | if (this.replaceLanguages) { 54 | CONFIG.UESRPG.languages = {}; 55 | } 56 | Object.keys(CONFIG.UESRPG.languages).forEach((key) => { 57 | const label = CONFIG.UESRPG.languages[key]; 58 | if (label) { 59 | langs[key] = { 60 | label, 61 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 62 | rng: languagesSetting[key]?.rng ?? "default", 63 | }; 64 | } 65 | }); 66 | this.languages = langs; 67 | } 68 | 69 | getUserLanguages(actor) { 70 | let knownLanguages = new Set(); 71 | let literateLanguages = new Set(); 72 | for (let item of actor.items) { 73 | if (item.type === "language") { 74 | if (item.system.speak) knownLanguages.add(item.name.trim().toLowerCase()); 75 | if (item.system.readWrite) literateLanguages.add(item.name.trim().toLowerCase()); 76 | } 77 | } 78 | return [knownLanguages, literateLanguages]; 79 | } 80 | 81 | conditions(lang) { 82 | return game.polyglot.literateLanguages.has(lang); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/module/providers/wfrp4e.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class wfrp4eLanguageProvider extends LanguageProvider { 4 | languages = { 5 | reikspiel: { 6 | font: "Infernal", 7 | }, 8 | wastelander: { 9 | font: "Infernal", 10 | }, 11 | classical: { 12 | font: "Infernal", 13 | }, 14 | cathan: { 15 | font: "Oriental", 16 | }, 17 | tilean: { 18 | font: "Thorass", 19 | }, 20 | estalian: { 21 | font: "Tengwar", 22 | }, 23 | gospodarinyi: { 24 | font: "Miroslav Normal", 25 | }, 26 | albion: { 27 | font: "Elder Futhark", 28 | }, 29 | norse: { 30 | font: "Elder Futhark", 31 | }, 32 | bretonnian: { 33 | font: "romance", 34 | }, 35 | druhir: { 36 | font: "Dark Eldar", 37 | }, 38 | elthárin: { 39 | font: "Eltharin", 40 | }, 41 | orcish: { 42 | font: "Ork Glyphs", 43 | }, 44 | queekish: { 45 | font: "Skaven", 46 | }, 47 | slaan: { 48 | font: "Saurian", 49 | }, 50 | khazalid: { 51 | font: "Floki", 52 | }, 53 | magick: { 54 | font: "Eltharin", 55 | }, 56 | }; 57 | 58 | requiresReady = true; 59 | 60 | get settings() { 61 | return { 62 | LanguageRegex: { 63 | type: String, 64 | default: game.i18n.localize("POLYGLOT.WFRP4E.LanguageSkills"), 65 | }, 66 | ReadWrite: { 67 | name: game.i18n.localize("POLYGLOT.WFRP4E.ReadWrite.title"), 68 | hint: game.i18n.localize("POLYGLOT.WFRP4E.ReadWrite.hint"), 69 | type: String, 70 | default: game.i18n.localize("POLYGLOT.WFRP4E.ReadWrite.default"), 71 | }, 72 | }; 73 | } 74 | 75 | getSystemDefaultLanguage() { 76 | return "reikspiel"; 77 | } 78 | 79 | async getLanguages() { 80 | if (this.replaceLanguages) { 81 | this.languages = {}; 82 | return; 83 | } 84 | let wfrp4ePack; 85 | if (isNewerVersion(game.system.version, "6.6.1")) { 86 | wfrp4ePack = game.packs.get("wfrp4e-core.items") || game.packs.get("wfrp4e.basic"); 87 | } else { 88 | wfrp4ePack = game.packs.get("wfrp4e-core.skills") || game.packs.get("wfrp4e.basic"); 89 | } 90 | const wfrp4eItemList = await wfrp4ePack.getIndex(); 91 | const languagesSetting = game.settings.get("polyglot", "Languages"); 92 | let myRegex = new RegExp(`(?:Language|${game.settings.get("polyglot", "LanguageRegex")})\\s*\\((.+)\\)`, "i"); 93 | const langs = {}; 94 | for (let item of wfrp4eItemList) { 95 | if (myRegex.test(item.name)) { 96 | let label = item.name.match(myRegex)[1].trim(); 97 | let key = label.toLowerCase(); 98 | if (!label) continue; 99 | langs[key] = { 100 | label, 101 | font: languagesSetting[key]?.font || this.languages[key]?.font || this.defaultFont, 102 | rng: languagesSetting[key]?.rng ?? "default", 103 | }; 104 | } 105 | } 106 | this.languages = langs; 107 | } 108 | 109 | getUserLanguages(actor) { 110 | let knownLanguages = new Set(); 111 | let literateLanguages = new Set(); 112 | const readWrite = game.settings.get("polyglot", "ReadWrite"); 113 | const isLiterate = actor.items.find((item) => item.name === readWrite && item.type === "talent") != null; 114 | let myRegex = new RegExp(`${game.settings.get("polyglot", "LanguageRegex")}\\s*\\((.+)\\)`, "i"); 115 | for (let item of actor.items) { 116 | // adding only the descriptive language name, not "Language (XYZ)" 117 | if (myRegex.test(item.name)) { 118 | let language = item.name.match(myRegex)[1].trim().toLowerCase(); 119 | knownLanguages.add(language); 120 | if (isLiterate) literateLanguages.add(language); 121 | } 122 | } 123 | return [knownLanguages, literateLanguages]; 124 | } 125 | 126 | conditions(lang) { 127 | return game.polyglot.literateLanguages.has(lang); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/module/providers/wwn.js: -------------------------------------------------------------------------------- 1 | import LanguageProvider from "./templates/Base.js"; 2 | 3 | export default class wwnLanguageProvider extends LanguageProvider { 4 | get settings() { 5 | return { 6 | // System has a built-in setting to handle languages. 7 | replaceLanguages: { 8 | polyglotHide: true, 9 | ...game.settings.settings.get("polyglot.replaceLanguages"), 10 | }, 11 | customLanguages: { 12 | polyglotHide: true, 13 | ...game.settings.settings.get("polyglot.customLanguages"), 14 | }, 15 | }; 16 | } 17 | 18 | getSystemDefaultLanguage() { 19 | return Object.keys(this.languages)[0]; 20 | } 21 | 22 | addLanguage(lang) { 23 | if (!lang) return; 24 | let languages = game.settings.get("wwn", "languageList"); 25 | const languagesSetting = game.settings.get("polyglot", "Languages"); 26 | if (!languages.includes(lang)) { 27 | if (languages.endsWith(",")) languages += lang; 28 | else languages += `,${lang}`; 29 | game.settings.set("wwn", "languageList", languages); 30 | } 31 | lang = lang.trim(); 32 | const key = lang.toLowerCase().replace(/[\s']/g, "_"); 33 | this.languages[key] = { 34 | label: lang, 35 | font: languagesSetting[key]?.font ?? this.defaultFont, 36 | rng: languagesSetting[key]?.rng ?? "default", 37 | }; 38 | } 39 | 40 | removeLanguage(lang) { 41 | if (!lang) return; 42 | let languages = game.settings.get("wwn", "languageList"); 43 | if (languages.includes(lang)) { 44 | languages.replace(new RegExp(`,\\s*${lang}`), ""); 45 | game.settings.set("wwn", "languageList", languages); 46 | } 47 | const key = lang.trim().toLowerCase().replace(/[\s']/g, "_"); 48 | delete this.languages[key]; 49 | } 50 | 51 | async getLanguages() { 52 | const languagesSetting = game.settings.get("polyglot", "Languages"); 53 | for (let lang of game.settings.get("wwn", "languageList").split(",")) { 54 | const key = lang.toLowerCase().replace(/[\s']/g, "_"); 55 | this.languages[key] = { 56 | label: lang, 57 | font: languagesSetting[key]?.font || this.defaultFont, 58 | rng: languagesSetting[key]?.rng ?? "default", 59 | }; 60 | } 61 | } 62 | 63 | getUserLanguages(actor) { 64 | let knownLanguages = new Set(); 65 | let literateLanguages = new Set(); 66 | if (actor.system.languages) { 67 | for (let lang of actor.system.languages.value) { 68 | knownLanguages.add(lang.toLowerCase()); 69 | } 70 | } 71 | return [knownLanguages, literateLanguages]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/module/tour.js: -------------------------------------------------------------------------------- 1 | 2 | class PolyglotTour extends foundry.nue.Tour { 3 | async _preStep() { 4 | await super._preStep(); 5 | 6 | if (this.currentStep.actions) await this.performActions(this.currentStep.actions); 7 | 8 | // If there's tab info, switch to that tab 9 | if (this.currentStep.tab) await this.switchTab(this.currentStep.tab); 10 | } 11 | 12 | async performActions(actions) { 13 | for (const action of actions) { 14 | switch (action) { 15 | case "chat-message": { 16 | await ChatMessage.create({ content: "Polyglot Test Message", flags: { polyglot: { language: "test" } } }); 17 | break; 18 | } 19 | case "user-config": { 20 | await game.user.sheet.render(true); 21 | break; 22 | } 23 | case "end": { 24 | this.configurator?.close(); 25 | game.user.sheet.close(); 26 | break; 27 | } 28 | } 29 | } 30 | } 31 | 32 | async switchTab(tab) { 33 | switch (tab.parent) { 34 | case "sidebar": 35 | ui.sidebar.activateTab(tab.id); 36 | break; 37 | case "settings": { 38 | const app = game.settings.sheet; 39 | await app._render(true); 40 | app.activateTab(tab.id); 41 | break; 42 | } 43 | case "general": { 44 | if (!this.configurator) { 45 | const configurator = game.settings.menus.get("polyglot.GeneralSettings"); 46 | this.configurator = new configurator.type(); 47 | } 48 | await this.configurator._render(true); 49 | this.configurator.activateTab(tab.id); 50 | break; 51 | } 52 | } 53 | } 54 | } 55 | 56 | export function registerTours() { 57 | game.tours.register("polyglot", "test", new PolyglotTour( 58 | { 59 | title: "POLYGLOT.TOURS.Main.title", 60 | description: "POLYGLOT.TOURS.Main.desc", 61 | restricted: true, 62 | display: game.settings.get("polyglot", "enableChatFeatures"), 63 | canBeResumed: true, 64 | steps: [ 65 | { 66 | id: "canvas", 67 | title: "POLYGLOT.TOURS.Main.Canvas.Title", 68 | content: "POLYGLOT.TOURS.Main.Canvas.Content", 69 | tab: { parent: "sidebar", id: "chat" } 70 | }, 71 | { 72 | id: "language-selector", 73 | selector: ".polyglot-lang-select", 74 | title: "POLYGLOT.TOURS.Main.LanguageSelector.Title", 75 | content: "POLYGLOT.TOURS.Main.LanguageSelector.Content" 76 | }, 77 | { 78 | id: "language-selector-dropdown", 79 | selector: ".polyglot-lang-select .ts-wrapper", 80 | title: "POLYGLOT.TOURS.Main.LanguageSelectorSelect.Title", 81 | content: "POLYGLOT.TOURS.Main.LanguageSelectorSelect.Content" 82 | }, 83 | { 84 | id: "language-selector-dropdown", 85 | selector: ".polyglot-lang-select .ts-wrapper", 86 | title: "POLYGLOT.TOURS.Main.LanguageSelectorSelect2.Title", 87 | content: "POLYGLOT.TOURS.Main.LanguageSelectorSelect2.Content" 88 | }, 89 | { 90 | id: "language-selector-pips", 91 | selector: ".polyglot-lang-select .ts-wrapper", 92 | title: "POLYGLOT.TOURS.Main.LanguageSelectorPips.Title", 93 | content: "POLYGLOT.TOURS.Main.LanguageSelectorPips.Content", 94 | actions: ["chat-message"] 95 | }, 96 | { 97 | id: "chat-message", 98 | selector: ".chat-log .chat-message:last-of-type", 99 | title: "POLYGLOT.TOURS.Main.ChatMessage.Title", 100 | content: "POLYGLOT.TOURS.Main.ChatMessage.Content", 101 | }, 102 | { 103 | id: "chat-message-scrambled", 104 | selector: ".chat-log .chat-message:last-of-type .polyglot-original-text", 105 | title: "POLYGLOT.TOURS.Main.ChatMessageScrambled.Title", 106 | content: "POLYGLOT.TOURS.Main.ChatMessageScrambled.Content", 107 | }, 108 | { 109 | id: "chat-message-translation", 110 | selector: ".chat-log .chat-message:last-of-type .polyglot-translation-text", 111 | title: "POLYGLOT.TOURS.Main.ChatMessageTranslation.Title", 112 | content: "POLYGLOT.TOURS.Main.ChatMessageTranslation.Content", 113 | }, 114 | { 115 | id: "chat-message-globe", 116 | selector: ".chat-log .chat-message:last-of-type .polyglot-message-language", 117 | title: "POLYGLOT.TOURS.Main.ChatMessageGlobe.Title", 118 | content: "POLYGLOT.TOURS.Main.ChatMessageGlobe.Content", 119 | }, 120 | { 121 | id: "chat-message-ending", 122 | selector: ".chat-log .chat-message:last-of-type", 123 | title: "POLYGLOT.TOURS.Main.ChatMessageEnding.Title", 124 | content: "POLYGLOT.TOURS.Main.ChatMessageEnding.Content", 125 | }, 126 | { 127 | id: "players-list", 128 | selector: "#ui-left aside#players #players-active", 129 | title: "POLYGLOT.TOURS.Main.PlayersList.Title", 130 | content: "POLYGLOT.TOURS.Main.PlayersList.Content" 131 | }, 132 | { 133 | id: "user-config", 134 | selector: ".application.user-config", 135 | title: "POLYGLOT.TOURS.Main.UserConfig.Title", 136 | content: "POLYGLOT.TOURS.Main.UserConfig.Content", 137 | actions: ["user-config"] 138 | }, 139 | { 140 | id: "user-config-select-character", 141 | selector: ".application.user-config fieldset:has(.form-group.character)", 142 | title: "POLYGLOT.TOURS.Main.UserConfigSelectCharacter.Title", 143 | content: "POLYGLOT.TOURS.Main.UserConfigSelectCharacter.Content", 144 | actions: ["user-config"] 145 | }, 146 | { 147 | id: "actor-ownership", 148 | selector: "#sidebar #actors", 149 | title: "POLYGLOT.TOURS.Main.ActorOwnership.Title", 150 | content: "POLYGLOT.TOURS.Main.ActorOwnership.Content", 151 | tab: { parent: "sidebar", id: "actors" } 152 | }, 153 | { 154 | id: "end", 155 | title: "POLYGLOT.TOURS.Main.End.Title", 156 | content: "POLYGLOT.TOURS.Main.End.Content", 157 | actions: ["end"] 158 | } 159 | ] 160 | } 161 | )); 162 | } 163 | -------------------------------------------------------------------------------- /src/styles/_chat.scss: -------------------------------------------------------------------------------- 1 | .polyglot-translation-text { 2 | border-top: 1px solid var(--color-border-light-2); 3 | -webkit-user-select: text; 4 | -moz-user-select: text; 5 | -ms-user-select: text; 6 | user-select: text; 7 | } 8 | 9 | a.polyglot-message-language.unclickable { 10 | cursor: default; 11 | } 12 | -------------------------------------------------------------------------------- /src/styles/_forms.scss: -------------------------------------------------------------------------------- 1 | @import "forms/common"; 2 | @import "forms/font-settings"; 3 | @import "forms/general-settings"; 4 | @import "forms/language-settings"; 5 | -------------------------------------------------------------------------------- /src/styles/_init.scss: -------------------------------------------------------------------------------- 1 | $color_1: #e2e2e2; 2 | $color_2: fieldtext; 3 | $color_3: red; 4 | $font-family_1: var(--polyglot-chat-bubble-font); 5 | $background-color_1: rgba(var(--polyglot-journal-color), var(--polyglot-journal-opacity)); 6 | $background-color_2: rgba(var(--polyglot-journal-color-temp), var(--polyglot-journal-opacity-temp)); 7 | $background-color_3: rgba(255, 255, 255, 0.4); 8 | $border-color_1: fieldtext transparent transparent transparent; 9 | -------------------------------------------------------------------------------- /src/styles/_journal.scss: -------------------------------------------------------------------------------- 1 | .polyglot-journal { 2 | background-color: $background-color_1; 3 | 4 | &-temp { 5 | background-color: $background-color_2; 6 | } 7 | } 8 | li[data-action="polyglot"] { 9 | ul { 10 | max-height: 100vh; 11 | overflow: auto; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/styles/_language-selector.scss: -------------------------------------------------------------------------------- 1 | &.polyglot-lang-select { 2 | margin: -6px 0; 3 | .ts-wrapper { 4 | &.disabled { 5 | text-decoration: line-through; 6 | } 7 | .ts-control { 8 | background: var(--color-cool-5-75); 9 | border: none; 10 | border-radius: 4px; 11 | padding: 1px 8px; 12 | } 13 | .ts-dropdown { 14 | bottom: 100%; 15 | top: unset; 16 | .optgroup-header, .option { 17 | padding: 1px 8px; 18 | } 19 | } 20 | &.focus .ts-control, .ts-control:hover { 21 | background: var(--color-cool-5); 22 | } 23 | &.input-active .ts-control { 24 | cursor: pointer; 25 | } 26 | } 27 | } 28 | 29 | &.polyglot-user-list { 30 | display: inline-flex; 31 | max-width: max-content; 32 | margin: auto; 33 | flex-wrap: wrap; 34 | div { 35 | width: 10px; 36 | height: 10px; 37 | border-radius: 50%; 38 | margin: 1px 2px; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/styles/_system-specific.scss: -------------------------------------------------------------------------------- 1 | &.wfrp4e { 2 | select { 3 | color: $color_1; 4 | option { 5 | color: $color_2; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/styles/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family:'ArCiela'; 3 | src:url('../fonts/ArCiela.ttf'); 4 | } 5 | @font-face { 6 | font-family:'Barazhad'; 7 | src:url('../fonts/Barazhad.otf'); 8 | } 9 | @font-face { 10 | font-family:'Celestial'; 11 | src:url('../fonts/Celestial.ttf'); 12 | } 13 | @font-face { 14 | font-family:'DarkEldar'; 15 | src:url('../fonts/DarkEldar.ttf'); 16 | } 17 | @font-face { 18 | font-family:'Dethek'; 19 | src:url('../fonts/Dethek.otf'); 20 | } 21 | @font-face { 22 | font-family:'ElderFuthark'; 23 | src:url('../fonts/ElderFutharkFS.ttf'); 24 | } 25 | @font-face { 26 | font-family:'Eltharin'; 27 | src:url('../fonts/Eltharin.ttf'); 28 | } 29 | @font-face { 30 | font-family:'Espruar'; 31 | src:url('../fonts/Espruar.otf'); 32 | } 33 | @font-face { 34 | font-family:'Floki'; 35 | src:url('../fonts/Floki.ttf'); 36 | } 37 | @font-face { 38 | font-family:'FingerAlphabet'; 39 | src:url('../fonts/FingerAlphabet.ttf'); 40 | } 41 | @font-face { 42 | font-family:'HighDrowic'; 43 | src:url('../fonts/HighDrowic.otf'); 44 | } 45 | @font-face { 46 | font-family:'HighschoolRunes'; 47 | src:url('../fonts/HighschoolRunes.ttf'); 48 | } 49 | @font-face { 50 | font-family:'Infernal'; 51 | src:url('../fonts/Infernal.ttf'); 52 | } 53 | @font-face { 54 | font-family:'Iokharic'; 55 | src:url('../fonts/Iokharic.otf'); 56 | } 57 | @font-face { 58 | font-family:'JungleSlang'; 59 | src:url('../fonts/JungleSlang.ttf'); 60 | } 61 | @font-face { 62 | font-family:'Kargi'; 63 | src:url('../fonts/Kargi.ttf'); 64 | } 65 | @font-face { 66 | font-family:'MarasEye'; 67 | src:url('../fonts/MarasEye.otf'); 68 | } 69 | @font-face { 70 | font-family:'MeroiticDemotic'; 71 | src:url('../fonts/MeroiticDemotic.ttf'); 72 | } 73 | @font-face { 74 | font-family:'MiroslavNormal'; 75 | src:url('../fonts/MiroslavNormal.ttf'); 76 | } 77 | @font-face { 78 | font-family:'OldeEspruar'; 79 | src:url('../fonts/OldeEspruar.otf'); 80 | } 81 | @font-face { 82 | font-family:'OldeThorass'; 83 | src:url('../fonts/OldeThorass.otf'); 84 | } 85 | @font-face { 86 | font-family:'Ophidian'; 87 | src:url('../fonts/Ophidian.otf'); 88 | } 89 | @font-face { 90 | font-family:'Pulsian'; 91 | src:url('../fonts/Pulsian.ttf'); 92 | } 93 | @font-face { 94 | font-family:'Oriental'; 95 | src:url('../fonts/Oriental.ttf'); 96 | } 97 | @font-face { 98 | font-family:'OrkGlyphs'; 99 | src:url('../fonts/OrkGlyphs.ttf'); 100 | } 101 | @font-face { 102 | font-family:'Qijomi'; 103 | src:url('../fonts/Qijomi.otf'); 104 | } 105 | @font-face { 106 | font-family:'Reanaarian'; 107 | src:url('../fonts/Reanaarian.otf'); 108 | } 109 | @font-face { 110 | font-family:'Saurian'; 111 | src:url('../fonts/Saurian.ttf'); 112 | } 113 | @font-face { 114 | font-family:'Semphari'; 115 | src:url('../fonts/Semphari.otf'); 116 | } 117 | @font-face { 118 | font-family:'Skaven'; 119 | src:url('../fonts/Skaven.ttf'); 120 | } 121 | @font-face { 122 | font-family:'Tengwar'; 123 | src:url('../fonts/Tengwar.ttf'); 124 | } 125 | @font-face { 126 | font-family:'Thassilonian'; 127 | src:url('../fonts/Thassilonian.ttf'); 128 | } 129 | @font-face { 130 | font-family:'Thorass'; 131 | src:url('../fonts/Thorass.otf'); 132 | } 133 | @font-face { 134 | font-family:'Tuzluca'; 135 | src:url('../fonts/Tuzluca.ttf'); 136 | } 137 | @font-face { 138 | font-family:'Valmaric'; 139 | src:url('../fonts/Valmaric.ttf'); 140 | } -------------------------------------------------------------------------------- /src/styles/forms/_common.scss: -------------------------------------------------------------------------------- 1 | & { 2 | .polyglot-languages-list { 3 | list-style: none; 4 | padding: 0; 5 | 6 | li { 7 | &.flexrow { 8 | flex-wrap: nowrap; 9 | } 10 | } 11 | } 12 | 13 | input.selectatr[type="number"] { 14 | width: 30px; 15 | height: 100%; 16 | background: none; 17 | border: none; 18 | border-radius: 0; 19 | border-bottom: 1px solid var(--color-border-light-tertiary); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/styles/forms/_font-settings.scss: -------------------------------------------------------------------------------- 1 | &.polyglot-font-settings { 2 | min-height: 255px; 3 | min-width: 780px; 4 | 5 | .polyglot-alphabet { 6 | margin: auto; 7 | } 8 | .font-name { 9 | flex: 0 0 150px; 10 | margin: auto; 11 | } 12 | 13 | .window-content { 14 | padding: 0; 15 | } 16 | form { 17 | height: 100%; 18 | section { 19 | padding: 1rem; 20 | overflow: hidden auto; 21 | } 22 | footer { 23 | margin: 1rem; 24 | flex: 0; 25 | } 26 | } 27 | .polyglot-languages-list { 28 | margin: 0; 29 | 30 | li { 31 | .font-name { 32 | flex: 0 0 150px; 33 | margin: auto; 34 | } 35 | .fontSize { 36 | flex: 0 0 90px; 37 | text-align: center; 38 | margin: auto; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/styles/forms/_general-settings.scss: -------------------------------------------------------------------------------- 1 | &.polyglot-general-settings { 2 | .tab { 3 | .form-group { 4 | textarea { 5 | resize: vertical; 6 | min-height: 57px; 7 | } 8 | select[name="allowOOC"] { 9 | flex: 1; 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/styles/forms/_language-settings.scss: -------------------------------------------------------------------------------- 1 | &.polyglot-language-settings { 2 | min-height: 265px; 3 | min-width: 600px; 4 | 5 | .font-name { 6 | text-transform: capitalize; 7 | } 8 | .selectatr { 9 | text-transform: capitalize; 10 | } 11 | .window-content { 12 | padding: 0; 13 | } 14 | form { 15 | height: 100%; 16 | section { 17 | padding: 1rem; 18 | overflow: hidden auto; 19 | } 20 | footer { 21 | margin: 1rem; 22 | flex: 0; 23 | } 24 | } 25 | 26 | .polyglot-languages-warn { 27 | font-weight: bold; 28 | color: $color_3; 29 | text-align: center; 30 | margin-bottom: 0.5em; 31 | display: none; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/styles/polyglot.scss: -------------------------------------------------------------------------------- 1 | @import "init"; 2 | @import "chat"; 3 | 4 | :root { 5 | --polyglot-journal-color: 255, 180, 0; 6 | --polyglot-journal-opacity: 0.25; 7 | --polyglot-journal-color-temp: 255, 180, 0; 8 | --polyglot-journal-opacity-temp: 0.25; 9 | } 10 | 11 | @import "journal"; 12 | 13 | .polyglot { 14 | &.polyglot-chat-bubble { 15 | font-family: $font-family_1; 16 | } 17 | 18 | @import "forms"; 19 | @import "language-selector"; 20 | @import "system-specific"; 21 | } 22 | 23 | #interface { 24 | &.theme-dark { 25 | .polyglot.polyglot-lang-select { 26 | .ts-wrapper { 27 | .ts-control { 28 | color: var(--color-light-1); 29 | } 30 | .ts-dropdown { 31 | background: var(--color-cool-5); 32 | .optgroup-header { 33 | border-bottom: solid 1px; 34 | } 35 | .option.active { 36 | background: var(--color-cool-3); 37 | color: var(--color-light-2); 38 | } 39 | .optgroup-header, .option { 40 | background: var(--color-cool-5); 41 | color: var(--color-light-1); 42 | } 43 | .ts-dropdown-content { 44 | scrollbar-width: none; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | &.theme-light { 51 | .polyglot.polyglot-lang-select { 52 | .ts-wrapper { 53 | .ts-control { 54 | background: rgba(255, 255, 255, 0.6); 55 | } 56 | .ts-dropdown { 57 | .optgroup-header { 58 | border-bottom: solid 1px; 59 | } 60 | } 61 | .option.active { 62 | background: #e0eef7; 63 | } 64 | &.focus .ts-control, .ts-control:hover { 65 | background: rgba(255, 255, 255, 0.85); 66 | } 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/templates/FontSettings.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
    5 |
  • 6 |
    {{localize "POLYGLOT.Font"}}
    7 |
    {{localize "POLYGLOT.FontSize"}}
    8 |
    {{localize "POLYGLOT.AlphabeticOnly"}}
    9 |
    {{localize "POLYGLOT.Logographical"}}
    10 |
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    11 |
  • 12 |
    13 | {{#each fonts}} 14 |
  • 15 |
    {{this.label}}
    16 |
    17 | 18 |
    19 |
    20 | 21 |
    22 |
    23 | 24 |
    25 |
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    29 |
  • 30 | {{/each}} 31 |
32 |
33 |
34 | 35 |
36 | 40 | 44 |
45 |
-------------------------------------------------------------------------------- /src/templates/GeneralSettings.hbs: -------------------------------------------------------------------------------- 1 |
2 | 10 | 11 |
12 | {{#each settings}} 13 |
14 | {{#each this as |setting|}} 15 | {{> "modules/polyglot/templates/partials/settings.hbs" setting}} 16 | {{/each}} 17 |
18 | {{/each}} 19 |
20 | 21 |
22 | 26 | 30 |
31 |
-------------------------------------------------------------------------------- /src/templates/LanguageSettings.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{#with data.providerSelection}} 5 |
6 | 7 | 10 |
11 |

{{this.hint}}

12 | {{/with}} 13 | 14 |
    15 |
  • 16 |
    {{localize "POLYGLOT.LanguageLabel"}}
    17 |
    {{localize "POLYGLOT.Fonts"}}
    18 |
    Randomize Letters
    19 |
  • 20 |
    21 | {{#each languages.value as |value key|}} 22 |
  • 23 |
    {{value.label}}
    24 |
    28 |
    29 | 32 |
    33 |
    34 | 37 |
    38 |
  • 39 | {{/each}} 40 |
41 |
⚠️ If you change the provider, your language settings will be 42 | overwritten.
43 |
44 |
45 | 46 |
47 | 51 | 55 |
56 |
-------------------------------------------------------------------------------- /src/templates/partials/settings.hbs: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{#if (eq type "Button")}} 4 | 5 | {{/if}} 6 | {{#if (eq type "Boolean")}} 7 | 8 | {{/if}} 9 | {{#if (eq type "String")}} 10 | 11 | {{/if}} 12 | {{#if (eq type "Textarea")}} 13 | 14 | {{/if}} 15 | {{#if (eq type "Color")}} 16 | 17 | {{/if}} 18 | {{#if (eq type "Select")}} 19 | 22 | {{/if}} 23 | {{#if (eq type "Range")}} 24 | 32 | {{value}} 33 | {{/if}} 34 |

{{localize hint}}

35 |
--------------------------------------------------------------------------------