Compare commits
187 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5eed1186ff | |||
| a87a9b3247 | |||
| 7f1c82cd91 | |||
| 048c1ed3ed | |||
| 9a2570d7e7 | |||
| 00b9c2156d | |||
| ff8b22274f | |||
| 786937f847 | |||
| c95efee8ec | |||
| 776d2f79a6 | |||
| 25a6b8cce6 | |||
| f6d7cae17b | |||
| 944a0b5fb1 | |||
| 7769653224 | |||
| ccdc5b5fae | |||
| 20158f573e | |||
| 87c60729b5 | |||
| a03a50b7c6 | |||
| fb85ccf501 | |||
| 3179442d8f | |||
| 33d3c52cd9 | |||
| 1d33e01a43 | |||
| 52ff221dd1 | |||
| 5afe178e23 | |||
| 9118b76084 | |||
| 5a62b527b9 | |||
| 2e9e14dc72 | |||
| 0a0b4893aa | |||
| 6277f81e26 | |||
| d550150787 | |||
| 7626b2153f | |||
| 6d17d1001d | |||
| 0273738d7a | |||
| 322df25ecc | |||
| ab3867d9a8 | |||
| 9bf8ec88f4 | |||
| 685f4d37a6 | |||
| f3b3fe8ac9 | |||
| d5fa49172a | |||
| b8303b9977 | |||
| 16d06c6356 | |||
| 79ddd887d9 | |||
| c394bc6725 | |||
| 9e6d7630f4 | |||
| e2fbdd3c2f | |||
| 849171af8f | |||
| 884975dda6 | |||
| 03cbf22c9b | |||
| a10cee2efa | |||
| 479c94a11d | |||
| c057f31e97 | |||
| d0bc9db6e5 | |||
| e2dd8dd1d7 | |||
| f2ff12faa6 | |||
| 50cc3d7da8 | |||
| 60b1f7a816 | |||
| 33d2bf043b | |||
| 86b20dcae6 | |||
| caf4936c9b | |||
| 7e864d2447 | |||
| ff324688f6 | |||
| efaeb1b341 | |||
| 488cb7f8a2 | |||
| 974fa08651 | |||
| 8f3312e8a8 | |||
| 57d5da0490 | |||
| daeb67319e | |||
| 213665bd1d | |||
| dfc48d6aa9 | |||
| d71d40453f | |||
| 635afbc892 | |||
| e90037e363 | |||
| a730359736 | |||
| 80acfe97c7 | |||
| b6267d07ba | |||
| 910f764823 | |||
| 7a8f302c21 | |||
| fb0c3b55c1 | |||
| f9579855a9 | |||
| 0dd1e2720a | |||
| 331d2d3d26 | |||
| f56554c2d4 | |||
| 98131b389c | |||
| 7cfe6288e1 | |||
| 84041ef2ff | |||
| 9a2af8079e | |||
| 633162d9af | |||
| 50baa0227d | |||
| 18da00f2e2 | |||
| f4f0b2c4b5 | |||
| b7d3007d31 | |||
| 67384981c1 | |||
| 4390bccfb9 | |||
| 8f5632c5ad | |||
| 1facd2ad11 | |||
| 0e1e2bbe4e | |||
| 3a2e62be4c | |||
| 697ceef8f2 | |||
| c8e81a456d | |||
| 2b334e5c5a | |||
| 90321e1284 | |||
| 9bcddb4b5c | |||
| 72fdc05f69 | |||
| e1d6540500 | |||
| 4b17719c69 | |||
| da056307dd | |||
| e4950728d8 | |||
| dac4e862b8 | |||
| 5fa45ef5bd | |||
| 9e6dafc8ca | |||
| a02b85b4bb | |||
| b3ff7805cd | |||
| 7f0ee40af4 | |||
| 39fa6da5dd | |||
| 7fd96a4540 | |||
| 8f5832b2ca | |||
| 58ce09ee06 | |||
| 3f5323d5a3 | |||
| d62482b280 | |||
| a609ea551a | |||
| 1f8e3647d3 | |||
| 76975ddc6c | |||
| 6ed0bb62b4 | |||
| 11d15d8dbb | |||
| 7cf92ddb81 | |||
| d907b36d59 | |||
| 307b626189 | |||
| f573e60079 | |||
| d3c52476f7 | |||
| 4f9d2ea846 | |||
| ec617d682e | |||
| 72d3d46e88 | |||
| 110797da9d | |||
| ab90a2e1dd | |||
| 1a3c950847 | |||
| 7fcc792255 | |||
| 97a13f9f41 | |||
| 29f1afac9a | |||
| c5d0abdc79 | |||
| 5a60c99df9 | |||
| 7d188622a8 | |||
| 97e9432d6b | |||
| c46b8fc162 | |||
| b2f1fb3a55 | |||
| 4743828e6b | |||
| 519fbbd1b2 | |||
| ebc084ad52 | |||
| 26fdd72610 | |||
| ea704c6d99 | |||
| ea88044d25 | |||
| a461cc147b | |||
| 5aefcae2ac | |||
| ba1e968510 | |||
| ba12abe506 | |||
| 29fb1dcca3 | |||
| 4be6c48aab | |||
| ee1017aa25 | |||
| bf806c5ecf | |||
| bf9709ed8e | |||
| 6c74ecfef7 | |||
| fb8c925037 | |||
| c8c154c2f4 | |||
| 92b2c4b757 | |||
| 260a354c22 | |||
| c67a969353 | |||
| 8d61703250 | |||
| 28df783bba | |||
| 51575a340b | |||
| 8068d34bf3 | |||
| b154fae0fa | |||
| c5ba1730c3 | |||
| a7d90da30e | |||
| 0bbc54a97f | |||
| 2081f1344f | |||
| d029607e16 | |||
| 5fe0c02cec | |||
| 70b45b3686 | |||
| ff098d5df1 | |||
| 95d7d70caa | |||
| 107ba6e525 | |||
| f72e0556e5 | |||
| 0ef975a177 | |||
| eb9f5450df | |||
| 7c49b50979 | |||
| 59b2fc9fd6 | |||
| f93ac987ac | |||
| fb32f9b523 |
5
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
||||
ARG VARIANT="16-bullseye"
|
||||
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
|
||||
|
||||
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
27
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "Node.js",
|
||||
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": { "VARIANT": "16-bullseye" }
|
||||
},
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "lokalise.i18n-ally"],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [80, 5432],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "pnpm install",
|
||||
|
||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "node",
|
||||
|
||||
"features": {
|
||||
"docker-from-docker": "latest"
|
||||
}
|
||||
}
|
||||
36
.env.example
@ -1,30 +1,26 @@
|
||||
# App
|
||||
# Shared
|
||||
TZ=UTC
|
||||
SECRET_KEY=change-me
|
||||
PUBLIC_URL=http://localhost
|
||||
PUBLIC_SERVER_URL=http://localhost/api
|
||||
PUBLIC_GOOGLE_CLIENT_ID=
|
||||
|
||||
# URLs
|
||||
PUBLIC_URL=http://<SERVER-IP>
|
||||
PUBLIC_SERVER_URL=http://<SERVER-IP>/api
|
||||
|
||||
# Database
|
||||
POSTGRES_HOST=localhost
|
||||
# Server
|
||||
SECRET_KEY=
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USERNAME=postgres
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_DATABASE=postgres
|
||||
POSTGRES_SSL_CERT=
|
||||
|
||||
# Auth
|
||||
JWT_SECRET=change-me
|
||||
JWT_SECRET=
|
||||
JWT_EXPIRY_TIME=604800
|
||||
|
||||
# Google
|
||||
PUBLIC_GOOGLE_CLIENT_ID=change-me
|
||||
GOOGLE_CLIENT_SECRET=change-me
|
||||
GOOGLE_API_KEY=change-me
|
||||
|
||||
# SendGrid (Optional)
|
||||
PUBLIC_GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
GOOGLE_API_KEY=
|
||||
SENDGRID_API_KEY=
|
||||
SENDGRID_FORGOT_PASSWORD_TEMPLATE_ID=
|
||||
SENDGRID_FROM_NAME=
|
||||
SENDGRID_FROM_EMAIL=
|
||||
SENDGRID_FROM_EMAIL=
|
||||
|
||||
# Flags
|
||||
PUBLIC_FLAG_DISABLE_SIGNUPS=false
|
||||
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
custom: https://paypal.me/RajaRajanA
|
||||
26
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@ -8,31 +8,29 @@ assignees: ''
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**Product Flavor**
|
||||
- [ ] Managed (https://rxresu.me)
|
||||
- [ ] Self Hosted
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
<!-- Steps to reproduce the behavior: -->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
- OS: <!--[e.g. iOS]-->
|
||||
- Browser <!--[e.g. chrome, safari]-->
|
||||
- Version <!--[e.g. 22]-->
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
<!-- Add any other context about the problem here. -->
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@ -8,13 +8,13 @@ assignees: ''
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
|
||||
22
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: 'docker'
|
||||
directory: '/server'
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
|
||||
- package-ecosystem: 'docker'
|
||||
directory: '/client'
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
|
||||
- package-ecosystem: 'gradle'
|
||||
directory: '/app'
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
|
||||
- package-ecosystem: 'github-actions'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'weekly'
|
||||
2
.github/workflows/digitalocean-deploy.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Install DigitalOcean CLI
|
||||
uses: digitalocean/action-doctl@v2.1.0
|
||||
uses: digitalocean/action-doctl@v2.1.1
|
||||
with:
|
||||
token: ${{ secrets.DIGITALOCEAN_TOKEN }}
|
||||
|
||||
|
||||
8
.github/workflows/docker-build-push.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and Push Client Image
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and Push Server Image
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@ -81,7 +81,7 @@ jobs:
|
||||
password: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Build and Push Client Image
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@ -110,7 +110,7 @@ jobs:
|
||||
password: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Build and Push Server Image
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
70
CHANGELOG.md
@ -2,6 +2,76 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [3.2.10](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.9...v3.2.10) (2022-03-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** add portuguese (pt) language to i18n locales ([7f1c82c](https://github.com/AmruthPillai/Reactive-Resume/commit/7f1c82cd9185ebb44486a16132eb44d5c2fb747a))
|
||||
|
||||
### [3.2.9](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.8...v3.2.9) (2022-03-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** add nl and ru i18n locales to app ([03cbf22](https://github.com/AmruthPillai/Reactive-Resume/commit/03cbf22c9bee96cac8f228830b67b44529b7ecee))
|
||||
|
||||
### [3.2.8](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.7...v3.2.8) (2022-03-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **client/theme:** add theme switcher to landing page ([8f5632c](https://github.com/AmruthPillai/Reactive-Resume/commit/8f5632c5ad0bc8a4b3028c2806365717fedd78c9))
|
||||
* **flags:** introduce flags, disable_user_signups ([b6267d0](https://github.com/AmruthPillai/Reactive-Resume/commit/b6267d07ba2dcaed0da3946d136a0a9a01c441d5)), closes [#698](https://github.com/AmruthPillai/Reactive-Resume/issues/698)
|
||||
* **i18n:** add Vietnamese language to i18n locales ([4390bcc](https://github.com/AmruthPillai/Reactive-Resume/commit/4390bccfb9764f2d2730ec3a124b7befb6792e9a))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **client/create-rename-slug:** fix slug accepting apostrophes and other special characters ([1facd2a](https://github.com/AmruthPillai/Reactive-Resume/commit/1facd2ad111cd9d990c808b3956d3915e8711acd)), closes [#706](https://github.com/AmruthPillai/Reactive-Resume/issues/706)
|
||||
* **disable_user_signups:** hide create account link under flag ([80acfe9](https://github.com/AmruthPillai/Reactive-Resume/commit/80acfe97c74bfa05b719285b19144144f3f7c5ba))
|
||||
|
||||
### [3.2.7](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.6...v3.2.7) (2022-03-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** add Malayalam (മലയാളം) language to i18n locales ([3a2e62b](https://github.com/AmruthPillai/Reactive-Resume/commit/3a2e62be4c9acc14f17277c060cc9ea2c417a478))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **printer/i18n:** fix dates not showing up in resume language when printing ([90321e1](https://github.com/AmruthPillai/Reactive-Resume/commit/90321e1284409ab9442883c04a9b4c591d36f95d)), closes [#729](https://github.com/AmruthPillai/Reactive-Resume/issues/729)
|
||||
|
||||
### [3.2.6](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.5...v3.2.6) (2022-03-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **client/auth/google:** disable google login/registration if GOOGLE_CLIENT_ID is not in ENV ([7f0ee40](https://github.com/AmruthPillai/Reactive-Resume/commit/7f0ee40af4acc7eb41514406ecee3218ace9e891)), closes [#724](https://github.com/AmruthPillai/Reactive-Resume/issues/724)
|
||||
* **i18n:** add arabic language to i18n locale ([39fa6da](https://github.com/AmruthPillai/Reactive-Resume/commit/39fa6da5dd77ce2e12e81530fa18c2eac722c1f2))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **i18n:** add missing languages to dayjs date wrapper locales ([9e6dafc](https://github.com/AmruthPillai/Reactive-Resume/commit/9e6dafc8cada5c01559894905996b81004bedaec)), closes [#719](https://github.com/AmruthPillai/Reactive-Resume/issues/719)
|
||||
* **json-export:** add mimeType and charset to JSON export ([b3ff780](https://github.com/AmruthPillai/Reactive-Resume/commit/b3ff7805cd856a52900d9acef0554867d8ce0b01)), closes [#726](https://github.com/AmruthPillai/Reactive-Resume/issues/726)
|
||||
* **linkedin:** fix skill modal crashing when importing from linkedin ([a02b85b](https://github.com/AmruthPillai/Reactive-Resume/commit/a02b85b4bb1c4a1499aacddeac7bc59bcb1f7adb)), closes [#718](https://github.com/AmruthPillai/Reactive-Resume/issues/718)
|
||||
|
||||
### [3.2.5](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.4...v3.2.5) (2022-03-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** add danish, polish and turkish locales to i18n ([97e9432](https://github.com/AmruthPillai/Reactive-Resume/commit/97e9432d6bd887e666a3443fbfde9a92cef53965))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **client/templates:** fix text veering off of artboard in most templates ([b2f1fb3](https://github.com/AmruthPillai/Reactive-Resume/commit/b2f1fb3a5502988a49c5cd3e496d9d165f5c1792)), closes [#702](https://github.com/AmruthPillai/Reactive-Resume/issues/702)
|
||||
|
||||
### [3.2.4](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.3...v3.2.4) (2022-03-14)
|
||||
|
||||
### [3.2.3](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.2.2...v3.2.3) (2022-03-14)
|
||||
|
||||
|
||||
|
||||
28
README.md
@ -1,11 +1,12 @@
|
||||
<img src="https://i.imgur.com/pc8Ingg.png" alt="Reactive Resume" width="256px" height="256px" />
|
||||
<img src="https://github.com/AmruthPillai/Reactive-Resume/blob/main/docs/static/logo.svg" alt="Reactive Resume" width="256px" height="256px" />
|
||||
|
||||
# Reactive Resume
|
||||
|
||||

|
||||

|
||||
[](https://github.com/AmruthPillai/Reactive-Resume/releases)
|
||||
[](https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE)
|
||||
[](https://translate.rxresu.me)
|
||||
[](https://hub.docker.com/r/amruthpillai/reactive-resume)
|
||||

|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume?ref=badge_shield)
|
||||
|
||||
## [Go to App](https://rxresu.me) | [Docs](https://docs.rxresu.me)
|
||||
@ -36,16 +37,25 @@ You have complete control over what goes into your resume, how it looks, what co
|
||||
|
||||
## Languages
|
||||
|
||||
- Arabic (اَلْعَرَبِيَّةُ)
|
||||
- Bengali (বাংলা)
|
||||
- Chinese (中文)
|
||||
- Danish (Dansk)
|
||||
- Dutch (Nederlands)
|
||||
- English
|
||||
- French (Français)
|
||||
- German (Deutsch)
|
||||
- Hindi (हिन्दी)
|
||||
- Italian (Italiano)
|
||||
- Kannada (ಕನ್ನಡ)
|
||||
- Malayalam (മലയാളം)
|
||||
- Polish (Polski)
|
||||
- Portuguese (Português)
|
||||
- Russian (русский)
|
||||
- Spanish (Español)
|
||||
- Tamil (தமிழ்)
|
||||
- Turkish (Türkçe)
|
||||
- Vietnamese (Tiếng Việt)
|
||||
|
||||
Help by [translating Reactive Resume](https://translate.rxresu.me) to your language!
|
||||
|
||||
@ -75,9 +85,9 @@ Use the [GitHub Issues](https://github.com/AmruthPillai/Reactive-Resume/issues/n
|
||||
|
||||
## Donations
|
||||
|
||||
Reactive Resume would be nothing without the folks who supported me and kept the project alive in the beginning, and your cotinued support is what keeps me going. If you found Reactive Resume to be useful, helpful or just insightful and appreciate the effort I took to make the project, please consider donating as little or as much as your can.
|
||||
Reactive Resume would be nothing without the folks who supported me and kept the project alive in the beginning, and your continued support is what keeps me going. If you found Reactive Resume to be useful, helpful or just insightful and appreciate the effort I took to make the project, please consider donating as little or as much as you can.
|
||||
|
||||
### [☕️ Buy me a coffee](https://www.buymeacoffee.com/AmruthPillai) | [💸 PayPal](https://paypal.me/RajaRajanA)
|
||||
### [💸 PayPal](https://paypal.me/RajaRajanA)
|
||||
|
||||
## Infrastructure
|
||||
|
||||
@ -93,6 +103,14 @@ Reactive Resume would be nothing without the folks who supported me and kept the
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/PoweredByDO/DO_Powered_by_Badge_blue.svg" width="200px" />
|
||||
</a>
|
||||
|
||||
## Contributors Wall
|
||||
<a href="https://github.com/AmruthPillai/Reactive-Resume/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=AmruthPillai/Reactive-Resume" />
|
||||
</a>
|
||||
|
||||
|
||||
_Note: It may take up to 24h for the [contrib.rocks](https://contrib.rocks/image?repo=AmruthPillai/Reactive-Resume) plugin to update because it's refreshed once a day._
|
||||
|
||||
## License
|
||||
|
||||
Reactive Resume is packaged and distributed using the [MIT License](https://choosealicense.com/licenses/mit/) which allows for commercial use, distribution, modification and private use provided that all copies of the software contain the same license and copyright.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:16-alpine as dependencies
|
||||
FROM node:17-alpine as dependencies
|
||||
|
||||
RUN apk add --no-cache curl g++ make python3 \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
@ -11,7 +11,7 @@ COPY ./client/package.json ./client/package.json
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
FROM node:16-alpine as builder
|
||||
FROM node:17-alpine as builder
|
||||
|
||||
RUN apk add --no-cache curl g++ make python3 \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
@ -27,7 +27,7 @@ COPY --from=dependencies /app/client/node_modules ./client/node_modules
|
||||
RUN pnpm run build:schema
|
||||
RUN pnpm run build:client
|
||||
|
||||
FROM node:16-alpine as production
|
||||
FROM node:17-alpine as production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -49,4 +49,7 @@ EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=20s --retries=3 --start-period=15s \
|
||||
CMD curl -fSs 127.0.0.1:3000 || exit 1
|
||||
|
||||
CMD [ "pnpm", "run", "start:client" ]
|
||||
@ -34,9 +34,10 @@ const Export = () => {
|
||||
|
||||
const redactedResume = pick(resume, ['basics', 'sections', 'metadata', 'public']);
|
||||
const jsonString = JSON.stringify(redactedResume, null, 4);
|
||||
const jsonBlob = new Blob([jsonString], { type: 'application/json;charset=utf-8' });
|
||||
const filename = `RxResume_JSONExport_${nanoid()}.json`;
|
||||
|
||||
download(jsonString, filename, 'application/json');
|
||||
download(jsonBlob, filename);
|
||||
};
|
||||
|
||||
const handleExportPDF = async () => {
|
||||
|
||||
@ -19,7 +19,7 @@ const Theme = () => {
|
||||
const { background, text, primary } = useAppSelector<ThemeType>((state) => get(state.resume, 'metadata.theme'));
|
||||
|
||||
const handleChange = (property: string, color: string) => {
|
||||
dispatch(setResumeState({ path: `metadata.theme.${property}`, value: color }));
|
||||
dispatch(setResumeState({ path: `metadata.theme.${property}`, value: color[0] !== '#' ? `#${color}` : color }));
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -8,14 +8,14 @@ import styles from './ArrayInput.module.scss';
|
||||
|
||||
type Props = {
|
||||
label: string;
|
||||
value: string[];
|
||||
value?: string[];
|
||||
className?: string;
|
||||
onChange: (event: any) => void;
|
||||
errors?: FieldError | FieldError[];
|
||||
};
|
||||
|
||||
const ArrayInput: React.FC<Props> = ({ value, label, onChange, errors, className }) => {
|
||||
const [items, setItems] = useState<string[]>(value);
|
||||
const [items, setItems] = useState<string[]>(value || []);
|
||||
|
||||
const onAdd = () => setItems([...items, '']);
|
||||
|
||||
|
||||
@ -1,70 +1,51 @@
|
||||
import { Language } from '@mui/icons-material';
|
||||
import { IconButton, Popover } from '@mui/material';
|
||||
import { IconButton, Menu, MenuItem } from '@mui/material';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { MouseEvent, useState } from 'react';
|
||||
|
||||
import { languages } from '@/config/languages';
|
||||
import { useAppDispatch } from '@/store/hooks';
|
||||
import { setResumeState } from '@/store/resume/resumeSlice';
|
||||
|
||||
import styles from './LanguageSwitcher.module.scss';
|
||||
import { TRANSLATE_URL } from '@/constants/index';
|
||||
|
||||
const LanguageSwitcher = () => {
|
||||
const router = useRouter();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
||||
|
||||
const handleClick = (event: MouseEvent<HTMLButtonElement>) => setAnchorEl(event.currentTarget);
|
||||
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
const handleChangeLanguage = (locale: string) => {
|
||||
const handleChange = (locale: string) => {
|
||||
const { pathname, asPath, query } = router;
|
||||
|
||||
handleClose();
|
||||
|
||||
document.cookie = `NEXT_LOCALE=${locale}; path=/; expires=2147483647`;
|
||||
dispatch(setResumeState({ path: 'metadata.locale', value: locale }));
|
||||
|
||||
router.push({ pathname, query }, asPath, { locale });
|
||||
};
|
||||
|
||||
const handleAddLanguage = () => window.open(TRANSLATE_URL, '_blank');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton onClick={handleClick}>
|
||||
<Language />
|
||||
</IconButton>
|
||||
|
||||
<Popover
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
>
|
||||
<div className={styles.popover}>
|
||||
<div className={styles.container}>
|
||||
{languages.map(({ code, name, localName }) => (
|
||||
<p key={code} className={styles.language} onClick={() => handleChangeLanguage(code)}>
|
||||
{name} {localName && `(${localName})`}
|
||||
</p>
|
||||
))}
|
||||
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
|
||||
{languages.map(({ code, name, localName }) => (
|
||||
<MenuItem key={code} onClick={() => handleChange(code)}>
|
||||
{name} {localName && `(${localName})`}
|
||||
</MenuItem>
|
||||
))}
|
||||
|
||||
<a href="https://translate.rxresu.me" target="_blank" rel="noreferrer" className={styles.language}>
|
||||
{t('common.footer.language.missing')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
<MenuItem>
|
||||
<span className="font-bold" onClick={handleAddLanguage}>
|
||||
Add your language
|
||||
</span>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -5,55 +5,25 @@ export type Language = {
|
||||
};
|
||||
|
||||
export const languages: Language[] = [
|
||||
{
|
||||
code: 'bn',
|
||||
name: 'Bengali',
|
||||
localName: 'বাংলা',
|
||||
},
|
||||
{
|
||||
code: 'zh',
|
||||
name: 'Chinese',
|
||||
localName: '中文',
|
||||
},
|
||||
{
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
},
|
||||
{
|
||||
code: 'fr',
|
||||
name: 'French',
|
||||
localName: 'Français',
|
||||
},
|
||||
{
|
||||
code: 'de',
|
||||
name: 'German',
|
||||
localName: 'Deutsch',
|
||||
},
|
||||
{
|
||||
code: 'hi',
|
||||
name: 'Hindi',
|
||||
localName: 'हिन्दी',
|
||||
},
|
||||
{
|
||||
code: 'it',
|
||||
name: 'Italian',
|
||||
localName: 'Italiano',
|
||||
},
|
||||
{
|
||||
code: 'kn',
|
||||
name: 'Kannada',
|
||||
localName: 'ಕನ್ನಡ',
|
||||
},
|
||||
{
|
||||
code: 'es',
|
||||
name: 'Spanish',
|
||||
localName: 'Español',
|
||||
},
|
||||
{
|
||||
code: 'ta',
|
||||
name: 'Tamil',
|
||||
localName: 'தமிழ்',
|
||||
},
|
||||
{ code: 'ar', name: 'Arabic', localName: 'اَلْعَرَبِيَّةُ' },
|
||||
{ code: 'bn', name: 'Bengali', localName: 'বাংলা' },
|
||||
{ code: 'da', name: 'Danish', localName: 'Dansk' },
|
||||
{ code: 'de', name: 'German', localName: 'Deutsch' },
|
||||
{ code: 'en', name: 'English' },
|
||||
{ code: 'es', name: 'Spanish', localName: 'Español' },
|
||||
{ code: 'fr', name: 'French', localName: 'Français' },
|
||||
{ code: 'hi', name: 'Hindi', localName: 'हिन्दी' },
|
||||
{ code: 'it', name: 'Italian', localName: 'Italiano' },
|
||||
{ code: 'kn', name: 'Kannada', localName: 'ಕನ್ನಡ' },
|
||||
{ code: 'ml', name: 'Malayalam', localName: 'മലയാളം' },
|
||||
{ code: 'nl', name: 'Dutch', localName: 'Nederlands' },
|
||||
{ code: 'pl', name: 'Polish', localName: 'Polski' },
|
||||
{ code: 'pt', name: 'Portuguese', localName: 'Português' },
|
||||
{ code: 'ru', name: 'Russian', localName: 'русский' },
|
||||
{ code: 'ta', name: 'Tamil', localName: 'தமிழ்' },
|
||||
{ code: 'tr', name: 'Turkish', localName: 'Türkçe' },
|
||||
{ code: 'vi', name: 'Vietnamese', localName: 'Tiếng Việt' },
|
||||
{ code: 'zh', name: 'Chinese', localName: '中文' },
|
||||
].sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
export const languageMap: Record<string, Language> = languages.reduce(
|
||||
|
||||
3
client/constants/flags.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import env from '@beam-australia/react-env';
|
||||
|
||||
export const FLAG_DISABLE_SIGNUPS = env('FLAG_DISABLE_SIGNUPS') === 'true';
|
||||
@ -9,7 +9,9 @@ export const VALID_URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}
|
||||
export const FILENAME_TIMESTAMP = 'DDMMYYYYHHmmss';
|
||||
|
||||
// Links
|
||||
export const DONATION_URL = 'https://www.buymeacoffee.com/AmruthPillai';
|
||||
export const DONATION_URL = 'https://paypal.me/RajaRajanA';
|
||||
export const TRANSLATE_URL = 'https://translate.rxresu.me/';
|
||||
export const DIGITALOCEAN_URL = 'https://pillai.xyz/digitalocean';
|
||||
export const GITHUB_URL = 'https://github.com/AmruthPillai/Reactive-Resume';
|
||||
export const PRODUCT_HUNT_URL = 'https://www.producthunt.com/posts/reactive-resume-v3';
|
||||
export const GITHUB_ISSUES_URL = 'https://github.com/AmruthPillai/Reactive-Resume/issues/new/choose';
|
||||
|
||||
@ -3,6 +3,7 @@ import { joiResolver } from '@hookform/resolvers/joi';
|
||||
import { Google, Login, Visibility, VisibilityOff } from '@mui/icons-material';
|
||||
import { Button, IconButton, InputAdornment, TextField } from '@mui/material';
|
||||
import Joi from 'joi';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Trans, useTranslation } from 'next-i18next';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { GoogleLoginResponse, GoogleLoginResponseOffline, useGoogleLogin } from 'react-google-login';
|
||||
@ -11,6 +12,7 @@ import toast from 'react-hot-toast';
|
||||
import { useIsMutating, useMutation } from 'react-query';
|
||||
|
||||
import BaseModal from '@/components/shared/BaseModal';
|
||||
import { FLAG_DISABLE_SIGNUPS } from '@/constants/flags';
|
||||
import { login, LoginParams, loginWithGoogle, LoginWithGoogleParams } from '@/services/auth';
|
||||
import { ServerError } from '@/services/axios';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
@ -115,15 +117,17 @@ const LoginModal: React.FC = () => {
|
||||
handleClose={handleClose}
|
||||
footerChildren={
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outlined"
|
||||
disabled={isLoading}
|
||||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.login.actions.google')}
|
||||
</Button>
|
||||
{!isEmpty(env('GOOGLE_CLIENT_ID')) && (
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outlined"
|
||||
disabled={isLoading}
|
||||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.login.actions.google')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
{t('modals.auth.login.actions.login')}
|
||||
@ -164,11 +168,13 @@ const LoginModal: React.FC = () => {
|
||||
/>
|
||||
</form>
|
||||
|
||||
<p className="text-xs">
|
||||
<Trans t={t} i18nKey="modals.auth.login.register-text">
|
||||
If you don't have one, you can <a onClick={handleCreateAccount}>create an account</a> here.
|
||||
</Trans>
|
||||
</p>
|
||||
{!FLAG_DISABLE_SIGNUPS && (
|
||||
<p className="text-xs">
|
||||
<Trans t={t} i18nKey="modals.auth.login.register-text">
|
||||
If you don't have one, you can <a onClick={handleCreateAccount}>create an account</a> here.
|
||||
</Trans>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<p className="text-xs">
|
||||
<Trans t={t} i18nKey="modals.auth.login.recover-text">
|
||||
|
||||
@ -3,6 +3,7 @@ import { joiResolver } from '@hookform/resolvers/joi';
|
||||
import { Google, HowToReg } from '@mui/icons-material';
|
||||
import { Button, TextField } from '@mui/material';
|
||||
import Joi from 'joi';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Trans, useTranslation } from 'next-i18next';
|
||||
import { GoogleLoginResponse, GoogleLoginResponseOffline, useGoogleLogin } from 'react-google-login';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
@ -97,21 +98,23 @@ const RegisterModal: React.FC = () => {
|
||||
heading={t('modals.auth.register.heading')}
|
||||
handleClose={handleClose}
|
||||
footerChildren={
|
||||
<>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outlined"
|
||||
disabled={isLoading}
|
||||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.register.actions.google')}
|
||||
</Button>
|
||||
<div className="flex gap-4">
|
||||
{!isEmpty(env('GOOGLE_CLIENT_ID')) && (
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outlined"
|
||||
disabled={isLoading}
|
||||
startIcon={<Google />}
|
||||
onClick={handleLoginWithGoogle}
|
||||
>
|
||||
{t('modals.auth.register.actions.google')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
|
||||
{t('modals.auth.register.actions.register')}
|
||||
</Button>
|
||||
</>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<p>{t('modals.auth.register.body')}</p>
|
||||
|
||||
@ -115,7 +115,7 @@ const PublicationModal: React.FC = () => {
|
||||
render={({ field, fieldState }) => (
|
||||
<TextField
|
||||
required
|
||||
label="{t('builder.leftSidebar.sections.publications.form.publisher.label')}"
|
||||
label={t('builder.leftSidebar.sections.publications.form.publisher.label')}
|
||||
error={!!fieldState.error}
|
||||
helperText={fieldState.error?.message}
|
||||
{...field}
|
||||
|
||||
@ -159,7 +159,7 @@ const SkillModal: React.FC = () => {
|
||||
render={({ field, fieldState }) => (
|
||||
<ArrayInput
|
||||
label={t('builder.common.form.keywords.label')}
|
||||
value={field.value as string[]}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
errors={fieldState.error}
|
||||
className="col-span-2"
|
||||
|
||||
@ -58,7 +58,7 @@ const CreateResumeModal: React.FC = () => {
|
||||
const slug = name
|
||||
? name
|
||||
.toLowerCase()
|
||||
.replace(/[`~!@#$%^&*()_|+=?;:'",.<>{}[]\\\/]/gi, '')
|
||||
.replace(/[^\w\s]/gi, '')
|
||||
.replace(/[ ]/gi, '-')
|
||||
: '';
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ const RenameResumeModal: React.FC = () => {
|
||||
const slug = name
|
||||
? name
|
||||
.toLowerCase()
|
||||
.replace(/[`~!@#$%^&*()_|+=?;:'",.<>{}[]\\\/]/gi, '')
|
||||
.replace(/[^\w\s]/gi, '')
|
||||
.replace(/[ ]/gi, '-')
|
||||
: '';
|
||||
|
||||
|
||||
@ -3,7 +3,27 @@ const path = require('path');
|
||||
const i18nConfig = {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['bn', 'de', 'en', 'es', 'fr', 'hi', 'it', 'kn', 'ta', 'zh'],
|
||||
locales: [
|
||||
'ar',
|
||||
'bn',
|
||||
'da',
|
||||
'de',
|
||||
'en',
|
||||
'es',
|
||||
'fr',
|
||||
'hi',
|
||||
'it',
|
||||
'kn',
|
||||
'ml',
|
||||
'nl',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'ta',
|
||||
'tr',
|
||||
'vi',
|
||||
'zh',
|
||||
],
|
||||
},
|
||||
nsSeparator: '.',
|
||||
localePath: path.resolve('./public/locales'),
|
||||
|
||||
@ -14,13 +14,13 @@
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@hookform/resolvers": "2.8.8",
|
||||
"@monaco-editor/react": "^4.3.1",
|
||||
"@mui/icons-material": "^5.5.0",
|
||||
"@mui/lab": "^5.0.0-alpha.72",
|
||||
"@mui/material": "^5.5.0",
|
||||
"@mui/icons-material": "^5.5.1",
|
||||
"@mui/lab": "^5.0.0-alpha.74",
|
||||
"@mui/material": "^5.5.2",
|
||||
"@reduxjs/toolkit": "^1.8.0",
|
||||
"axios": "^0.26.1",
|
||||
"clsx": "^1.1.1",
|
||||
"dayjs": "^1.10.8",
|
||||
"dayjs": "^1.11.0",
|
||||
"downloadjs": "^1.4.7",
|
||||
"joi": "^17.6.0",
|
||||
"lodash": "^4.17.21",
|
||||
@ -36,11 +36,11 @@
|
||||
"react-dnd-html5-backend": "^15.1.2",
|
||||
"react-dom": ">=17",
|
||||
"react-google-login": "^5.2.2",
|
||||
"react-hook-form": "^7.28.0",
|
||||
"react-hook-form": "^7.28.1",
|
||||
"react-hot-toast": "2.2.0",
|
||||
"react-hotkeys-hook": "^3.4.4",
|
||||
"react-icons": "^4.3.1",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-markdown": "^8.0.1",
|
||||
"react-query": "^3.34.16",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-zoom-pan-pinch": "^2.1.3",
|
||||
@ -48,29 +48,29 @@
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.1.3",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sharp": "^0.30.2",
|
||||
"sharp": "^0.30.3",
|
||||
"uuid": "^8.3.2",
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.5",
|
||||
"@babel/core": "^7.17.8",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@tailwindcss/typography": "^0.5.2",
|
||||
"@types/downloadjs": "^1.4.3",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/node": "17.0.21",
|
||||
"@types/react": "17.0.40",
|
||||
"@types/lodash": "^4.14.180",
|
||||
"@types/node": "17.0.23",
|
||||
"@types/react": "17.0.42",
|
||||
"@types/react-beautiful-dnd": "^13.1.2",
|
||||
"@types/react-redux": "^7.1.23",
|
||||
"@types/tailwindcss": "^3.0.9",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/webfontloader": "^1.6.34",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-config-next": "12.1.0",
|
||||
"next-sitemap": "^2.5.7",
|
||||
"postcss": "^8.4.8",
|
||||
"prettier": "^2.5.1",
|
||||
"next-sitemap": "^2.5.13",
|
||||
"postcss": "^8.4.12",
|
||||
"prettier": "^2.6.0",
|
||||
"sass": "^1.49.9",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"typescript": "<4.6.0"
|
||||
|
||||
@ -3,6 +3,7 @@ import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { GetServerSideProps, NextPage } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
@ -20,6 +21,7 @@ type QueryParams = {
|
||||
|
||||
type Props = {
|
||||
resume?: Resume;
|
||||
locale: string;
|
||||
redirect?: any;
|
||||
};
|
||||
|
||||
@ -35,7 +37,13 @@ export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, Quer
|
||||
const resume = await fetchResumeByIdentifier({ username, slug, options: { secretKey } });
|
||||
const displayLocale = resume.metadata.locale || locale || 'en';
|
||||
|
||||
return { props: { resume, ...(await serverSideTranslations(displayLocale, ['common'])) } };
|
||||
return {
|
||||
props: {
|
||||
resume,
|
||||
locale: displayLocale,
|
||||
...(await serverSideTranslations(displayLocale, ['common'])),
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
redirect: {
|
||||
@ -46,7 +54,9 @@ export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, Quer
|
||||
}
|
||||
};
|
||||
|
||||
const Printer: NextPage<Props> = ({ resume: initialData }) => {
|
||||
const Printer: NextPage<Props> = ({ resume: initialData, locale }) => {
|
||||
const router = useRouter();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const resume = useAppSelector((state) => state.resume);
|
||||
@ -55,6 +65,12 @@ const Printer: NextPage<Props> = ({ resume: initialData }) => {
|
||||
if (initialData) dispatch(setResume(initialData));
|
||||
}, [dispatch, initialData]);
|
||||
|
||||
useEffect(() => {
|
||||
const { pathname, asPath, query } = router;
|
||||
|
||||
router.push({ pathname, query }, asPath, { locale });
|
||||
}, [router, locale]);
|
||||
|
||||
if (!resume || isEmpty(resume)) return null;
|
||||
|
||||
const layout: string[][][] = get(resume, 'metadata.layout', []);
|
||||
|
||||
@ -4,6 +4,7 @@ import NextDocument, { DocumentContext, Head, Html, Main, NextScript } from 'nex
|
||||
const Document: NextPage = () => (
|
||||
<Html>
|
||||
<Head />
|
||||
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Link as LinkIcon } from '@mui/icons-material';
|
||||
import { DarkMode, LightMode, Link as LinkIcon } from '@mui/icons-material';
|
||||
import { Masonry } from '@mui/lab';
|
||||
import { Button } from '@mui/material';
|
||||
import { Button, IconButton } from '@mui/material';
|
||||
import type { GetStaticProps, NextPage } from 'next';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
@ -13,13 +13,15 @@ import LanguageSwitcher from '@/components/shared/LanguageSwitcher';
|
||||
import Logo from '@/components/shared/Logo';
|
||||
import NoSSR from '@/components/shared/NoSSR';
|
||||
import { screenshots } from '@/config/screenshots';
|
||||
import { FLAG_DISABLE_SIGNUPS } from '@/constants/flags';
|
||||
import testimonials from '@/data/testimonials';
|
||||
import { logout } from '@/store/auth/authSlice';
|
||||
import { setTheme } from '@/store/build/buildSlice';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||
import { setModalState } from '@/store/modal/modalSlice';
|
||||
import styles from '@/styles/pages/Home.module.scss';
|
||||
|
||||
import { DONATION_URL, GITHUB_URL } from '../constants';
|
||||
import { DIGITALOCEAN_URL, DONATION_URL, GITHUB_URL } from '../constants';
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => {
|
||||
return {
|
||||
@ -34,12 +36,15 @@ const Home: NextPage = () => {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const theme = useAppSelector((state) => state.build.theme);
|
||||
const isLoggedIn = useAppSelector((state) => state.auth.isLoggedIn);
|
||||
|
||||
const handleLogin = () => dispatch(setModalState({ modal: 'auth.login', state: { open: true } }));
|
||||
|
||||
const handleRegister = () => dispatch(setModalState({ modal: 'auth.register', state: { open: true } }));
|
||||
|
||||
const handleToggle = () => dispatch(setTheme({ theme: theme === 'light' ? 'dark' : 'light' }));
|
||||
|
||||
const handleLogout = () => dispatch(logout());
|
||||
|
||||
return (
|
||||
@ -70,7 +75,7 @@ const Home: NextPage = () => {
|
||||
<>
|
||||
<Button onClick={handleLogin}>{t('landing.actions.login')}</Button>
|
||||
|
||||
<Button variant="outlined" onClick={handleRegister}>
|
||||
<Button variant="outlined" onClick={handleRegister} disabled={FLAG_DISABLE_SIGNUPS}>
|
||||
{t('landing.actions.register')}
|
||||
</Button>
|
||||
</>
|
||||
@ -175,7 +180,7 @@ const Home: NextPage = () => {
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
<a href="https://pillai.xyz/digitalocean" target="_blank" rel="noreferrer">
|
||||
<a href={DIGITALOCEAN_URL} target="_blank" rel="noreferrer">
|
||||
<Image src="/images/sponsors/digitalocean.svg" alt="Powered By DigitalOcean" width={200} height={40} />
|
||||
</a>
|
||||
</section>
|
||||
@ -187,7 +192,11 @@ const Home: NextPage = () => {
|
||||
<div>v{process.env.appVersion}</div>
|
||||
</div>
|
||||
|
||||
<LanguageSwitcher />
|
||||
<div className={styles.actions}>
|
||||
<IconButton onClick={handleToggle}>{theme === 'dark' ? <DarkMode /> : <LightMode />}</IconButton>
|
||||
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
</footer>
|
||||
</main>
|
||||
);
|
||||
|
||||
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 265 KiB After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 319 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 329 KiB After Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 323 KiB After Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 267 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 103 KiB |
358
client/public/locales/ar/builder.json
Normal file
@ -0,0 +1,358 @@
|
||||
{
|
||||
"common": {
|
||||
"actions": {
|
||||
"add": "إضافة {{فقرة}} جديدة",
|
||||
"delete": "حذة {{الفقرة}}",
|
||||
"edit": "تحرير {{الفقرة}}"
|
||||
},
|
||||
"columns": {
|
||||
"heading": "الأعمدة",
|
||||
"tooltip": "تغيير عدد الأعمدة"
|
||||
},
|
||||
"form": {
|
||||
"date": {
|
||||
"label": "التاريخ"
|
||||
},
|
||||
"description": {
|
||||
"label": "التفاصيل"
|
||||
},
|
||||
"email": {
|
||||
"label": "البريد الإلكتروني"
|
||||
},
|
||||
"end-date": {
|
||||
"help-text": "اترك هذا الحقل فارغًا ، إذا كان لا يزال موجودًا",
|
||||
"label": "تاريخ الانتهاء"
|
||||
},
|
||||
"keywords": {
|
||||
"label": "الكلمات الرئيسية"
|
||||
},
|
||||
"level": {
|
||||
"label": "مستوى"
|
||||
},
|
||||
"levelNum": {
|
||||
"label": "المستوى (Number)"
|
||||
},
|
||||
"name": {
|
||||
"label": "الاسم"
|
||||
},
|
||||
"phone": {
|
||||
"label": "رقم الهاتف"
|
||||
},
|
||||
"position": {
|
||||
"label": "المنصب"
|
||||
},
|
||||
"start-date": {
|
||||
"label": "تاريخ البداية"
|
||||
},
|
||||
"subtitle": {
|
||||
"label": "العنوان الفرعي"
|
||||
},
|
||||
"summary": {
|
||||
"label": "الملخص"
|
||||
},
|
||||
"title": {
|
||||
"label": "العنوان"
|
||||
},
|
||||
"url": {
|
||||
"label": "موقع الويب"
|
||||
}
|
||||
},
|
||||
"glossary": {
|
||||
"page": "الصفحة"
|
||||
},
|
||||
"list": {
|
||||
"actions": {
|
||||
"delete": "حذف",
|
||||
"duplicate": "نسخه مطابقه",
|
||||
"edit": "تعديل"
|
||||
},
|
||||
"empty-text": "هذه القائمة فارغة."
|
||||
},
|
||||
"tooltip": {
|
||||
"delete-item": "هل أنت متأكد أنك تريد حذف هذا العنصر؟ لا يمكن التراجع عن هذا الإجراء.",
|
||||
"delete-section": "حذف القسم",
|
||||
"rename-section": "إعادة تسمية القسم",
|
||||
"toggle-visibility": "تبديل الرؤية"
|
||||
}
|
||||
},
|
||||
"controller": {
|
||||
"tooltip": {
|
||||
"center-artboard": "لوحة الوسط",
|
||||
"copy-link": "انسخ الرابط للسيرة الذاتية",
|
||||
"export-pdf": "تصدير PDF",
|
||||
"toggle-orientation": "تبديل اتجاه الصفحة",
|
||||
"toggle-page-break-line": "تبديل سطر الصفحة",
|
||||
"toggle-sidebars": "تبديل الشريط الجانبي",
|
||||
"zoom-in": "تكبير",
|
||||
"zoom-out": "تصغير"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"menu": {
|
||||
"delete": "حذف",
|
||||
"duplicate": "تكرار",
|
||||
"rename": "إعادة تسمية",
|
||||
"share-link": "مشاركة الرّابط",
|
||||
"tooltips": {
|
||||
"delete": "هل أنت متأكد أنك تريد حذف هذا العنصر؟ لا يمكن التراجع عن هذا الإجراء.",
|
||||
"share-link": "أنت بحاجة إلى تغيير رؤية سيرتك الذاتية للعامة لجعلها مرئية للآخرين."
|
||||
}
|
||||
}
|
||||
},
|
||||
"leftSidebar": {
|
||||
"sections": {
|
||||
"awards": {
|
||||
"form": {
|
||||
"awarder": {
|
||||
"label": "جائزة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"basics": {
|
||||
"actions": {
|
||||
"photo-filters": "فلاتر الصور"
|
||||
},
|
||||
"heading": "الأساسيات",
|
||||
"headline": {
|
||||
"label": "العنوان الرئيسي"
|
||||
},
|
||||
"name": {
|
||||
"label": "الاسم الكامل"
|
||||
},
|
||||
"photo-filters": {
|
||||
"effects": {
|
||||
"border": {
|
||||
"label": "الحدود"
|
||||
},
|
||||
"grayscale": {
|
||||
"label": "رمادي"
|
||||
},
|
||||
"heading": "مؤثرات"
|
||||
},
|
||||
"shape": {
|
||||
"heading": "الشكل"
|
||||
},
|
||||
"size": {
|
||||
"heading": "الحجم (بالبكسل)"
|
||||
}
|
||||
},
|
||||
"photo-upload": {
|
||||
"tooltip": {
|
||||
"remove": "إزالة صورة",
|
||||
"upload": "رفع صورة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"certifications": {
|
||||
"form": {
|
||||
"issuer": {
|
||||
"label": "جهة الإصدار"
|
||||
}
|
||||
}
|
||||
},
|
||||
"education": {
|
||||
"form": {
|
||||
"area-study": {
|
||||
"label": "مجال الدراسة"
|
||||
},
|
||||
"courses": {
|
||||
"label": "دورات"
|
||||
},
|
||||
"degree": {
|
||||
"label": "الدرجة العلمية"
|
||||
},
|
||||
"grade": {
|
||||
"label": "الدرجة / التقييم"
|
||||
},
|
||||
"institution": {
|
||||
"label": "المؤسسة/الجامعة/المعهد"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"address": {
|
||||
"label": "العنوان"
|
||||
},
|
||||
"city": {
|
||||
"label": "المدينة"
|
||||
},
|
||||
"country": {
|
||||
"label": "البلد/الدولة"
|
||||
},
|
||||
"heading": "المكان",
|
||||
"postal-code": {
|
||||
"label": "الرمز البريدي"
|
||||
},
|
||||
"region": {
|
||||
"label": "المنطقة"
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"form": {
|
||||
"network": {
|
||||
"label": "الشبكة"
|
||||
},
|
||||
"username": {
|
||||
"label": "اسم المستخدم"
|
||||
}
|
||||
},
|
||||
"heading": "الملفات الشخصية",
|
||||
"heading_one": "الملف الشخصي"
|
||||
},
|
||||
"publications": {
|
||||
"form": {
|
||||
"publisher": {
|
||||
"label": "الناشر"
|
||||
}
|
||||
}
|
||||
},
|
||||
"references": {
|
||||
"form": {
|
||||
"relationship": {
|
||||
"label": "العلاقة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"section": {
|
||||
"heading": "القسم"
|
||||
},
|
||||
"volunteer": {
|
||||
"form": {
|
||||
"organization": {
|
||||
"label": "المنظمة/المؤسسة"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rightSidebar": {
|
||||
"sections": {
|
||||
"css": {
|
||||
"heading": "تنسيقات CSS مخصصة"
|
||||
},
|
||||
"export": {
|
||||
"heading": "تصدير",
|
||||
"json": {
|
||||
"primary": "JSON",
|
||||
"secondary": "قم بتنزيل نسخة بصيغة JSON من سيرتك الذاتية والتي يمكن استيرادها مرة أخرى إلى Reactive Resume."
|
||||
},
|
||||
"pdf": {
|
||||
"loading": {
|
||||
"primary": "توليد ملف PDF",
|
||||
"secondary": "يرجى الانتظار حتى يتم إنشاء ملف PDF الخاص بك ، فقد يستغرق هذا ما يصل إلى 15 ثانية."
|
||||
},
|
||||
"normal": {
|
||||
"primary": "ملف - PDF",
|
||||
"secondary": "قم بتنزيل ملف PDF لسيرتك الذاتية بحيث يمكنك طباعته وإرساله إلى وظيفة أحلامك. لا يمكن استيراد هذا الملف مرة أخرى لمزيد من التحرير."
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"heading": "تخطيط",
|
||||
"tooltip": {
|
||||
"reset-layout": "إعادة تعيين التخطيط"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"bugs-features": {
|
||||
"body": "شيء يمنعك من عمل سيرة ذاتية؟ أو هل لديك فكرة رائعة لتضيفها؟ إطرح المشكلة على GitHub للبدء.",
|
||||
"button": "صفحة المشاكل على \"GitHub\"",
|
||||
"heading": "خلل برمجي؟ طلب وظائف ومميزات مخصصة؟"
|
||||
},
|
||||
"donate": {
|
||||
"body": "إذا أعجبك استخدام Resctive Resume ، فالرجاء التفكير في التبرع بأكبر قدر ممكن من أجل الحفاظ على استمرار التطبيق وتشغيله ، بدون إعلانات وبشكل مجاني إلى الأبد.",
|
||||
"button": "إشتر لي قهوة",
|
||||
"heading": "تبرع الى Reactive Resume"
|
||||
},
|
||||
"github": "الشفرة المصدرية",
|
||||
"heading": "الروابط"
|
||||
},
|
||||
"settings": {
|
||||
"global": {
|
||||
"date": {
|
||||
"primary": "التاريخ",
|
||||
"secondary": "صيغة التاريخ لاستخدامه عبر التطبيق"
|
||||
},
|
||||
"heading": "عام",
|
||||
"language": {
|
||||
"primary": "اللغة",
|
||||
"secondary": "اعرض اللغة لاستخدامها عبر التطبيق"
|
||||
},
|
||||
"theme": {
|
||||
"primary": "التصميم"
|
||||
}
|
||||
},
|
||||
"heading": "الإعدادات",
|
||||
"page": {
|
||||
"break-line": {
|
||||
"primary": "خط فاصل",
|
||||
"secondary": "اعرض خط في كل الصفحات لتحديد ارتفاع صفحة A4"
|
||||
},
|
||||
"heading": "صفحة",
|
||||
"orientation": {
|
||||
"disabled": "ليس له تأثير عندما تكون هناك صفحة واحدة فقط",
|
||||
"primary": "الإتجاة",
|
||||
"secondary": "ما إذا كان سيتم عرض الصفحات أفقيًا أو رأسيًا"
|
||||
}
|
||||
},
|
||||
"resume": {
|
||||
"heading": "سيرة ذاتية",
|
||||
"reset": {
|
||||
"primary": "إعادة تعيين كل شيء",
|
||||
"secondary": "أرتكبت الكثير من الأخطاء؟ انقر هنا لإعادة تعيين جميع التغييرات والبدء من نقطة الصفر. كن حذرا ، هذا الإجراء لا يمكن عكسه."
|
||||
},
|
||||
"sample": {
|
||||
"primary": "تحميل نموذج البيانات",
|
||||
"secondary": "لست متأكدا من أين تبدأ؟ انقر هنا لتحميل بعض عينات البيانات لترى كيف تبدو سيرة ذاتية كاملة."
|
||||
}
|
||||
}
|
||||
},
|
||||
"sharing": {
|
||||
"heading": "جاري المشاركة",
|
||||
"short-url": {
|
||||
"label": "تفضل عنوان URL قصير"
|
||||
},
|
||||
"visibility": {
|
||||
"subtitle": "اسمح لأي شخص لديه الرابط لعرض سيرتك الذاتية",
|
||||
"title": "عام"
|
||||
}
|
||||
},
|
||||
"templates": {
|
||||
"heading": "قوالب"
|
||||
},
|
||||
"theme": {
|
||||
"form": {
|
||||
"background": {
|
||||
"label": "الخلفية"
|
||||
},
|
||||
"primary": {
|
||||
"label": "اساسي"
|
||||
},
|
||||
"text": {
|
||||
"label": "نص"
|
||||
}
|
||||
},
|
||||
"heading": "السمة"
|
||||
},
|
||||
"typography": {
|
||||
"form": {
|
||||
"font-family": {
|
||||
"label": "اسم الخط"
|
||||
},
|
||||
"font-size": {
|
||||
"label": "حجم الخط"
|
||||
}
|
||||
},
|
||||
"heading": "الطباعة والخطوط",
|
||||
"widgets": {
|
||||
"body": {
|
||||
"label": "المتن"
|
||||
},
|
||||
"headings": {
|
||||
"label": "العناوين"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
client/public/locales/ar/common.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"avatar": {
|
||||
"menu": {
|
||||
"greeting": "مرحبا",
|
||||
"logout": "تسجيل خروج"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"credit": "مشروع عاطفي من تأليف <1> أمروث بيلاي</1>",
|
||||
"license": "من قبل المجتمع للمجتمع."
|
||||
},
|
||||
"markdown": {
|
||||
"help-text": "يدعم هذا القسم تنسيق <1> تخفيض السعر </1>."
|
||||
},
|
||||
"date": {
|
||||
"present": "الحاضر"
|
||||
},
|
||||
"subtitle": "سيرة ذاتية مجانية ومفتوحة المصدر.",
|
||||
"title": "سيرة ذاتية تفاعلية",
|
||||
"toast": {
|
||||
"error": {
|
||||
"upload-file-size": "الرجاء تحميل الملفات تحت 2 ميغابايت فقط.",
|
||||
"upload-photo-size": "الرجاء تحميل الصور التي تقل حجمها عن 2 ميغا ويفضل أن تكون مربعة."
|
||||
},
|
||||
"success": {
|
||||
"resume-link-copied": "تم نسخ رابط السيرة الذاتية الخاصة بك إلى الحافظة."
|
||||
}
|
||||
}
|
||||
}
|
||||
25
client/public/locales/ar/dashboard.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"create-resume": {
|
||||
"subtitle": "البدء من الصفر",
|
||||
"title": "إنشاء سيرة ذاتية جديدة"
|
||||
},
|
||||
"import-external": {
|
||||
"subtitle": "LinkedIn ، سيرة ذاتية من ملف JSON ،سيرة ذاتية من Reactive Resume",
|
||||
"title": "استيراد من مصادر خارجية"
|
||||
},
|
||||
"resume": {
|
||||
"menu": {
|
||||
"delete": "حذف",
|
||||
"duplicate": "إنشاء نسخة مطابقة",
|
||||
"open": "فتح",
|
||||
"rename": "إعادة تسمية",
|
||||
"share-link": "مشاركة الرّابط",
|
||||
"tooltips": {
|
||||
"delete": "هل أنت متأكد أنك تريد حذف ملف السيرة الذاتية هذا؟ لا يمكن التراجع عن هذا الإجراء.",
|
||||
"share-link": "أنت بحاجة إلى تغيير خصوصية سيرتك الذاتية إلى عامة لجعلها مرئية للآخرين."
|
||||
}
|
||||
},
|
||||
"timestamp": "آخر تحديث تم في {{timestamp}}"
|
||||
},
|
||||
"title": "لوحة التحكم"
|
||||
}
|
||||
41
client/public/locales/ar/landing.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"actions": {
|
||||
"app": "انتقل إلى التطبيق",
|
||||
"login": "تسجيل الدخول",
|
||||
"logout": "تسجيل الخروج",
|
||||
"register": "التسجيل"
|
||||
},
|
||||
"features": {
|
||||
"heading": "الخصائص",
|
||||
"list": {
|
||||
"ads": "بدون اعلانات",
|
||||
"export": "قم بتصدير سيرتك الذاتية إلى تنسيق JSON أو PDF",
|
||||
"free": "مجاني، إلى الأبد",
|
||||
"import": "استيراد البيانات من LinkedIn أو ملف JSON",
|
||||
"languages": "متعدد اللغات",
|
||||
"more": "ومميزات مثيرة أكثر، <1>للمزيد إقرأ هنا</1>",
|
||||
"tracking": "لا يوجد تتبع للمستخدم"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"heading": "الروابط",
|
||||
"links": {
|
||||
"donate": "تبرّع",
|
||||
"github": "الشفرة المصدرية",
|
||||
"privacy": "سياسة الخصوصية",
|
||||
"service": "شروط الإستخدام"
|
||||
}
|
||||
},
|
||||
"screenshots": {
|
||||
"heading": "لقطات الشاشة"
|
||||
},
|
||||
"testimonials": {
|
||||
"heading": "الآراء والتقييمات",
|
||||
"body": "سواء أكان ذلك جيدًا أم سيئًا ، أود أن أسمع رأيك في \"السيرة الذاتية التفاعلية\" وكيف كانت التجربة بالنسبة لك.<br/>فيما يلي بعض الرسائل المرسلة بواسطة مستخدمين من جميع أنحاء العالم.",
|
||||
"contact": "يمكنك التواصل معي من خلال <1> بريدي الإلكتروني</1> أو من خلال نموذج الاتصال الموجود على <3> موقع الويب الخاص بي</3>."
|
||||
},
|
||||
"summary": {
|
||||
"body": "Reactive Resume هو منشئ سيرة ذاتية مجاني ومفتوح المصدر تم إنشاؤه لجعل المهام الروتينية لإنشاء وتحديث ومشاركة سيرتك الذاتية سهلة مثل 1 و 2 و 3. باستخدام هذا التطبيق ، يمكنك إنشاء سيرة ذاتية متعددة ومشاركتها مع جهات التوظيف أو الأصدقاء من خلال رابط فريد وطباعته كملف PDF ، كل ذلك مجانًا ، بدون إعلانات ، بدون تتبع ، دون فقدان سلامة وخصوصية بياناتك.",
|
||||
"heading": "الملخص"
|
||||
}
|
||||
}
|
||||
136
client/public/locales/ar/modals.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"auth": {
|
||||
"forgot-password": {
|
||||
"actions": {
|
||||
"send-email": "إرسال بريد لإعادة تعيين كلمة المرور"
|
||||
},
|
||||
"body": "يرجى أدخال عنوان البريد الإلكتروني المرتبط بالحساب الذي ترغب في استعادته.",
|
||||
"form": {
|
||||
"email": {
|
||||
"label": "البريد الإلكتروني"
|
||||
}
|
||||
},
|
||||
"heading": "نسيت كلمة المرور؟",
|
||||
"help-text": "إذا كان حسابك موجود، سوف يصلك بريد يحتوي على رابط إستعادة كلمة المرور."
|
||||
},
|
||||
"login": {
|
||||
"actions": {
|
||||
"login": "تسجيل الدخول",
|
||||
"google": "تسجيل الدخول باستخدام حساب جوجل"
|
||||
},
|
||||
"body": "يرجى إدخال اسم المستخدم وكلمة المرور المرتبطين بحسابك لتسجيل الدخول والوصول إلى السير الذاتية وإدارتها ومشاركتها.",
|
||||
"form": {
|
||||
"password": {
|
||||
"label": "كلمة المرور"
|
||||
},
|
||||
"username": {
|
||||
"help-text": "يمكنك أيضا إدخال عنوان بريدك الألكتروني",
|
||||
"label": "اسم المستخدم"
|
||||
}
|
||||
},
|
||||
"heading": "تسجيل الدخول إلى حسابك",
|
||||
"recover-text": "في حالة نسيت كلمة المرور الخاصة بك ، يمكنك <1> استعادة حسابك</1> من هنا.",
|
||||
"register-text": "إذا لم يكن لديك حساب ، يمكنك <1> إنشاء حساب</1> من هنا."
|
||||
},
|
||||
"register": {
|
||||
"actions": {
|
||||
"register": "التسجيل",
|
||||
"google": "التسجيل بإستخدام حساب جوجل"
|
||||
},
|
||||
"body": "الرجاء إدخال معلوماتك الشخصية لإنشاء حساب.",
|
||||
"form": {
|
||||
"confirm-password": {
|
||||
"label": "تأكيد كلمة المرور"
|
||||
},
|
||||
"email": {
|
||||
"label": "عنوان البريد الالكترونى"
|
||||
},
|
||||
"name": {
|
||||
"label": "الاسم الكامل"
|
||||
},
|
||||
"password": {
|
||||
"label": "كلمة المرور"
|
||||
},
|
||||
"username": {
|
||||
"label": "اسم المستخدم"
|
||||
}
|
||||
},
|
||||
"heading": "انشئ حساب",
|
||||
"loginText": "إذا كان لديك حساب بالفعل ، يمكنك <1> تسجيل الدخول من هنا</1>."
|
||||
},
|
||||
"reset-password": {
|
||||
"actions": {
|
||||
"set-password": "تعيين كلمة سر جديدة"
|
||||
},
|
||||
"body": "أدخل كلمة مرور جديدة لحسابك.",
|
||||
"form": {
|
||||
"confirm-password": {
|
||||
"label": "تأكيد كلمة المرور"
|
||||
},
|
||||
"password": {
|
||||
"label": "كلمة المرور"
|
||||
}
|
||||
},
|
||||
"heading": "إعادة تعيين كلمة المرور الخاصة بك"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"create-resume": {
|
||||
"actions": {
|
||||
"create-resume": "إنشاء سيرة ذاتية"
|
||||
},
|
||||
"body": "ابدأ في بناء سيرتك الذاتية بإعطائها اسمًا. يمكن أن يكون إشارة إلى الوظيفة الذي تتقدم إليها ، أو اسم وجبتك الخفيفة المفضلة.",
|
||||
"form": {
|
||||
"name": {
|
||||
"label": "الاسم"
|
||||
},
|
||||
"public": {
|
||||
"label": "هل يمكن لأي احد الوصول إليها؟"
|
||||
},
|
||||
"slug": {
|
||||
"label": "الاسم اللطيف"
|
||||
}
|
||||
},
|
||||
"heading": "أنشئ سيرة ذاتية جديدة"
|
||||
},
|
||||
"import-external": {
|
||||
"heading": "استيراد من مصادر خارجية",
|
||||
"json-resume": {
|
||||
"actions": {
|
||||
"upload-json": "تحميل JSON"
|
||||
},
|
||||
"body": "إذا كان لديك ملف سيرة ذاتية بصيغة JSON تم التحقق من صحته <1></1> جاهز للعمل ، يمكنك استخدامه لتسريع عملية الإنشاء على Resctive Resume. انقر فوق الزر أدناه وقم بتحميل ملف JSON صالح للبدء.",
|
||||
"heading": "استيراد من ملف JSON"
|
||||
},
|
||||
"linkedin": {
|
||||
"actions": {
|
||||
"upload-archive": "تحميل ملف zip مضغوط"
|
||||
},
|
||||
"body": "يمكنك توفير الوقت عن طريق تصدير بياناتك من LinkedIn واستخدامها لملء الحقول تلقائيًا في Reactive Resume. توجه إلى <1> خصوصية البيانات</1> على LinkedIn واطلب تحميل بياناتك بشكل مضغوط ZIP. بمجرد توفره ، قم برفع ملف ZIP أدناه.",
|
||||
"heading": "استيراد من LinkedIn"
|
||||
},
|
||||
"reactive-resume": {
|
||||
"actions": {
|
||||
"upload-json": "رفع JSON",
|
||||
"upload-json-v2": "رفع JSON من v2"
|
||||
},
|
||||
"body": "إذا كان لديك JSON تم تصديره بالإصدار الحالي من Reactive Resume ، فيمكنك استيراده مرة أخرى هنا للحصول على نسخة قابلة للتحرير مرة أخرى.",
|
||||
"heading": "استيراد من Reactive Resume"
|
||||
}
|
||||
},
|
||||
"rename-resume": {
|
||||
"actions": {
|
||||
"rename-resume": "إعادة تسمية السيرة الذاتية"
|
||||
},
|
||||
"form": {
|
||||
"name": {
|
||||
"label": "الاسم"
|
||||
},
|
||||
"slug": {
|
||||
"label": "الاسم اللطيف"
|
||||
}
|
||||
},
|
||||
"heading": "أعد تسمية سيرتك الذاتية"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,6 @@
|
||||
},
|
||||
"footer": {
|
||||
"credit": "<1>অমরুথ পিল্লাই</1>-এর একটি প্যাশন প্রোজেক্ট",
|
||||
"language": {
|
||||
"missing": "আপনার ভাষা অনুপস্থিত?"
|
||||
},
|
||||
"license": "সম্প্রদায়ের দ্বারা, সম্প্রদায়ের জন্য।"
|
||||
},
|
||||
"markdown": {
|
||||
|
||||
@ -111,9 +111,10 @@
|
||||
},
|
||||
"reactive-resume": {
|
||||
"actions": {
|
||||
"upload-json": "JSON আপলোড করুন"
|
||||
"upload-json": "JSON আপলোড করুন",
|
||||
"upload-json-v2": "v2 থেকে JSON আপলোড করুন"
|
||||
},
|
||||
"body": "আপনার যদি একটি JSON থাকে যা রিঅ্যাকটিভ রিজিউমের বর্তমান সংস্করণের সাথে রপ্তানি করা হয়েছিল, আপনি আবার সম্পাদনাযোগ্য সংস্করণ পেতে এটিকে এখানে আবার আমদানি করতে পারেন। প্রতিক্রিয়াশীল জীবনবৃত্তান্তের পূর্ববর্তী সংস্করণগুলি দুর্ভাগ্যবশত এই মুহূর্তে সমর্থিত নয়৷",
|
||||
"body": "আপনার যদি একটি JSON থাকে যা রিঅ্যাকটিভ রিজিউমের বর্তমান সংস্করণের সাথে রপ্তানি করা হয়েছিল, আপনি আবার সম্পাদনাযোগ্য সংস্করণ পেতে এটিকে এখানে আবার আমদানি করতে পারেন।",
|
||||
"heading": "প্রতিক্রিয়াশীল জীবনবৃত্তান্ত থেকে আমদানি করুন"
|
||||
}
|
||||
},
|
||||
|
||||
358
client/public/locales/cs/builder.json
Normal file
@ -0,0 +1,358 @@
|
||||
{
|
||||
"common": {
|
||||
"actions": {
|
||||
"add": "Přidat nový {{token}}",
|
||||
"delete": "Odstranit {{token}}",
|
||||
"edit": "Upravit {{token}}"
|
||||
},
|
||||
"columns": {
|
||||
"heading": "Sloupce",
|
||||
"tooltip": "Změnit počet sloupců"
|
||||
},
|
||||
"form": {
|
||||
"date": {
|
||||
"label": "Datum"
|
||||
},
|
||||
"description": {
|
||||
"label": "Popis"
|
||||
},
|
||||
"email": {
|
||||
"label": "E-mailová adresa"
|
||||
},
|
||||
"end-date": {
|
||||
"help-text": "Nechte toto pole prázdné, pokud stále trvá",
|
||||
"label": "Datum ukončení"
|
||||
},
|
||||
"keywords": {
|
||||
"label": "Klíčová slova"
|
||||
},
|
||||
"level": {
|
||||
"label": "Úroveň"
|
||||
},
|
||||
"levelNum": {
|
||||
"label": "Úroveň (číslo)"
|
||||
},
|
||||
"name": {
|
||||
"label": "Jméno"
|
||||
},
|
||||
"phone": {
|
||||
"label": "Telefonní číslo"
|
||||
},
|
||||
"position": {
|
||||
"label": "Pozice"
|
||||
},
|
||||
"start-date": {
|
||||
"label": "Počáteční datum"
|
||||
},
|
||||
"subtitle": {
|
||||
"label": "Podtitul"
|
||||
},
|
||||
"summary": {
|
||||
"label": "Shrnutí"
|
||||
},
|
||||
"title": {
|
||||
"label": "Název"
|
||||
},
|
||||
"url": {
|
||||
"label": "Webová stránka"
|
||||
}
|
||||
},
|
||||
"glossary": {
|
||||
"page": "Stránka"
|
||||
},
|
||||
"list": {
|
||||
"actions": {
|
||||
"delete": "Odstranit",
|
||||
"duplicate": "Duplikovat",
|
||||
"edit": "Upravit"
|
||||
},
|
||||
"empty-text": "Tento seznam je prázdný."
|
||||
},
|
||||
"tooltip": {
|
||||
"delete-item": "Opravdu chcete odstranit tuto položku? Tato akce je nevratná.",
|
||||
"delete-section": "Odstranit sekci",
|
||||
"rename-section": "Přejmenovat sekci",
|
||||
"toggle-visibility": "Přepnout viditelnost"
|
||||
}
|
||||
},
|
||||
"controller": {
|
||||
"tooltip": {
|
||||
"center-artboard": "Vycentrovat Artboard",
|
||||
"copy-link": "Kopírovat odkaz na životopis",
|
||||
"export-pdf": "Exportovat PDF",
|
||||
"toggle-orientation": "Přepnout orientaci stránky",
|
||||
"toggle-page-break-line": "Přepnout řádek zalomení stránky",
|
||||
"toggle-sidebars": "Přepnout boční panely",
|
||||
"zoom-in": "Přiblížit",
|
||||
"zoom-out": "Oddálit"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"menu": {
|
||||
"delete": "Odstranit",
|
||||
"duplicate": "Duplikovat",
|
||||
"rename": "Přejmenovat",
|
||||
"share-link": "Sdílet odkaz",
|
||||
"tooltips": {
|
||||
"delete": "Opravdu chcete smazat tento životopis? Tato akce je nevratná.",
|
||||
"share-link": "Musíte změnit viditelnost svého životopisu na veřejnou, aby byl viditelný pro ostatní."
|
||||
}
|
||||
}
|
||||
},
|
||||
"leftSidebar": {
|
||||
"sections": {
|
||||
"awards": {
|
||||
"form": {
|
||||
"awarder": {
|
||||
"label": "Udělovatel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"basics": {
|
||||
"actions": {
|
||||
"photo-filters": "Foto filtry"
|
||||
},
|
||||
"heading": "Základy",
|
||||
"headline": {
|
||||
"label": "Titulek"
|
||||
},
|
||||
"name": {
|
||||
"label": "Celé jméno"
|
||||
},
|
||||
"photo-filters": {
|
||||
"effects": {
|
||||
"border": {
|
||||
"label": "Rám"
|
||||
},
|
||||
"grayscale": {
|
||||
"label": "Odstíny šedi"
|
||||
},
|
||||
"heading": "Efekty"
|
||||
},
|
||||
"shape": {
|
||||
"heading": "Tvar"
|
||||
},
|
||||
"size": {
|
||||
"heading": "Velikost (v px)"
|
||||
}
|
||||
},
|
||||
"photo-upload": {
|
||||
"tooltip": {
|
||||
"remove": "Odstranit fotku",
|
||||
"upload": "Nahrát fotografii"
|
||||
}
|
||||
}
|
||||
},
|
||||
"certifications": {
|
||||
"form": {
|
||||
"issuer": {
|
||||
"label": "Vydavatel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"education": {
|
||||
"form": {
|
||||
"area-study": {
|
||||
"label": "Studijní oblast"
|
||||
},
|
||||
"courses": {
|
||||
"label": "Kurzy"
|
||||
},
|
||||
"degree": {
|
||||
"label": "Titul"
|
||||
},
|
||||
"grade": {
|
||||
"label": "Známka"
|
||||
},
|
||||
"institution": {
|
||||
"label": "Instituce"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"address": {
|
||||
"label": "Adresa"
|
||||
},
|
||||
"city": {
|
||||
"label": "Město"
|
||||
},
|
||||
"country": {
|
||||
"label": "Stát"
|
||||
},
|
||||
"heading": "Lokace",
|
||||
"postal-code": {
|
||||
"label": "PSČ"
|
||||
},
|
||||
"region": {
|
||||
"label": "Region"
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"form": {
|
||||
"network": {
|
||||
"label": "Síť"
|
||||
},
|
||||
"username": {
|
||||
"label": "Uživatelské jméno"
|
||||
}
|
||||
},
|
||||
"heading": "Profily",
|
||||
"heading_one": "Profil"
|
||||
},
|
||||
"publications": {
|
||||
"form": {
|
||||
"publisher": {
|
||||
"label": "Vydavatel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"references": {
|
||||
"form": {
|
||||
"relationship": {
|
||||
"label": "Vztah"
|
||||
}
|
||||
}
|
||||
},
|
||||
"section": {
|
||||
"heading": "Sekce"
|
||||
},
|
||||
"volunteer": {
|
||||
"form": {
|
||||
"organization": {
|
||||
"label": "Firma"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rightSidebar": {
|
||||
"sections": {
|
||||
"css": {
|
||||
"heading": "Vlastní CSS"
|
||||
},
|
||||
"export": {
|
||||
"heading": "Exportovat",
|
||||
"json": {
|
||||
"primary": "JSON",
|
||||
"secondary": "Stáhněte si JSON verzi vašeho životopisu, kterou lze importovat zpět do Reactive Resume."
|
||||
},
|
||||
"pdf": {
|
||||
"loading": {
|
||||
"primary": "Generování PDF",
|
||||
"secondary": "Počkejte prosím, než se váš PDF vygeneruje, může to trvat až 15 sekund."
|
||||
},
|
||||
"normal": {
|
||||
"primary": "PDF",
|
||||
"secondary": "Stáhněte si PDF se svým životopisem, který si můžete vytisknout a poslat do své vysněné práce. Tento soubor nelze importovat zpět pro další úpravy."
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"heading": "Rozvržení",
|
||||
"tooltip": {
|
||||
"reset-layout": "Reset rozvržení"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"bugs-features": {
|
||||
"body": "Brání vám něco ve vytvoření životopisu? Nebo máte úžasný nápad, který byste mohli přidat? Pro začátek, založte problém na GitHubu.",
|
||||
"button": "Hlášení chyb GitHub",
|
||||
"heading": "Chyby? Požadavky na funkce?"
|
||||
},
|
||||
"donate": {
|
||||
"body": "Pokud se vám líbilo používání Reactive Resume, zvažte prosím darování co největší částky na udržení aplikace v provozu, bez reklam a navždy zdarma.",
|
||||
"button": "Kupte mi kávu",
|
||||
"heading": "Přispějte na Reactive Resume"
|
||||
},
|
||||
"github": "Zdrojový kód",
|
||||
"heading": "Odkazy"
|
||||
},
|
||||
"settings": {
|
||||
"global": {
|
||||
"date": {
|
||||
"primary": "Datum",
|
||||
"secondary": "Formát datumu, který se má používat napříč aplikací"
|
||||
},
|
||||
"heading": "Globální",
|
||||
"language": {
|
||||
"primary": "Jazyk",
|
||||
"secondary": "Jazyk zobrazení pro použití v celé aplikaci"
|
||||
},
|
||||
"theme": {
|
||||
"primary": "Motiv"
|
||||
}
|
||||
},
|
||||
"heading": "Nastavení",
|
||||
"page": {
|
||||
"break-line": {
|
||||
"primary": "Nový řádek",
|
||||
"secondary": "Zobrazit čáru na všech stránkách pro označení výšky stránky A4"
|
||||
},
|
||||
"heading": "Stránka",
|
||||
"orientation": {
|
||||
"disabled": "Nemá žádný efekt, pokud existuje pouze jedna stránka",
|
||||
"primary": "Orientace",
|
||||
"secondary": "Zda se mají stránky zobrazovat vodorovně nebo svisle"
|
||||
}
|
||||
},
|
||||
"resume": {
|
||||
"heading": "Životopis",
|
||||
"reset": {
|
||||
"primary": "Resetovat vše",
|
||||
"secondary": "Udělali jste příliš mnoho chyb? Kliknutím sem můžete všechny změny resetovat a začít znovu. Buďte opatrní, tuto akci nelze vrátit zpět."
|
||||
},
|
||||
"sample": {
|
||||
"primary": "Načíst ukázková data",
|
||||
"secondary": "Nevíte, kde začít? Klikněte zde a načtěte si vzorové údaje, abyste viděli, jak vypadá kompletní životopis."
|
||||
}
|
||||
}
|
||||
},
|
||||
"sharing": {
|
||||
"heading": "Sdílení",
|
||||
"short-url": {
|
||||
"label": "Preferovat krátkou adresu URL"
|
||||
},
|
||||
"visibility": {
|
||||
"subtitle": "Umožnit komukoli pomocí odkazu zobrazit váš životopis",
|
||||
"title": "Veřejné"
|
||||
}
|
||||
},
|
||||
"templates": {
|
||||
"heading": "Šablony"
|
||||
},
|
||||
"theme": {
|
||||
"form": {
|
||||
"background": {
|
||||
"label": "Pozadí"
|
||||
},
|
||||
"primary": {
|
||||
"label": "Hlavní"
|
||||
},
|
||||
"text": {
|
||||
"label": "Text"
|
||||
}
|
||||
},
|
||||
"heading": "Motiv"
|
||||
},
|
||||
"typography": {
|
||||
"form": {
|
||||
"font-family": {
|
||||
"label": "Rodina písma"
|
||||
},
|
||||
"font-size": {
|
||||
"label": "Velikost písma"
|
||||
}
|
||||
},
|
||||
"heading": "Typografie",
|
||||
"widgets": {
|
||||
"body": {
|
||||
"label": "Tělo"
|
||||
},
|
||||
"headings": {
|
||||
"label": "Nadpisy"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
358
client/public/locales/da/builder.json
Normal file
@ -0,0 +1,358 @@
|
||||
{
|
||||
"common": {
|
||||
"actions": {
|
||||
"add": "Tilføj ny {{token}}",
|
||||
"delete": "Slet {{token}}",
|
||||
"edit": "Rediger {{token}}"
|
||||
},
|
||||
"columns": {
|
||||
"heading": "Kolonner",
|
||||
"tooltip": "Skift antal kolonner"
|
||||
},
|
||||
"form": {
|
||||
"date": {
|
||||
"label": "Dato"
|
||||
},
|
||||
"description": {
|
||||
"label": "Beskriveslse"
|
||||
},
|
||||
"email": {
|
||||
"label": "Email adresse"
|
||||
},
|
||||
"end-date": {
|
||||
"help-text": "Lad dette felt stå tomt, hvis det stadig er til stede",
|
||||
"label": "Slutdato"
|
||||
},
|
||||
"keywords": {
|
||||
"label": "Nøgleord"
|
||||
},
|
||||
"level": {
|
||||
"label": "Niveau"
|
||||
},
|
||||
"levelNum": {
|
||||
"label": "Niveau (antal)"
|
||||
},
|
||||
"name": {
|
||||
"label": "Navn"
|
||||
},
|
||||
"phone": {
|
||||
"label": "Telefonnummer"
|
||||
},
|
||||
"position": {
|
||||
"label": "Stilling"
|
||||
},
|
||||
"start-date": {
|
||||
"label": "Startdato"
|
||||
},
|
||||
"subtitle": {
|
||||
"label": "Undertitel"
|
||||
},
|
||||
"summary": {
|
||||
"label": "Resumé"
|
||||
},
|
||||
"title": {
|
||||
"label": "Titel"
|
||||
},
|
||||
"url": {
|
||||
"label": "Hjemmeside"
|
||||
}
|
||||
},
|
||||
"glossary": {
|
||||
"page": "Side"
|
||||
},
|
||||
"list": {
|
||||
"actions": {
|
||||
"delete": "Slet",
|
||||
"duplicate": "Duplikér",
|
||||
"edit": "Rediger"
|
||||
},
|
||||
"empty-text": "Denne liste er tom."
|
||||
},
|
||||
"tooltip": {
|
||||
"delete-item": "Er du sikker på at du ønsker at slette denne aktivitet? Det kan ikke fortrydes.",
|
||||
"delete-section": "Slet sektion",
|
||||
"rename-section": "Omdøb sektion",
|
||||
"toggle-visibility": "Slå synlighed til/fra"
|
||||
}
|
||||
},
|
||||
"controller": {
|
||||
"tooltip": {
|
||||
"center-artboard": "Centrer tegnebræt",
|
||||
"copy-link": "Kopier link til CV",
|
||||
"export-pdf": "Eksporter PDF",
|
||||
"toggle-orientation": "Skift sideorientering",
|
||||
"toggle-page-break-line": "Skift sideskiftlinje",
|
||||
"toggle-sidebars": "Sidebjælke til/fra",
|
||||
"zoom-in": "Zoom ind",
|
||||
"zoom-out": "Zoom ud"
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"menu": {
|
||||
"delete": "Slet",
|
||||
"duplicate": "Duplikér",
|
||||
"rename": "Omdøb",
|
||||
"share-link": "Del Link",
|
||||
"tooltips": {
|
||||
"delete": "Er du sikker på at du ønsker at slette dette CV? Det kan ikke fortrydes.",
|
||||
"share-link": "Du skal ændre synligheden af dit CV til offentligheden for at gøre det synligt for andre."
|
||||
}
|
||||
}
|
||||
},
|
||||
"leftSidebar": {
|
||||
"sections": {
|
||||
"awards": {
|
||||
"form": {
|
||||
"awarder": {
|
||||
"label": "Udsteder"
|
||||
}
|
||||
}
|
||||
},
|
||||
"basics": {
|
||||
"actions": {
|
||||
"photo-filters": "Fotofiltre"
|
||||
},
|
||||
"heading": "Grundlæggende",
|
||||
"headline": {
|
||||
"label": "Overskrift"
|
||||
},
|
||||
"name": {
|
||||
"label": "Fulde navn"
|
||||
},
|
||||
"photo-filters": {
|
||||
"effects": {
|
||||
"border": {
|
||||
"label": "Grænse"
|
||||
},
|
||||
"grayscale": {
|
||||
"label": "Gråtoneskala"
|
||||
},
|
||||
"heading": "Effekter"
|
||||
},
|
||||
"shape": {
|
||||
"heading": "Facon"
|
||||
},
|
||||
"size": {
|
||||
"heading": "Størrelse (i px)"
|
||||
}
|
||||
},
|
||||
"photo-upload": {
|
||||
"tooltip": {
|
||||
"remove": "Fjern Billede",
|
||||
"upload": "Upload billede"
|
||||
}
|
||||
}
|
||||
},
|
||||
"certifications": {
|
||||
"form": {
|
||||
"issuer": {
|
||||
"label": "Udsteder"
|
||||
}
|
||||
}
|
||||
},
|
||||
"education": {
|
||||
"form": {
|
||||
"area-study": {
|
||||
"label": "Studieretning"
|
||||
},
|
||||
"courses": {
|
||||
"label": "Kurser"
|
||||
},
|
||||
"degree": {
|
||||
"label": "Grad"
|
||||
},
|
||||
"grade": {
|
||||
"label": "karakter"
|
||||
},
|
||||
"institution": {
|
||||
"label": "Institution"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"address": {
|
||||
"label": "Adresse"
|
||||
},
|
||||
"city": {
|
||||
"label": "By"
|
||||
},
|
||||
"country": {
|
||||
"label": "Land"
|
||||
},
|
||||
"heading": "Lokation",
|
||||
"postal-code": {
|
||||
"label": "Postnummer"
|
||||
},
|
||||
"region": {
|
||||
"label": "Region"
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"form": {
|
||||
"network": {
|
||||
"label": "Netværk"
|
||||
},
|
||||
"username": {
|
||||
"label": "Brugernavn"
|
||||
}
|
||||
},
|
||||
"heading": "Profiler",
|
||||
"heading_one": "Profil"
|
||||
},
|
||||
"publications": {
|
||||
"form": {
|
||||
"publisher": {
|
||||
"label": "Udgiver"
|
||||
}
|
||||
}
|
||||
},
|
||||
"references": {
|
||||
"form": {
|
||||
"relationship": {
|
||||
"label": "Forbindelse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"section": {
|
||||
"heading": "Sektion"
|
||||
},
|
||||
"volunteer": {
|
||||
"form": {
|
||||
"organization": {
|
||||
"label": "Organisation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rightSidebar": {
|
||||
"sections": {
|
||||
"css": {
|
||||
"heading": "Tilpasset CSS"
|
||||
},
|
||||
"export": {
|
||||
"heading": "Eksportér",
|
||||
"json": {
|
||||
"primary": "JSON",
|
||||
"secondary": "Download en JSON-version af dit CV, der kan importeres tilbage til Reactive Resume."
|
||||
},
|
||||
"pdf": {
|
||||
"loading": {
|
||||
"primary": "Generering af PDF",
|
||||
"secondary": "Vent venligst mens din PDF bliver genereret. Dette kan tage op til 15 sekunder."
|
||||
},
|
||||
"normal": {
|
||||
"primary": "PDF",
|
||||
"secondary": "Download en PDF af dit CV, som du kan printe og sende ud til dit drømmejob. Denne fil kan ikke importeres tilbage til yderligere redigering."
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"heading": "Layout",
|
||||
"tooltip": {
|
||||
"reset-layout": "Nulstil layout"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"bugs-features": {
|
||||
"body": "Er der noget, der forhindrer dig i at lave et CV? Eller har du en fantastisk idé at tilføje? Rejs et problem på GitHub for at komme i gang.",
|
||||
"button": "GitHub-problemer",
|
||||
"heading": "Fejl? Ønsker til en ny funktion?"
|
||||
},
|
||||
"donate": {
|
||||
"body": "Hvis du kunne lide at bruge Reactive Resume, bedes du overveje at donere så meget som muligt til formålet med at holde appen oppe og køre, uden annoncer og gratis for evigt.",
|
||||
"button": "Købe mig en kop kaffe",
|
||||
"heading": "Donér til Reactive Resume"
|
||||
},
|
||||
"github": "Kildekode",
|
||||
"heading": "Links"
|
||||
},
|
||||
"settings": {
|
||||
"global": {
|
||||
"date": {
|
||||
"primary": "Dato",
|
||||
"secondary": "Datoformat til brug på tværs af appen"
|
||||
},
|
||||
"heading": "Global",
|
||||
"language": {
|
||||
"primary": "Sprog",
|
||||
"secondary": "Vis sprog til brug på tværs af appen"
|
||||
},
|
||||
"theme": {
|
||||
"primary": "Tema"
|
||||
}
|
||||
},
|
||||
"heading": "Indstillinger",
|
||||
"page": {
|
||||
"break-line": {
|
||||
"primary": "Brudlinje",
|
||||
"secondary": "Vis en streg på alle sider for at markere højden på en A4-side"
|
||||
},
|
||||
"heading": "Side",
|
||||
"orientation": {
|
||||
"disabled": "Har ingen effekt, når der kun er én side",
|
||||
"primary": "Orientering",
|
||||
"secondary": "Om sider skal vises vandret eller lodret"
|
||||
}
|
||||
},
|
||||
"resume": {
|
||||
"heading": "Genoptag",
|
||||
"reset": {
|
||||
"primary": "Nulstil alt",
|
||||
"secondary": "lavet for mange fejl? Klik her for at nulstille alle ændringer og starte fra bunden. Vær forsigtig, denne handling kan ikke gøres om."
|
||||
},
|
||||
"sample": {
|
||||
"primary": "Indlæs prøvedata",
|
||||
"secondary": "Ikke sikker på, hvor du skal begynde? Klik her for at indlæse nogle eksempeldata for at se, hvordan et komplet CV ser ud."
|
||||
}
|
||||
}
|
||||
},
|
||||
"sharing": {
|
||||
"heading": "Deling",
|
||||
"short-url": {
|
||||
"label": "Foretræk Kort URL"
|
||||
},
|
||||
"visibility": {
|
||||
"subtitle": "Tillad alle med et link at se dit CV",
|
||||
"title": "Offentlig"
|
||||
}
|
||||
},
|
||||
"templates": {
|
||||
"heading": "Skabeloner"
|
||||
},
|
||||
"theme": {
|
||||
"form": {
|
||||
"background": {
|
||||
"label": "Baggrund"
|
||||
},
|
||||
"primary": {
|
||||
"label": "Primær"
|
||||
},
|
||||
"text": {
|
||||
"label": "Tekst"
|
||||
}
|
||||
},
|
||||
"heading": "Tema"
|
||||
},
|
||||
"typography": {
|
||||
"form": {
|
||||
"font-family": {
|
||||
"label": "Skrifttype"
|
||||
},
|
||||
"font-size": {
|
||||
"label": "Skriftstørrelse"
|
||||
}
|
||||
},
|
||||
"heading": "Typografi",
|
||||
"widgets": {
|
||||
"body": {
|
||||
"label": "Krop"
|
||||
},
|
||||
"headings": {
|
||||
"label": "Overskrifter"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
client/public/locales/da/common.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"avatar": {
|
||||
"menu": {
|
||||
"greeting": "Hej",
|
||||
"logout": "Log ud"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"credit": "Et passionsprojekt af <1>Amruth Pillai</1>",
|
||||
"license": "Af fællesskabet, for fællesskabet."
|
||||
},
|
||||
"markdown": {
|
||||
"help-text": "Dette afsnit understøtter <1>markdown</1> formatering."
|
||||
},
|
||||
"date": {
|
||||
"present": "Nuværende"
|
||||
},
|
||||
"subtitle": "En gratis og open source CV-bygger.",
|
||||
"title": "Reaktivt CV",
|
||||
"toast": {
|
||||
"error": {
|
||||
"upload-file-size": "Upload kun filer under 2 megabyte.",
|
||||
"upload-photo-size": "Upload kun billeder under 2 megabyte, helst kvadratiske."
|
||||
},
|
||||
"success": {
|
||||
"resume-link-copied": "Et link til dit CV er blevet kopieret til dit udklipsholder."
|
||||
}
|
||||
}
|
||||
}
|
||||
25
client/public/locales/da/dashboard.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"create-resume": {
|
||||
"subtitle": "Start fra begyndelsen",
|
||||
"title": "Opret nyt CV"
|
||||
},
|
||||
"import-external": {
|
||||
"subtitle": "LinkedIn, JSON CV, Reaktivt CV",
|
||||
"title": "Importer fra eksterne kilder"
|
||||
},
|
||||
"resume": {
|
||||
"menu": {
|
||||
"delete": "Slet",
|
||||
"duplicate": "Duplikér",
|
||||
"open": "Åbn",
|
||||
"rename": "Omdøb",
|
||||
"share-link": "Del Link",
|
||||
"tooltips": {
|
||||
"delete": "Er du sikker på at du ønsker at slette dette CV? Det kan ikke fortrydes.",
|
||||
"share-link": "Du skal ændre synligheden af dit CV til offentligheden for at gøre det synligt for andre."
|
||||
}
|
||||
},
|
||||
"timestamp": "Sidst opdateret for {{timestamp}} siden"
|
||||
},
|
||||
"title": "Betjeningspanel"
|
||||
}
|
||||
41
client/public/locales/da/landing.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"actions": {
|
||||
"app": "Gå til app",
|
||||
"login": "Log ind",
|
||||
"logout": "Log ud",
|
||||
"register": "Tilmeld"
|
||||
},
|
||||
"features": {
|
||||
"heading": "Funktioner",
|
||||
"list": {
|
||||
"ads": "Ingen reklamer.",
|
||||
"export": "Eksporter dit CV til JSON- eller PDF-format",
|
||||
"free": "Gratis for evigt",
|
||||
"import": "Importer data fra LinkedIn, JSON CV",
|
||||
"languages": "Tilgængelig på flere sprog",
|
||||
"more": "Og meget flere spændende funktioner, <1>læs alt om det her</1>",
|
||||
"tracking": "Ingen brugersporing"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"heading": "Links",
|
||||
"links": {
|
||||
"donate": "Donér",
|
||||
"github": "Kildekode",
|
||||
"privacy": "Fortrolighedspolitik",
|
||||
"service": "Servicevilkår"
|
||||
}
|
||||
},
|
||||
"screenshots": {
|
||||
"heading": "Skærmbilleder"
|
||||
},
|
||||
"testimonials": {
|
||||
"heading": "Udtalelser",
|
||||
"body": "Godt eller dårligt, jeg ville elske at høre din mening om Reactive Resume og hvordan oplevelsen har været for dig.<br/>Her er nogle af de beskeder, der er sendt af brugere over hele verden.",
|
||||
"contact": "Du kan kontakte mig via <1>min e-mail</1> eller gennem kontaktformularen på <3>min hjemmeside</3> ."
|
||||
},
|
||||
"summary": {
|
||||
"body": "Reactive Resume er en gratis og open source CV-bygger, der er bygget til at gøre de hverdagsagtige opgaver med at oprette, opdatere og dele dit CV så lette som 1, 2, 3. Med denne app kan du oprette flere CV'er, dele dem med rekrutterere eller venner gennem et unikt link og udskriv det som en PDF, helt gratis, ingen annoncer, ingen sporing, uden at miste integriteten og fortroligheden af dine data.",
|
||||
"heading": "Opsummering"
|
||||
}
|
||||
}
|
||||
136
client/public/locales/da/modals.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"auth": {
|
||||
"forgot-password": {
|
||||
"actions": {
|
||||
"send-email": "Send e-mail med Nulstil adgangskode"
|
||||
},
|
||||
"body": "Indtast blot den e-mailadresse, der er knyttet til den konto, du gerne vil gendanne.",
|
||||
"form": {
|
||||
"email": {
|
||||
"label": "Email adresse"
|
||||
}
|
||||
},
|
||||
"heading": "Har du glemt din adgangskode?",
|
||||
"help-text": "Hvis der er en konto, der er knyttet til %1 vil du modtage en e-mail med et link for at nulstille din adgangskode."
|
||||
},
|
||||
"login": {
|
||||
"actions": {
|
||||
"login": "Log ind",
|
||||
"google": "Log ind med Google"
|
||||
},
|
||||
"body": "Indtast venligst dit brugernavn og din adgangskode knyttet til din konto for at logge ind og få adgang til, administrere og dele dine CV'er.",
|
||||
"form": {
|
||||
"password": {
|
||||
"label": "Adgangskode"
|
||||
},
|
||||
"username": {
|
||||
"help-text": "Du skal indtaste din e-mailadresse.",
|
||||
"label": "Brugernavn"
|
||||
}
|
||||
},
|
||||
"heading": "Log ind på din konto",
|
||||
"recover-text": "Hvis du har glemt din adgangskode, kan du <1>gendanne din konto</1> her.",
|
||||
"register-text": "Hvis du ikke har en, kan du <1>oprette en konto</1> her."
|
||||
},
|
||||
"register": {
|
||||
"actions": {
|
||||
"register": "Tilmeld",
|
||||
"google": "Log på med Google"
|
||||
},
|
||||
"body": "Indtast e-mail adresse for at oprette en konto.",
|
||||
"form": {
|
||||
"confirm-password": {
|
||||
"label": "Bekræft adgangskode"
|
||||
},
|
||||
"email": {
|
||||
"label": "Email adresse"
|
||||
},
|
||||
"name": {
|
||||
"label": "Fulde navn"
|
||||
},
|
||||
"password": {
|
||||
"label": "Adgangskode"
|
||||
},
|
||||
"username": {
|
||||
"label": "Brugernavn"
|
||||
}
|
||||
},
|
||||
"heading": "Opret en konto",
|
||||
"loginText": "Hvis du allerede har en konto, kan du <1>logge ind her</1>."
|
||||
},
|
||||
"reset-password": {
|
||||
"actions": {
|
||||
"set-password": "Indstil ny adgangskode"
|
||||
},
|
||||
"body": "Indtast en ny adgangskode til din konto.",
|
||||
"form": {
|
||||
"confirm-password": {
|
||||
"label": "Bekræft adgangskode"
|
||||
},
|
||||
"password": {
|
||||
"label": "Adgangskode"
|
||||
}
|
||||
},
|
||||
"heading": "Nulstil din adgangskode"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"create-resume": {
|
||||
"actions": {
|
||||
"create-resume": "Opret CV"
|
||||
},
|
||||
"body": "Begynd at bygge dit CV ved at give det et navn. Det kan være i forbindelse med den rolle, du søger, eller blot din yndlingssnack.",
|
||||
"form": {
|
||||
"name": {
|
||||
"label": "Navn"
|
||||
},
|
||||
"public": {
|
||||
"label": "Er offentligt tilgængeligt?"
|
||||
},
|
||||
"slug": {
|
||||
"label": "Slug"
|
||||
}
|
||||
},
|
||||
"heading": "Opret nyt CV"
|
||||
},
|
||||
"import-external": {
|
||||
"heading": "Importer fra eksterne kilder",
|
||||
"json-resume": {
|
||||
"actions": {
|
||||
"upload-json": "Upload JSON"
|
||||
},
|
||||
"body": "Hvis du har et <1>valideret JSON-CV</1> klar, kan du bruge den til at fremskynde din udvikling på Reactive Resume. Klik på knappen nedenfor og upload en gyldig JSON-fil for at begynde.",
|
||||
"heading": "Importer fra JSON CV"
|
||||
},
|
||||
"linkedin": {
|
||||
"actions": {
|
||||
"upload-archive": "Upload ZIP-arkiv"
|
||||
},
|
||||
"body": "Du kan spare tid ved at eksportere dine data fra LinkedIn og bruge dem til automatisk at udfylde felter på Reactive Resume. Gå over til <1>Databeskyttelse</1> sektion på LinkedIn og anmod om et arkiv af dine data. Når den er tilgængelig, skal du uploade ZIP-filen nedenfor.",
|
||||
"heading": "Importer fra LinkedIn"
|
||||
},
|
||||
"reactive-resume": {
|
||||
"actions": {
|
||||
"upload-json": "Upload JSON",
|
||||
"upload-json-v2": "Upload JSON fra v2"
|
||||
},
|
||||
"body": "Hvis du har en JSON, der blev eksporteret med den aktuelle version af Reactive Resume, kan du importere den tilbage her for at få en redigerbar version igen.",
|
||||
"heading": "Importer fra JSON CV"
|
||||
}
|
||||
},
|
||||
"rename-resume": {
|
||||
"actions": {
|
||||
"rename-resume": "Omdøb CV"
|
||||
},
|
||||
"form": {
|
||||
"name": {
|
||||
"label": "Navn"
|
||||
},
|
||||
"slug": {
|
||||
"label": "Slug"
|
||||
}
|
||||
},
|
||||
"heading": "Omdøb dit CV"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,6 @@
|
||||
},
|
||||
"footer": {
|
||||
"credit": "Ein Herzensprojekt von <1>Amruth Pillai</1>",
|
||||
"language": {
|
||||
"missing": "Ihre Sprache fehlt?"
|
||||
},
|
||||
"license": "Von der Gemeinschaft, für die Gemeinschaft."
|
||||
},
|
||||
"markdown": {
|
||||
|
||||
@ -111,9 +111,10 @@
|
||||
},
|
||||
"reactive-resume": {
|
||||
"actions": {
|
||||
"upload-json": "JSON hochladen"
|
||||
"upload-json": "JSON hochladen",
|
||||
"upload-json-v2": "Laden Sie JSON von v2 hoch"
|
||||
},
|
||||
"body": "Wenn Sie ein JSON haben, das mit der aktuellen Version von Reactive Resume exportiert wurde, Sie können es hier wieder importieren um wieder eine editierbare Version zu erhalten. Vorherige Versionen von Reactive Resume werden derzeit leider nicht unterstützt.",
|
||||
"body": "Wenn Sie eine JSON haben, die mit der aktuellen Version von Reactive Resume exportiert wurde, können Sie sie hier wieder importieren, um wieder eine bearbeitbare Version zu erhalten.",
|
||||
"heading": "Import vom Reaktives Lebenslauf"
|
||||
}
|
||||
},
|
||||
|
||||
@ -7,9 +7,6 @@
|
||||
},
|
||||
"footer": {
|
||||
"credit": "A passion project by <1>Amruth Pillai</1>",
|
||||
"language": {
|
||||
"missing": "Missing your language?"
|
||||
},
|
||||
"license": "By the community, for the community."
|
||||
},
|
||||
"markdown": {
|
||||
|
||||
@ -7,9 +7,6 @@
|
||||
},
|
||||
"footer": {
|
||||
"credit": "Un proyecto apasionante de <1>Amruth Pillai</1>",
|
||||
"language": {
|
||||
"missing": "Idioma ausente?"
|
||||
},
|
||||
"license": "Por la comunidad, para la comunidad."
|
||||
},
|
||||
"markdown": {
|
||||
|
||||