diff --git a/.buildpacks b/.buildpacks index 3450683ce84ce6592d034ed2b4d7f7c29259c657..5e73304a5d7c5b9ac8d076a937a735972b2688e0 100644 --- a/.buildpacks +++ b/.buildpacks @@ -1,4 +1,3 @@ https://github.com/heroku/heroku-buildpack-apt https://github.com/Scalingo/ffmpeg-buildpack -https://github.com/Scalingo/nodejs-buildpack https://github.com/Scalingo/ruby-buildpack diff --git a/.codeclimate.yml b/.codeclimate.yml index d8d5c0ac797f31bd96469473e00a989083681430..dc8ca9a6f2d600fd4c1c9827192cf7592c3cfe09 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -27,10 +27,10 @@ plugins: enabled: true eslint: enabled: true - channel: eslint-6 + channel: eslint-7 rubocop: enabled: true - channel: rubocop-0-82 + channel: rubocop-0-92 sass-lint: enabled: true exclude_patterns: diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f49964bd9f5bfb2637bd258c3c4b399020ad7600..8ae4bb8825335b58f70dc7a45e3e1587deb7c95e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug Report about: If something isn't working as expected - +labels: bug --- <!-- Make sure that you are submitting a new bug that was not previously reported or already fixed --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3890729e22f22d5933f2e852573d5ac6c0397fdb..ff92c0316e031a28a4909165df28936998459f9f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,7 +1,6 @@ --- name: Feature Request about: I have a suggestion - --- <!-- Please use a concise and distinct title for the issue --> diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6b47350a4dd29ee794229388e143be64fd3db9f8..c4cd4887876a0d6ab75f446742300532e8b9ce9e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,7 +11,7 @@ updates: interval: weekly open-pull-requests-limit: 99 allow: - - dependency-type: all + - dependency-type: direct - package-ecosystem: bundler directory: "/" @@ -19,4 +19,4 @@ updates: interval: weekly open-pull-requests-limit: 99 allow: - - dependency-type: all + - dependency-type: direct diff --git a/.rubocop.yml b/.rubocop.yml index 25e0fa940b719fe66c416f9ac2445521a2df9eae..14728bf0e9417f3bebcd208eb9c19e11ef31168f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -25,30 +25,68 @@ Layout/AccessModifierIndentation: Layout/EmptyLineAfterMagicComment: Enabled: false +Layout/EmptyLineAfterGuardClause: + Enabled: false + +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: true + +Layout/HashAlignment: + Enabled: false + # EnforcedHashRocketStyle: table + # EnforcedColonStyle: table + +Layout/SpaceAroundMethodCallOperator: + Enabled: true + Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: space +Lint/DeprecatedOpenSSLConstant: + Enabled: true + +Lint/DuplicateElsifCondition: + Enabled: true + +Lint/MixedRegexpCaptureTypes: + Enabled: true + +Lint/RaiseException: + Enabled: true + +Lint/StructNewOverride: + Enabled: true + Lint/UselessAccessModifier: ContextCreatingMethods: - class_methods Metrics/AbcSize: Max: 100 + Exclude: + - 'lib/mastodon/*_cli.rb' Metrics/BlockLength: - Max: 35 + Max: 55 Exclude: - 'lib/tasks/**/*' + - 'lib/mastodon/*_cli.rb' Metrics/BlockNesting: Max: 3 + Exclude: + - 'lib/mastodon/*_cli.rb' Metrics/ClassLength: CountComments: false - Max: 300 + Max: 400 + Exclude: + - 'lib/mastodon/*_cli.rb' Metrics/CyclomaticComplexity: Max: 25 + Exclude: + - 'lib/mastodon/*_cli.rb' Layout/LineLength: AllowURI: true @@ -56,7 +94,9 @@ Layout/LineLength: Metrics/MethodLength: CountComments: false - Max: 55 + Max: 65 + Exclude: + - 'lib/mastodon/*_cli.rb' Metrics/ModuleLength: CountComments: false @@ -67,24 +107,29 @@ Metrics/ParameterLists: CountKeywordArgs: true Metrics/PerceivedComplexity: - Max: 20 + Max: 25 Naming/MemoizedInstanceVariableName: Enabled: false +Naming/MethodParameterName: + Enabled: true + Rails: Enabled: true -Rails/EnumHash: +Rails/ApplicationController: Enabled: false + Exclude: + - 'app/controllers/well_known/**/*.rb' -Rails/HasAndBelongsToMany: +Rails/BelongsTo: Enabled: false -Rails/SkipsModelValidations: +Rails/ContentTag: Enabled: false -Rails/HttpStatus: +Rails/EnumHash: Enabled: false Rails/Exit: @@ -92,9 +137,60 @@ Rails/Exit: - 'lib/mastodon/*' - 'lib/cli.rb' +Rails/FilePath: + Enabled: false + +Rails/HasAndBelongsToMany: + Enabled: false + +Rails/HasManyOrHasOneDependent: + Enabled: false + Rails/HelperInstanceVariable: Enabled: false +Rails/HttpStatus: + Enabled: false + +Rails/IndexBy: + Enabled: false + +Rails/InverseOf: + Enabled: false + +Rails/LexicallyScopedActionFilter: + Enabled: false + +Rails/OutputSafety: + Enabled: true + +Rails/RakeEnvironment: + Enabled: false + +Rails/RedundantForeignKey: + Enabled: false + +Rails/SkipsModelValidations: + Enabled: false + +Rails/UniqueValidationWithoutIndex: + Enabled: false + +Style/AccessorGrouping: + Enabled: true + +Style/AccessModifierDeclarations: + Enabled: false + +Style/ArrayCoercion: + Enabled: true + +Style/BisectedAttrAccessor: + Enabled: true + +Style/CaseLikeIf: + Enabled: false + Style/ClassAndModuleChildren: Enabled: false @@ -109,6 +205,15 @@ Style/Documentation: Style/DoubleNegation: Enabled: true +Style/ExpandPathArguments: + Enabled: false + +Style/ExponentialNotation: + Enabled: true + +Style/FormatString: + Enabled: false + Style/FormatStringToken: Enabled: false @@ -118,9 +223,33 @@ Style/FrozenStringLiteralComment: Style/GuardClause: Enabled: false +Style/HashAsLastArrayItem: + Enabled: false + +Style/HashEachMethods: + Enabled: true + +Style/HashLikeCase: + Enabled: true + +Style/HashTransformKeys: + Enabled: true + +Style/HashTransformValues: + Enabled: false + +Style/IfUnlessModifier: + Enabled: false + +Style/InverseMethods: + Enabled: false + Style/Lambda: Enabled: false +Style/MutableConstant: + Enabled: false + Style/PercentLiteralDelimiters: PreferredDelimiters: '%i': '()' @@ -129,9 +258,36 @@ Style/PercentLiteralDelimiters: Style/PerlBackrefs: AutoCorrect: false +Style/RedundantAssignment: + Enabled: false + +Style/RedundantFetchBlock: + Enabled: true + +Style/RedundantFileExtensionInRequire: + Enabled: true + +Style/RedundantRegexpCharacterClass: + Enabled: false + +Style/RedundantRegexpEscape: + Enabled: false + +Style/RedundantReturn: + Enabled: true + Style/RegexpLiteral: Enabled: false +Style/RescueStandardError: + Enabled: false + +Style/SignalException: + Enabled: false + +Style/SlicingWithRange: + Enabled: true + Style/SymbolArray: Enabled: false @@ -140,3 +296,6 @@ Style/TrailingCommaInArrayLiteral: Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: 'comma' + +Style/UnpackFirst: + Enabled: false diff --git a/.ruby-version b/.ruby-version index 338a5b5d8fec491b97978114dc35e36348fa56a7..37c2961c2430f357166156e7ddf1c590eb8d4ce1 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.6 +2.7.2 diff --git a/AUTHORS.md b/AUTHORS.md index 5ff241afd3605c403d7321f3037c44466a5311d9..43adc3bb1af4085d1e479480e3709c087b898346 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -5,38 +5,39 @@ Mastodon is available on [GitHub](https://github.com/tootsuite/mastodon) and provided thanks to the work of the following contributors: * [Gargron](https://github.com/Gargron) -* [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) * [ThibG](https://github.com/ThibG) -* [ykzts](https://github.com/ykzts) +* [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) * [dependabot[bot]](https://github.com/apps/dependabot) +* [ykzts](https://github.com/ykzts) * [akihikodaki](https://github.com/akihikodaki) * [mjankowski](https://github.com/mjankowski) * [unarist](https://github.com/unarist) * [yiskah](https://github.com/yiskah) * [nolanlawson](https://github.com/nolanlawson) * [abcang](https://github.com/abcang) -* [ysksn](https://github.com/ysksn) * [mayaeh](https://github.com/mayaeh) +* [ysksn](https://github.com/ysksn) * [sorin-davidoi](https://github.com/sorin-davidoi) +* [noellabo](https://github.com/noellabo) * [lynlynlynx](https://github.com/lynlynlynx) * [m4sk1n](mailto:me@m4sk.in) * [Marcin MikoÅ‚ajczak](mailto:me@m4sk.in) * [Kjwon15](https://github.com/Kjwon15) -* [noellabo](https://github.com/noellabo) * [renatolond](https://github.com/renatolond) * [alpaca-tc](https://github.com/alpaca-tc) * [jeroenpraat](https://github.com/jeroenpraat) * [nclm](https://github.com/nclm) * [ineffyble](https://github.com/ineffyble) -* [shleeable](https://github.com/shleeable) * [zunda](https://github.com/zunda) +* [shleeable](https://github.com/shleeable) * [Masoud Abkenar](mailto:ampbox@gmail.com) * [blackle](https://github.com/blackle) * [Quent-in](https://github.com/Quent-in) * [JantsoP](https://github.com/JantsoP) * [nullkal](https://github.com/nullkal) * [yookoala](https://github.com/yookoala) -* [Sasha-Sorokin](https://github.com/Sasha-Sorokin) +* [Brawaru](https://github.com/Brawaru) +* [ariasuni](https://github.com/ariasuni) * [Aditoo17](https://github.com/Aditoo17) * [Quenty31](https://github.com/Quenty31) * [marek-lach](https://github.com/marek-lach) @@ -45,9 +46,9 @@ and provided thanks to the work of the following contributors: * [danhunsaker](https://github.com/danhunsaker) * [eramdam](https://github.com/eramdam) * [takayamaki](https://github.com/takayamaki) -* [ariasuni](https://github.com/ariasuni) * [masarakki](https://github.com/masarakki) * [ticky](https://github.com/ticky) +* [trwnh](https://github.com/trwnh) * [ThisIsMissEm](https://github.com/ThisIsMissEm) * [hinaloe](https://github.com/hinaloe) * [hcmiya](https://github.com/hcmiya) @@ -57,10 +58,10 @@ and provided thanks to the work of the following contributors: * [yukimochi](https://github.com/yukimochi) * [palindromordnilap](https://github.com/palindromordnilap) * [rkarabut](https://github.com/rkarabut) -* [trwnh](https://github.com/trwnh) * [nightpool](https://github.com/nightpool) * [Artoria2e5](https://github.com/Artoria2e5) * [marrus-sh](https://github.com/marrus-sh) +* [dunn](https://github.com/dunn) * [krainboltgreene](https://github.com/krainboltgreene) * [pfigel](https://github.com/pfigel) * [BoFFire](https://github.com/BoFFire) @@ -84,25 +85,25 @@ and provided thanks to the work of the following contributors: * [ashleyhull-versent](https://github.com/ashleyhull-versent) * [yhirano55](https://github.com/yhirano55) * [rinsuki](https://github.com/rinsuki) -* [dunn](https://github.com/dunn) * [devkral](https://github.com/devkral) * [camponez](https://github.com/camponez) * [hugogameiro](https://github.com/hugogameiro) * [SerCom_KC](mailto:szescxz@gmail.com) * [aschmitz](https://github.com/aschmitz) +* [mfmfuyu](https://github.com/mfmfuyu) +* [kedamaDQ](https://github.com/kedamaDQ) * [fpiesche](https://github.com/fpiesche) * [gandaro](https://github.com/gandaro) * [johnsudaar](https://github.com/johnsudaar) * [trebmuh](https://github.com/trebmuh) * [rmhasan](https://github.com/rmhasan) -* [kedamaDQ](https://github.com/kedamaDQ) * [lindwurm](https://github.com/lindwurm) * [victorhck](mailto:victorhck@geeko.site) * [voidsatisfaction](https://github.com/voidsatisfaction) +* [mkljczk](https://github.com/mkljczk) * [hikari-no-yume](https://github.com/hikari-no-yume) * [seefood](https://github.com/seefood) * [jackjennings](https://github.com/jackjennings) -* [mfmfuyu](https://github.com/mfmfuyu) * [puckipedia](https://github.com/puckipedia) * [spla](mailto:spla@mastodont.cat) * [walf443](https://github.com/walf443) @@ -111,14 +112,15 @@ and provided thanks to the work of the following contributors: * [Ashley](mailto:expenses@airmail.cc) * [xqus](https://github.com/xqus) * [pfm-eyesightjp](https://github.com/pfm-eyesightjp) -* [Samy KACIMI](mailto:samy.kacimi@gmail.com) +* [fakenine](https://github.com/fakenine) * [tsuwatch](https://github.com/tsuwatch) * [victorhck](https://github.com/victorhck) -* [mkljczk](https://github.com/mkljczk) * [manuelviens](https://github.com/manuelviens) +* [tateisu](https://github.com/tateisu) * [fvh-P](https://github.com/fvh-P) * [rtucker](https://github.com/rtucker) * [Anna e só](mailto:contraexemplos@gmail.com) +* [dariusk](https://github.com/dariusk) * [kazu9su](https://github.com/kazu9su) * [Komic](https://github.com/Komic) * [lmorchard](https://github.com/lmorchard) @@ -145,9 +147,9 @@ and provided thanks to the work of the following contributors: * [fhemberger](https://github.com/fhemberger) * [Gomasy](https://github.com/Gomasy) * [greysteil](https://github.com/greysteil) -* [hencatsmith](https://github.com/hencatsmith) +* [hendotcat](https://github.com/hendotcat) * [d6rkaiz](https://github.com/d6rkaiz) -* [Reverite](https://github.com/Reverite) +* [ladyisatis](https://github.com/ladyisatis) * [JohnD28](https://github.com/JohnD28) * [znz](https://github.com/znz) * [saper](https://github.com/saper) @@ -160,14 +162,14 @@ and provided thanks to the work of the following contributors: * [leopku](https://github.com/leopku) * [SansPseudoFix](https://github.com/SansPseudoFix) * [spla](mailto:sp@mastodont.cat) -* [tateisu](https://github.com/tateisu) * [tomfhowe](https://github.com/tomfhowe) * [noraworld](https://github.com/noraworld) * [lfuelling](https://github.com/lfuelling) -* [theboss](https://github.com/theboss) +* [aji-su](https://github.com/aji-su) * [nzws](https://github.com/nzws) * [duxovni](https://github.com/duxovni) * [smorimoto](https://github.com/smorimoto) +* [mashirozx](https://github.com/mashirozx) * [178inaba](https://github.com/178inaba) * [acid-chicken](https://github.com/acid-chicken) * [xgess](https://github.com/xgess) @@ -175,7 +177,6 @@ and provided thanks to the work of the following contributors: * [aablinov](https://github.com/aablinov) * [stalker314314](https://github.com/stalker314314) * [cutls](https://github.com/cutls) -* [dariusk](https://github.com/dariusk) * [huertanix](https://github.com/huertanix) * [eleboucher](https://github.com/eleboucher) * [halkeye](https://github.com/halkeye) @@ -183,7 +184,7 @@ and provided thanks to the work of the following contributors: * [treby](https://github.com/treby) * [jpdevries](https://github.com/jpdevries) * [gdpelican](https://github.com/gdpelican) -* [kmichl](https://github.com/kmichl) +* [Korbinian](mailto:kontakt@korbinian-michl.de) * [Kurtis Rainbolt-Greene](mailto:me@kurtisrainboltgreene.name) * [panarom](https://github.com/panarom) * [Dar13](https://github.com/Dar13) @@ -225,6 +226,7 @@ and provided thanks to the work of the following contributors: * [aaribaud](https://github.com/aaribaud) * [pointlessone](https://github.com/pointlessone) * [Andrew](mailto:andrewlchronister@gmail.com) +* [arielrodrigues](https://github.com/arielrodrigues) * [aurelien-reeves](https://github.com/aurelien-reeves) * [elegaanz](https://github.com/elegaanz) * [estuans](https://github.com/estuans) @@ -238,6 +240,7 @@ and provided thanks to the work of the following contributors: * [muffinista](https://github.com/muffinista) * [cdutson](https://github.com/cdutson) * [farlistener](https://github.com/farlistener) +* [divergentdave](https://github.com/divergentdave) * [DavidLibeau](https://github.com/DavidLibeau) * [dmerejkowsky](https://github.com/dmerejkowsky) * [ddevault](https://github.com/ddevault) @@ -276,7 +279,7 @@ and provided thanks to the work of the following contributors: * [xPaw](https://github.com/xPaw) * [petzah](https://github.com/petzah) * [ignisf](https://github.com/ignisf) -* [raymestalez](https://github.com/raymestalez) +* [lumenwrites](https://github.com/lumenwrites) * [remram44](https://github.com/remram44) * [sts10](https://github.com/sts10) * [SuperSandro2000](https://github.com/SuperSandro2000) @@ -286,8 +289,9 @@ and provided thanks to the work of the following contributors: * [Sir-Boops](https://github.com/Sir-Boops) * [stemid](https://github.com/stemid) * [sumdog](https://github.com/sumdog) +* [OmmyZhang](https://github.com/OmmyZhang) * [ThomasLeister](https://github.com/ThomasLeister) -* [mcat-ee](https://github.com/mcat-ee) +* [Tom McAtee](mailto:a1608768@student.adelaide.edu.au) * [tototoshi](https://github.com/tototoshi) * [TrashMacNugget](https://github.com/TrashMacNugget) * [VirtuBox](https://github.com/VirtuBox) @@ -314,11 +318,13 @@ and provided thanks to the work of the following contributors: * [matsurai25](https://github.com/matsurai25) * [mecab](https://github.com/mecab) * [nicobz25](https://github.com/nicobz25) +* [niwatori24](https://github.com/niwatori24) * [oliverkeeble](https://github.com/oliverkeeble) * [partev](https://github.com/partev) * [pinfort](https://github.com/pinfort) * [rbaumert](https://github.com/rbaumert) * [rhoio](https://github.com/rhoio) +* [santiagorodriguez96](https://github.com/santiagorodriguez96) * [sclaire-1](https://github.com/sclaire-1) * [umonaca](https://github.com/umonaca) * [usagi-f](https://github.com/usagi-f) @@ -327,7 +333,7 @@ and provided thanks to the work of the following contributors: * [wxcafe](https://github.com/wxcafe) * [Grawl](https://github.com/Grawl) * [新都心(Neet Shin)](mailto:nucx@dio-vox.com) -* [clarfon](https://github.com/clarfon) +* [clarfonthey](https://github.com/clarfonthey) * [cygnan](https://github.com/cygnan) * [Awea](https://github.com/Awea) * [eai04191](https://github.com/eai04191) @@ -358,11 +364,11 @@ and provided thanks to the work of the following contributors: * [schas002](https://github.com/schas002) * [contraexemplo](https://github.com/contraexemplo) * [abackstrom](https://github.com/abackstrom) -* [arielrodrigues](https://github.com/arielrodrigues) * [orlea](https://github.com/orlea) * [armandfardeau](https://github.com/armandfardeau) * [raboof](https://github.com/raboof) * [jumbosushi](https://github.com/jumbosushi) +* [acuteaura](https://github.com/acuteaura) * [ayumin](https://github.com/ayumin) * [bzg](https://github.com/bzg) * [BastienDurel](https://github.com/BastienDurel) @@ -389,7 +395,7 @@ and provided thanks to the work of the following contributors: * [colindean](https://github.com/colindean) * [DeeUnderscore](https://github.com/DeeUnderscore) * [dachinat](https://github.com/dachinat) -* [shapeshifter-system](https://github.com/shapeshifter-system) +* [monsterpit-firedemon](https://github.com/monsterpit-firedemon) * [watilde](https://github.com/watilde) * [daprice](https://github.com/daprice) * [da2x](https://github.com/da2x) @@ -400,14 +406,13 @@ and provided thanks to the work of the following contributors: * [singingwolfboy](https://github.com/singingwolfboy) * [caldwell](https://github.com/caldwell) * [davidcelis](https://github.com/davidcelis) -* [divergentdave](https://github.com/divergentdave) * [davefp](https://github.com/davefp) * [yipdw](https://github.com/yipdw) * [debanshuk](https://github.com/debanshuk) * [mascali33](https://github.com/mascali33) * [DerekNonGeneric](https://github.com/DerekNonGeneric) * [dblandin](https://github.com/dblandin) -* [Drew Gates](mailto:aranaur@users.noreply.github.com) +* [Aranaur](https://github.com/Aranaur) * [dtschust](https://github.com/dtschust) * [Dryusdan](https://github.com/Dryusdan) * [d3vgru](https://github.com/d3vgru) @@ -451,22 +456,25 @@ and provided thanks to the work of the following contributors: * [J Yeary](mailto:usbsnowcrash@users.noreply.github.com) * [jack-michaud](https://github.com/jack-michaud) * [Floppy](https://github.com/Floppy) -* [loomchild](https://github.com/loomchild) -* [jglauche](https://github.com/jglauche) -* [jenkr55](https://github.com/jenkr55) -* [hyenagirl64](https://github.com/hyenagirl64) -* [press5](https://github.com/press5) -* [TrollDecker](https://github.com/TrollDecker) -* [jmontane](https://github.com/jmontane) +* [Jarek Lipski](mailto:pub@loomchild.net) +* [Jennifer Glauche](mailto:=^.^=@github19.jglauche.de) +* [Jennifer Kruse](mailto:jenkr55@gmail.com) +* [Jeremy Rose](mailto:nornagon@nornagon.net) +* [Jessica](mailto:46502909+hyenagirl64@users.noreply.github.com) +* [Jessica K. Litwin](mailto:jessica@litw.in) +* [Jo Decker](mailto:trolldecker@users.noreply.github.com) +* [Joan Montané](mailto:jmontane@users.noreply.github.com) * [Jonathan Klee](mailto:klee.jonathan@gmail.com) * [Jordan Guerder](mailto:jguerder@fr.pulseheberg.net) * [Joseph Mingrone](mailto:jehops@users.noreply.github.com) +* [Josh Leeb-du Toit](mailto:mail@joshleeb.com) * [Joshua Wood](mailto:josh@joshuawood.net) * [Julien](mailto:tiwy57@users.noreply.github.com) * [Julien Deswaef](mailto:juego@requiem4tv.com) * [June Sallou](mailto:jnsll@users.noreply.github.com) * [Jérémy Benoist](mailto:j0k3r@users.noreply.github.com) * [KEINOS](mailto:github@keinos.com) +* [Kairui Song | 宋æºç¿](mailto:ryncsn@gmail.com) * [Keiji Matsuzaki](mailto:futoase@gmail.com) * [Kevin Liu](mailto:kevin@potatofrom.space) * [Kit Redgrave](mailto:qwertyitis@gmail.com) @@ -482,7 +490,6 @@ and provided thanks to the work of the following contributors: * [Lukas Burk](mailto:jemus42@users.noreply.github.com) * [Manato Kameya](mailto:grabacr07+github@gmail.com) * [Mantas](mailto:mistermantas@users.noreply.github.com) -* [Marcin MikoÅ‚ajczak](mailto:me@mkljczk.pl) * [Mareena Kunjachan](mailto:mareenakunjachan@gmail.com) * [Marek Lach](mailto:marek.brohatwack.lach@gmail.com) * [Markus R](mailto:wirehack7@users.noreply.github.com) @@ -529,10 +536,12 @@ and provided thanks to the work of the following contributors: * [Norayr Chilingarian](mailto:norayr@arnet.am) * [Noëlle Anthony](mailto:noelle.d.anthony@gmail.com) * [Næ°](mailto:uenok.htc@gmail.com) +* [OSAMU SATO](mailto:satosamu@gmail.com) * [Olivier Nicole](mailto:olivierthnicole@gmail.com) * [Oskari Noppa](mailto:noppa@users.noreply.github.com) * [Otakan](mailto:otakan951@gmail.com) * [Padraig Fahy](mailto:tech@padraigfahy.com) +* [Patrice Ferlet](mailto:metal3d@gmail.com) * [PatrickRWells](mailto:32802366+patrickrwells@users.noreply.github.com) * [Paul](mailto:naydex.mc+github@gmail.com) * [Pete Keen](mailto:pete@petekeen.net) @@ -574,7 +583,6 @@ and provided thanks to the work of the following contributors: * [TakesxiSximada](mailto:takesxi.sximada@gmail.com) * [Tao Bror Bojlén](mailto:brortao@users.noreply.github.com) * [Taras Gogol](mailto:taras2358@gmail.com) -* [Tdxdxoz](mailto:tdxdxoz@gmail.com) * [TheInventrix](mailto:theinventrix@users.noreply.github.com) * [TheMainOne](mailto:50847364+theevilskeleton@users.noreply.github.com) * [Thomas Alberola](mailto:thomas@needacoffee.fr) @@ -594,6 +602,7 @@ and provided thanks to the work of the following contributors: * [Wesley Ellis](mailto:tahnok@gmail.com) * [Wiktor](mailto:wiktor@metacode.biz) * [Wonderfall](mailto:wonderfall@schrodinger.io) +* [Y.Yamashiro](mailto:shukukei@mojizuri.jp) * [YDrogen](mailto:ydrogen45@gmail.com) * [YMHuang](mailto:ymhuang@fmbase.tw) * [YOSHIOKA Eiichiro](mailto:yoshioka.eiichiro@gmail.com) @@ -638,6 +647,7 @@ and provided thanks to the work of the following contributors: * [jumoru](mailto:jumoru@mailbox.org) * [kaiyou](mailto:pierre@jaury.eu) * [karlyeurl](mailto:karl.yeurl@gmail.com) +* [kawaguchi](mailto:jiikko@users.noreply.github.com) * [kedama](mailto:32974885+kedamadq@users.noreply.github.com) * [kuro5hin](mailto:rusty@kuro5hin.org) * [leo60228](mailto:leo@60228.dev) @@ -655,6 +665,7 @@ and provided thanks to the work of the following contributors: * [notozeki](mailto:notozeki@users.noreply.github.com) * [ntl-purism](mailto:57806346+ntl-purism@users.noreply.github.com) * [nzws](mailto:git-yuzu@svk.jp) +* [proxy](mailto:51172302+3n-k1@users.noreply.github.com) * [rch850](mailto:rich850@gmail.com) * [roikale](mailto:roikale@users.noreply.github.com) * [rysiekpl](mailto:rysiek@hackerspace.pl) @@ -694,122 +705,414 @@ This document is provided for informational purposes only. Since it is only upda Following people have contributed to translation of Mastodon: -- Zoltán Gera (*Hungarian*) -- Kristijan Tkalec (*Slovenian*) -- Evert Prants (*Estonian*) +- á¦áᎢᎵ᫠😷 (KNTRO) (*Spanish, Argentina*) +- Sveinn à Felli (sveinki) (*Icelandic*) +- qezwan (*Persian, Sorani (Kurdish)*) +- Hồ Nhất Duy (kantcer) (*Vietnamese*) +- taicv (*Vietnamese*) +- Zoltán Gera (gerazo) (*Hungarian*) +- ButterflyOfFire (BoFFire) (*French, Arabic, Kabyle*) +- adrmzz (*Sardinian*) +- Ramdziana F Y (rafeyu) (*Indonesian*) +- Evert Prants (IcyDiamond) (*Estonian*) +- Daniele Lira Mereb (danilmereb) (*Portuguese, Brazilian*) +- Xosé M. (XoseM) (*Spanish, Galician*) +- Kristijan Tkalec (lapor) (*Slovenian*) +- stan ionut (stanionut12) (*Romanian*) +- Besnik_b (*Albanian*) +- Emanuel Pina (emanuelpina) (*Portuguese*) +- Thai Localization (thl10n) (*Thai*) +- å¥ˆåœæ‹‰ (nebula_moe) (*Chinese Simplified*) +- Jeong Arm (Kjwon15) (*Japanese, Korean, Esperanto*) +- Michal Stanke (mstanke) (*Czech*) +- Alix Rossi (palindromordnilap) (*French, Corsican*) +- spla (*Spanish, Catalan*) +- Imre Kristoffer Eilertsen (DandelionSprout) (*Norwegian*) +- Jeroen (jeroenpraat) (*Dutch*) - borys_sh (*Ukrainian*) -- ButterflyOfFire (*Arabic; French*) -- Osoitz (*Basque*) -- oɹʇuÊž (*Spanish, Argentina*) +- Miguel Mayol (mitcoes) (*Spanish, Catalan*) +- Danial Behzadi (danialbehzadi) (*Persian*) +- yeft (*Chinese Traditional, Chinese Traditional, Hong Kong*) - koyu (*German*) -- Jeroen (*Dutch*) -- Muha Aliss (*Turkish*) -- å”å®—å‹› (*Chinese Simplified*) -- Jeong Arm (*Korean; Esperanto; Japanese*) -- Oguz Ersen (*Turkish*) -- spla (*Catalan*) -- Ramdziana F Y (*Indonesian*) -- Aditoo17 (*Czech*) -- Xosé M. (*Galician*) -- Roboron (*Spanish*) -- Alix Rossi (*Corsican; French*) -- Maya Minatsuki (*Japanese*) -- Masoud Abkenar (*Persian*) -- Thai Localization (*Thai*) -- Marek Ľach (*Slovak; Polish*) -- d5Ziif3K (*Ukrainian*) +- Koala Yeung (yookoala) (*Chinese Traditional, Hong Kong*) +- Osoitz (*Basque*) +- Peterandre (*Norwegian, Norwegian Nynorsk*) +- tzium (*Sardinian*) +- Iváns (Ivans_translator) (*Galician*) +- Sasha Sorokin (Sasha-Sorokin) (*French, Catalan, Danish, German, Greek, Hungarian, Armenian, Korean, Russian, Albanian, Swedish, Ukrainian, Vietnamese, Galician*) +- kamee (*Armenian*) +- tolstoevsky (*Russian*) +- enolp (*Asturian*) +- FédiQuébec (manuelviens) (*French*) - lamnatos (*Greek*) -- Emyn Nant Nefydd (*Welsh*) +- Maya Minatsuki (mayaeh) (*Japanese*) +- Masoud Abkenar (mabkenar) (*Persian*) +- Alessandro Levati (Oct326) (*Italian*) +- arshat (*Kazakh*) +- Roboron (*Spanish*) +- ariasuni (*French, Arabic, Czech, German, Greek, Hungarian, Slovenian, Ukrainian, Chinese Simplified, Portuguese, Brazilian, Persian, Norwegian Nynorsk, Esperanto, Breton, Corsican, Sardinian, Kabyle*) +- Ali DemirtaÅŸ (alidemirtas) (*Turkish*) +- Em St Cenydd (cancennau) (*Welsh*) +- Marek Ľach (mareklach) (*Polish, Slovak*) +- Muha Aliss (muhaaliss) (*Turkish*) +- Jurica (ahjk) (*Croatian*) +- Aditoo17 (*Czech*) - Diluns (*Occitan*) +- gagik_ (*Armenian*) +- vishnuvaratharajan (*Tamil*) +- Marcin MikoÅ‚ajczak (mkljczkk) (*Czech, Polish, Russian*) +- regulartranslator (*Portuguese, Brazilian*) +- Akarshan Biswas (biswasab) (*Bengali, Sanskrit*) +- Yi-Jyun Pan (pan93412) (*Chinese Traditional*) +- d5Ziif3K (*Ukrainian*) +- GiorgioHerbie (*Italian*) +- Rafael H L Moretti (Moretti) (*Portuguese, Brazilian*) +- Saederup92 (*Danish*) +- christalleras (*Norwegian Nynorsk*) +- cybergene (cyber-gene) (*Japanese*) +- Taloran (*Norwegian Nynorsk*) +- ThibG (*French, Icelandic*) +- xatier (*Chinese Traditional*) +- otrapersona (*Spanish, Spanish, Mexico*) - atarashiako (*Chinese Simplified*) -- 101010 (*Polish*) -- Yi-Jyun Pan (*Chinese Traditional*) +- 101010 (101010pl) (*Polish*) - silkevicious (*Italian*) -- FédiQuébec (*French*) -- Jaz-Michael King (*Welsh*) -- christalleras (*Norwegian Nynorsk*) -- tykayn (*French*) -- Alessandro Levati (*Italian*) +- Floxu (fredrikdim1) (*Norwegian Nynorsk*) +- Bertil Hedkvist (Berrahed) (*Swedish*) +- William(Ñ•)â¿ (wmlgr) (*Spanish*) +- norayr (*Armenian*) +- Tiago Epifânio (tfve) (*Portuguese*) +- Ryo (DrRyo) (*Korean*) +- Mentor Gashi (mentorgashi.com) (*Albanian*) +- Jaz-Michael King (jazmichaelking) (*Welsh*) - carolinagiorno (*Portuguese, Brazilian*) +- Roby Thomas (roby.thomas) (*Malayalam*) +- Bharat Kumar (Marwari) (*Hindi*) +- ThonyVezbe (*Breton*) +- dkdarshan760 (*Sanskrit*) +- Tagomago (tagomago) (*French, Spanish*) +- tykayn (*French*) +- axi (*Finnish*) +- Selyan Slimane AMIRI (slimane_AMIRI) (*Kabyle*) +- Balázs Meskó (mesko.balazs) (*Hungarian*) - taoxvx (*Danish*) -- sabri (*Spanish*) -- Sasha Sorokin (*Russian*) -- shioko (*Chinese Simplified*) -- Evgeny Petrov (*Russian*) -- ariasuni (*French; Esperanto*) -- Tiago Epifânio (*Portuguese*) -- dxwc (*Bengali*) +- Hrach Mkrtchyan (mhrach87) (*Armenian*) +- sabri (thetomatoisavegetable) (*Spanish, Spanish, Argentina*) +- Dewi (Unkorneg) (*French, Breton*) +- Coelacanthus (*Chinese Simplified*) +- syncopams (*Chinese Simplified, Chinese Traditional, Chinese Traditional, Hong Kong*) +- SteinarK (*Norwegian Nynorsk*) +- Sokratis Alichanidis (alichani) (*Greek*) +- Mathias B. Vagnes (vagnes) (*Norwegian*) +- dashersyed (*Urdu (Pakistan)*) +- Acolyte (666noob404) (*Ukrainian*) +- Conight Wang (xfddwhh) (*Chinese Simplified*) - liffon (*Swedish*) +- Damjan Dimitrioski (gnud) (*Macedonian*) +- PPNplus (*Thai*) +- shioko (*Chinese Simplified*) +- v4vachan (*Malayalam*) +- Hakim Oubouali (zenata1) (*Standard Moroccan Tamazight*) +- Evgeny Petrov (kondra007) (*Russian*) +- Gwenn (Belvar) (*Breton*) +- StanleyFrew (*French*) +- Hayk Khachatryan (brutusromanus123) (*Armenian*) +- jaranta (*Finnish*) +- Felicia (midsommar) (*Swedish*) +- Denys (dector) (*Ukrainian*) +- Pukima (pukimaaa) (*German*) - Vanege (*Esperanto*) -- Johan Schiff (*Swedish*) -- kat (*Ukrainian; Russian*) -- oti4500 (*Hungarian; Ukrainian*) -- Juan José Salvador Piedra (*Spanish*) -- diazepan (*Spanish*) +- Jess Rafn (therealyez) (*Danish*) +- strubbl (*German*) +- Stasiek Michalski (hellcp) (*Polish*) +- dxwc (*Bengali*) +- jmontane (*Catalan*) +- Liboide (*Spanish*) +- Johan Schiff (schyffel) (*Swedish*) +- Arunmozhi (tecoholic) (*Tamil*) +- kat (katktv) (*Russian, Ukrainian*) +- Rikard Linde (rikardlinde) (*Swedish*) +- oti4500 (*Hungarian, Ukrainian*) +- Laura (selfisekai) (*Polish*) +- Rachida S. (ZiriSut) (*Kabyle*) +- diazepan (*Spanish, Spanish, Argentina*) +- marzuquccen (*Kabyle*) +- Juan José Salvador Piedra (JuanjoSalvador) (*Spanish*) +- Tigran (tigransimonyan) (*Armenian*) +- BurekzFinezt (*Serbian (Cyrillic)*) - SHeija (*Finnish*) -- Jack R (*Spanish*) -- Saederup92 (*Danish*) -- Stasiek Michalski (*Polish*) -- Dewi (*Breton; French*) -- cybergene (*Japanese*) -- AW Unad (*Indonesian*) -- Andrea Lo Iacono (*Italian*) -- Ray (*Spanish*) +- atriix (*Swedish*) +- Jack R (isaac.97_WT) (*Spanish*) +- antonyho (*Chinese Traditional, Hong Kong*) +- andruhov (*Russian, Ukrainian*) +- Aryamik Sharma (Aryamik) (*Swedish, Hindi*) +- phena109 (*Chinese Traditional, Hong Kong*) +- 森ã®åリスã®ãƒŸãƒ¼ã‚³ã®å¤§å†’険 (Phroneris) (*Japanese*) +- ã‚‹ã„ーã (ruine) (*Japanese*) +- ahangarha (*Persian*) +- Sam Tux (imahbub) (*Bengali*) +- igordrozniak (*Polish*) - Unmual (*Spanish*) -- Ryo (*Korean*) -- juanda097 (*Spanish*) +- Isaac Huang (caasih) (*Chinese Traditional*) +- AW Unad (awcodify) (*Indonesian*) +- Allen Zhong (AstroProfundis) (*Chinese Simplified*) +- Cutls (cutls) (*Japanese*) +- Ray (Ipsumry) (*Spanish*) +- Falling Snowdin (tghgg) (*Vietnamese*) +- coxde (*Chinese Simplified*) +- Rasmus Lindroth (RasmusLindroth) (*Swedish*) +- Andrea Lo Iacono (niels0n) (*Italian*) +- Kinshuk Sunil (kinshuksunil) (*Hindi*) +- Ullas Joseph (ullasjoseph) (*Malayalam*) +- Goudarz Jafari (Goudarz) (*Persian*) +- Yu-Pai Liu (tedliou) (*Chinese Traditional*) +- Amarin Cemthong (acitmaster) (*Thai*) +- juanda097 (juanda-097) (*Spanish*) - Anunnakey (*Macedonian*) -- Cutls (*Japanese*) +- fragola (*Italian*) - erikstl (*Esperanto*) -- ruine (*Japanese*) +- twpenguin (*Chinese Traditional*) +- bobchao (*Chinese Traditional*) +- Esther (esthermations) (*Portuguese*) - MadeInSteak (*Finnish*) -- Sokratis Alichanidis (*Greek*) -- dragnucs2 (*Arabic*) -- frumble (*German*) -- Rikard Linde (*Swedish*) -- PPNplus (*Thai*) +- Heimen Stoffels (vistausss) (*Dutch*) +- Rajarshi Guha (rajarshiguha) (*Bengali*) +- Andrew (iAndrew3) (*Romanian*) +- Gopal Sharma (gopalvirat) (*Hindi*) - arethsu (*Swedish*) -- EPEMA YT (*German*) -- Rhys Harrison (*Esperanto*) -- KEINOS (*Japanese*) +- Tofiq Abdula (Xwla) (*Sorani (Kurdish)*) +- Carlos SolÃs (csolisr) (*Esperanto*) +- Parthan S Ramanujam (parthan) (*Tamil*) +- Kasper Nymand (KasperNymand) (*Danish*) +- TS (morte) (*Finnish*) +- subram (*Turkish*) +- SensDeViata (*Ukrainian*) +- Ptrcmd (ptrcmd) (*Chinese Traditional*) +- SergioFMiranda (*Portuguese, Brazilian*) +- Scvoet (scvoet) (*Chinese Simplified*) +- hiroTS (*Chinese Traditional*) +- johne32rus23 (*Russian*) +- AzureNya (*Chinese Simplified*) +- OctolinGamer (octolingamer) (*Portuguese, Brazilian*) +- Ram varma (ram4varma) (*Tamil*) +- Hexandcube (hexandcube) (*Polish*) +- 北䑓如法 (Nyoho) (*Japanese*) +- frumble (*German*) +- kekkepikkuni (*Tamil*) +- Neo_Chen (NeoChen1024) (*Chinese Traditional*) +- oorsutri (*Tamil*) +- Rhys Harrison (rhedders) (*Esperanto*) +- Nithin V (Nithin896) (*Tamil*) +- Miro Rauhala (mirorauhala) (*Finnish*) +- diorama (*Italian*) +- AlexKoala (alexkoala) (*Korean*) +- Aswin C (officialcjunior) (*Malayalam*) +- Guillaume Turchini (orion78fr) (*French*) +- Ganesh D (auntgd) (*Marathi*) +- dragnucs2 (*Arabic*) +- Ryan Ho (koungho) (*Chinese Traditional*) +- Pedro Henrique (exploronauta) (*Portuguese, Brazilian*) +- Tejas Harad (h_tejas) (*Marathi*) +- Vasanthan (vasanthan) (*Tamil*) +- ç¡«é…¸é¶ (acid_chicken) (*Japanese*) +- clarmin b8 (clarminb8) (*Sorani (Kurdish)*) +- manukp (*Malayalam*) +- psymyn (*Hebrew*) +- earth dweller (sanethoughtyt) (*Marathi*) +- meijerivoi (toilet) (*Finnish*) +- essaar (*Tamil*) +- serubeena (*Swedish*) +- Karol Kosek (krkkPL) (*Polish*) +- Rintan (*Japanese*) +- valarivan (*Tamil*) +- Hernik (hernik27) (*Czech*) +- Sebastián Andil (Selrond) (*Slovak*) +- Hinaloe (hinaloe) (*Japanese*) - filippodb (*Italian*) +- KEINOS (*Japanese*) +- Balázs Meskó (meskobalazs) (*Hungarian*) +- Bottle (suryasalem2010) (*Tamil*) - JzshAC (*Chinese Simplified*) -- Rintan1 (*Japanese*) -- Antillion (*Spanish*) +- Wrya ali (John12) (*Sorani (Kurdish)*) +- Khóo (khootiatling) (*Chinese Traditional*) +- Steven Tappert (sammy8806) (*German*) +- Antillion (antillion99) (*Spanish*) +- Pukima (Pukimaa) (*German*) +- Reg3xp (*Persian*) - hiphipvargas (*Portuguese*) -- Ch. (*Korean*) +- gowthamanb (*Tamil*) +- Ch. (sftblw) (*Korean*) +- Jeff Huang (s8321414) (*Chinese Traditional*) +- Arttu Ylhävuori (arttu.ylhavuori) (*Finnish*) - tctovsli (*Norwegian Nynorsk*) +- Timo Tijhof (Krinkle) (*Dutch*) +- Yamagishi Kazutoshi (ykzts) (*Japanese, Icelandic, Sorani (Kurdish)*) - vjasiegd (*Polish*) -- SamitiMed (*Thai*) +- SamitiMed (samiti3d) (*Thai*) +- Rekan Adl (rekan-adl1) (*Sorani (Kurdish)*) - umelard (*Hebrew*) -- ç¡«é…¸é¶ (*Japanese*) -- Adrián Lattes (*Spanish*) -- Hinaloe (*Japanese*) -- Renato "Lond" Cerqueira (*Portuguese, Brazilian*) +- Antara2Cinta (Se7enTime) (*Indonesian*) +- VSx86 (*Russian*) +- Daniel Dimitrov (danny-dimitrov) (*Bulgarian*) - parnikkapore (*Thai*) -- Marcin MikoÅ‚ajczak (*Polish*) -- 森ã®åリスã®ãƒŸãƒ¼ã‚³ã®å¤§å†’険 (*Japanese*) -- Marcepanek_ (*Polish*) -- Sahak Petrosyan (*Armenian*) -- Daniel Dimitrov (*Bulgarian*) -- Hugh Liu (*Chinese Simplified*) -- Rakino (*Chinese Simplified*) +- mynameismonkey (*Welsh*) +- Sherwan Othman (sherwanothman11) (*Sorani (Kurdish)*) +- Yassine Aït-El-Mouden (yaitelmouden) (*Standard Moroccan Tamazight*) +- SKELET (*Danish*) +- Mo_der Steven (SakuraPuare) (*Chinese Simplified*) +- Fei Yang (Fei1Yang) (*Chinese Traditional*) +- ALEM FARID (faridatcemlulaqbayli) (*Kabyle*) +- enipra (*Armenian*) +- musix (*Persian*) +- Renato "Lond" Cerqueira (renatolond) (*Portuguese, Brazilian*) +- ギャラ (gyara) (*Japanese, Chinese Simplified*) +- Hougo (hougo) (*French*) +- ybardapurkar (*Marathi*) +- Adrián Lattes (haztecaso) (*Spanish*) +- TracyJacks (*Chinese Simplified*) +- rasheedgm (*Kannada*) +- GatoOscuro (*Spanish*) +- mecqor labi (mecqorlabi) (*Persian*) +- Belkacem Mohammed (belkacem77) (*Kabyle*) +- Navjot Singh (nspeaks) (*Hindi*) +- omquylzu (*Latvian*) +- Ozai (*German*) +- Sahak Petrosyan (petrosyan) (*Armenian*) +- siamano (*Thai, Esperanto*) +- Viorel-Cătălin RăpiÈ›eanu (rapiteanu) (*Romanian*) +- Siddhartha Sarathi Basu (quinoa_biryani) (*Bengali*) +- Pachara Chantawong (pachara2202) (*Thai*) +- mkljczk (*Polish*) +- Skew (noan.perrot) (*French*) +- Zijian Zhao (jobs2512821228) (*Chinese Simplified*) +- turtle836 (*German*) +- Guru Prasath Anandapadmanaban (guruprasath) (*Tamil*) +- Lamin (laminne) (*Japanese*) +- Marcepanek_ (thekingmarcepan) (*Polish*) +- Feruz Oripov (FeruzOripov) (*Russian*) +- Yann Aguettaz (yann-a) (*French*) +- Mick Onio (xgc.redes) (*Asturian*) +- Tianqi Zhang (tina.zhang040609) (*Chinese Simplified*) +- Malik Mann (dermalikmann) (*German*) +- dadosch (*German*) +- r3dsp1 (*Chinese Traditional, Hong Kong*) +- padulafacundo (*Spanish*) +- hg6 (*Hindi*) +- Orlando Murcio (Atos20) (*Spanish, Mexico*) +- piupiupiudiu (*Chinese Simplified*) +- shdy (*German*) +- Padraic Calpin (padraic-padraic) (*Slovenian*) +- Ильзира Рахматуллина (rahmatullinailzira53) (*Tatar*) +- cenegd (*Chinese Simplified*) +- Hugh Liu (youloveonlymeh) (*Chinese Simplified*) +- Pixelcode (realpixelcode) (*German*) +- Yogesh K S (yogi) (*Kannada*) +- Rakino (rakino) (*Chinese Simplified*) +- Miquel Sabaté Solà (mssola) (*Catalan*) +- AmazighNM (*Kabyle*) +- Jothipazhani Nagarajan (jothipazhani.n) (*Tamil*) +- Clash Clans (KURD12345) (*Sorani (Kurdish)*) +- hallomaurits (*Dutch*) +- alnd hezh (alndhezh) (*Sorani (Kurdish)*) +- Solid Rhino (SolidRhino) (*Dutch*) +- k_taka (peaceroad) (*Japanese*) +- Hallo Abdullah (hallo_hamza12) (*Sorani (Kurdish)*) - hussama (*Portuguese, Brazilian*) -- ThibG (*French*) +- Sébastien Feugère (smonff) (*French*) +- 林水溶 (shuiRong) (*Chinese Simplified*) +- eichkat3r (*German*) +- OminousCry (*Russian*) - SnDer (*Dutch*) - PifyZ (*French*) -- eichkat3r (*German*) -- Karol Kosek (*Polish*) -- Akarshan Biswas (*Bengali*) -- Tradjincal (*French*) -- Steven Tappert (*German*) -- sergioaraujo1 (*Portuguese, Brazilian*) +- Tom_ (*Czech*) +- Tagada (Tagadda) (*French*) +- shafouz (*Portuguese, Brazilian*) +- Kahina Mess (K_hina) (*Kabyle*) +- Nathaël Noguès (NatNgs) (*French*) +- Kk (kishorkumara3) (*Kannada*) +- Swati Sani (swatisani) (*Urdu (Pakistan)*) +- Shrinivasan T (tshrinivasan) (*Tamil*) +- ã•ã£ã‹ã‚Šã‚“ã«ãƒ¼ã•ã‚“ (saccharin23) (*Japanese*) +- 夜楓Yoka (Yoka2627) (*Chinese Simplified*) +- Daniel M. (daniconil) (*Catalan*) +- Vikatakavi (*Kannada*) +- SusVersiva (*Catalan*) +- Tradjincal (tradjincal) (*French*) +- pullopen (*Chinese Simplified*) +- Robin van der Vliet (RobinvanderVliet) (*Esperanto*) +- Zinkokooo (*Basque*) - mmokhi (*Persian*) -- fedot (*Russian*) +- Livingston Samuel (livingston) (*Tamil*) +- prabhjot (*Hindi*) +- sergioaraujo1 (*Portuguese, Brazilian*) +- CyberAmoeba (pseudoobscura) (*Chinese Simplified*) +- tsundoker (*Malayalam*) - skaaarrr (*German*) -- JackXu (*Chinese Simplified*) -- Lukas Fülling (*German*) -- Zoé BÅ‘le (*German*) +- Ricardo Colin (rysard) (*Spanish*) +- mkljczk (mykylyjczyk) (*Polish*) +- Philipp Fischbeck (PFischbeck) (*German*) +- fedot (*Russian*) +- Paz Galindo (paz.almendra.g) (*Spanish*) +- GaggiX (*Italian*) +- ralozkolya (*Georgian*) +- Zoé BÅ‘le (zoe1337) (*German*) +- Lukas Fülling (lfuelling) (*German*) +- JackXu (Merman-Jack) (*Chinese Simplified*) +- Aymeric (AymBroussier) (*French*) +- Anoop (anoopp) (*Malayalam*) +- pezcurrel (*Italian*) - Dremski (*Bulgarian*) -- tamaina (*Japanese*) +- Xurxo Guerra (xguerrap) (*Galician*) +- mashirozx (*Chinese Simplified*) +- Albatroz Jeremias (albjeremias) (*Portuguese*) +- Samir Tighzert (samir_t7) (*Kabyle*) +- Apple (blackteaovo) (*Chinese Simplified*) +- Nocta (*French*) - OpenAlgeria (*Arabic*) +- tamaina (*Japanese*) +- abidin toumi (Zet24) (*Arabic*) +- xpac1985 (xpac) (*German*) +- Kaede (kaedech) (*Japanese*) +- ÀŘǾŚ PÀŚĦÀà (arospashai) (*Sorani (Kurdish)*) +- Matias Lavik (matiaslavik) (*Norwegian Nynorsk*) +- smedvedev (*Russian*) +- mikel (mikelalas) (*Spanish*) +- Doug (douglasalvespe) (*Portuguese, Brazilian*) +- Trond Boksasp (boksasp) (*Norwegian*) +- Fleva (*Sardinian*) +- Mohammad Adnan Mahmood (adnanmig) (*Arabic*) +- Sais Lakshmanan (Saislakshmanan) (*Tamil*) +- Amith Raj Shetty (amithraj1989) (*Kannada*) +- random_person (*Spanish*) +- djoerd (*Dutch*) +- Baban Abdulrahman (baban.abdulrehman) (*Sorani (Kurdish)*) +- ebrezhoneg (*Breton*) +- dashty (*Sorani (Kurdish)*) +- Salh_haji6 (*Sorani (Kurdish)*) +- Amir Kurdo (kuraking202) (*Sorani (Kurdish)*) +- ãŠã• (osapon) (*Japanese*) +- Ranj A Abdulqadir (RanjAhmed) (*Sorani (Kurdish)*) +- umonaca (*Chinese Simplified*) +- Bartek FijaÅ‚kowski (brateq) (*Polish*) +- tateisu (*Japanese*) +- centumix (*Japanese*) +- Jari Ronkainen (ronchaine) (*Finnish*) +- SavarÃn Electrográfico Marmota Intergalactica (herrero.maty) (*Spanish*) +- Torsten Högel (torstenhoegel) (*German*) +- Abijeet Patro (Abijeet) (*Basque*) +- Ãcs Zoltán (acszoltan111) (*Hungarian*) +- Benjamin Cobb (benjamincobb) (*German*) +- waweic (*German*) +- Aries (orlea) (*Japanese*) +- silverscat_3 (SilversCat) (*Japanese*) +- kavitha129 (*Tamil*) +- dcapillae (*Spanish*) +- SamOak (*Portuguese, Brazilian*) +- capiscuas (*Spanish*) +- NeverMine17 (*Russian*) +- Nithya Mary (nithyamary25) (*Tamil*) +- t_aus_m (*German*) +- dobrado (*Portuguese, Brazilian*) +- Hannah (Aniqueper1) (*Chinese Simplified*) +- Jiniux (*Italian*) +- 于晚霞 (xissshawww) (*Chinese Simplified*) diff --git a/Aptfile b/Aptfile index 0a01fa24bdf07b4f073b65fb5c95044bdd7e1181..419d159ef6d64f5386de0092e3e546c0f457edb8 100644 --- a/Aptfile +++ b/Aptfile @@ -5,7 +5,6 @@ libidn11 libidn11-dev libpq-dev libprotobuf-dev -libssl-dev libxdamage1 libxfixes3 protobuf-compiler diff --git a/CHANGELOG.md b/CHANGELOG.md index 348d1cefc25948117a429d72d2a1fa24609f2f57..8d749c255c3f30a48c350ae3031fd4d626f77137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,238 @@ Changelog All notable changes to this project will be documented in this file. -## Unreleased +## [3.3.0] - 2020-12-27 +### Added + +- **Add hotkeys for audio/video control in web UI** ([Gargron](https://github.com/tootsuite/mastodon/pull/15158), [Gargron](https://github.com/tootsuite/mastodon/pull/15198)) + - `Space` and `k` to toggle playback + - `m` to toggle mute + - `f` to toggle fullscreen + - `j` and `l` to go back and forward by 10 seconds + - `.` and `,` to go back and forward by a frame (video only) +- Add expand/compress button on media modal in web UI ([mashirozx](https://github.com/tootsuite/mastodon/pull/15068), [mashirozx](https://github.com/tootsuite/mastodon/pull/15088), [mashirozx](https://github.com/tootsuite/mastodon/pull/15094)) +- Add border around 🕺 emoji in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14769)) +- Add border around 🞠emoji in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14712)) +- Add home link to the getting started column when home isn't mounted ([ThibG](https://github.com/tootsuite/mastodon/pull/14707)) +- Add option to disable swiping motions across the web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13885)) +- **Add pop-out player for audio/video in web UI** ([Gargron](https://github.com/tootsuite/mastodon/pull/14870), [Gargron](https://github.com/tootsuite/mastodon/pull/15157), [Gargron](https://github.com/tootsuite/mastodon/pull/14915), [noellabo](https://github.com/tootsuite/mastodon/pull/15309)) + - Continue watching/listening when you scroll away + - Action bar to interact with/open toot from the pop-out player +- Add unread notification markers in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14818), [ThibG](https://github.com/tootsuite/mastodon/pull/14960), [ThibG](https://github.com/tootsuite/mastodon/pull/14954), [noellabo](https://github.com/tootsuite/mastodon/pull/14897), [noellabo](https://github.com/tootsuite/mastodon/pull/14907)) +- Add paragraph about browser add-ons when encountering errors in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14801)) +- Add import and export for bookmarks ([ThibG](https://github.com/tootsuite/mastodon/pull/14956)) +- Add cache buster feature for media files ([Gargron](https://github.com/tootsuite/mastodon/pull/15155)) + - If you have a proxy cache in front of object storage, deleted files will persist until the cache expires + - If enabled, cache buster will make a special request to the proxy to signal a cache reset +- Add duration option to the mute function ([aquarla](https://github.com/tootsuite/mastodon/pull/13831)) +- Add replies policy option to the list function ([ThibG](https://github.com/tootsuite/mastodon/pull/9205), [trwnh](https://github.com/tootsuite/mastodon/pull/15304)) +- Add `og:published_time` OpenGraph tags on toots ([nornagon](https://github.com/tootsuite/mastodon/pull/14865)) +- **Add option to be notified when a followed user posts** ([Gargron](https://github.com/tootsuite/mastodon/pull/13546), [ThibG](https://github.com/tootsuite/mastodon/pull/14896), [Gargron](https://github.com/tootsuite/mastodon/pull/14822)) + - If you don't want to miss a toot, click the bell button! +- Add client-side validation in password change forms ([ThibG](https://github.com/tootsuite/mastodon/pull/14564)) +- Add client-side validation in the registration form ([ThibG](https://github.com/tootsuite/mastodon/pull/14560), [ThibG](https://github.com/tootsuite/mastodon/pull/14599)) +- Add support for Gemini URLs ([joshleeb](https://github.com/tootsuite/mastodon/pull/15013)) +- Add app shortcuts to web app manifest ([mkljczk](https://github.com/tootsuite/mastodon/pull/15234)) +- Add WebAuthn as an alternative 2FA method ([santiagorodriguez96](https://github.com/tootsuite/mastodon/pull/14466), [jiikko](https://github.com/tootsuite/mastodon/pull/14806)) +- Add honeypot fields and minimum fill-out time for sign-up form ([ThibG](https://github.com/tootsuite/mastodon/pull/15276)) +- Add icon for mutual relationships in relationship manager ([noellabo](https://github.com/tootsuite/mastodon/pull/15149)) +- Add follow selected followers button in relationship manager ([noellabo](https://github.com/tootsuite/mastodon/pull/15148)) +- **Add subresource integrity for JS and CSS assets** ([Gargron](https://github.com/tootsuite/mastodon/pull/15096)) + - If you use a CDN for static assets (JavaScript, CSS, and so on), you have to trust that the CDN does not modify the assets maliciously + - Subresource integrity compares server-generated asset digests with what's actually served from the CDN and prevents such attacks +- Add `ku`, `sa`, `sc`, `zgh` to available locales ([ykzts](https://github.com/tootsuite/mastodon/pull/15138)) +- Add ability to force an account to mark media as sensitive ([noellabo](https://github.com/tootsuite/mastodon/pull/14361)) +- **Add ability to block access or limit sign-ups from chosen IPs** ([Gargron](https://github.com/tootsuite/mastodon/pull/14963), [ThibG](https://github.com/tootsuite/mastodon/pull/15263)) + - Add rules for IPs or CIDR ranges that automatically expire after a configurable amount of time + - Choose the severity of the rule, either blocking all access or merely limiting sign-ups +- **Add support for reversible suspensions through ActivityPub** ([Gargron](https://github.com/tootsuite/mastodon/pull/14989)) + - Servers can signal that one of their accounts has been suspended + - During suspension, the account can only delete its own content + - A reversal of the suspension can be signalled the same way + - A local suspension always overrides a remote one +- Add indication to admin UI of whether a report has been forwarded ([ThibG](https://github.com/tootsuite/mastodon/pull/13237)) +- Add display of reasons for joining of an account in admin UI ([mashirozx](https://github.com/tootsuite/mastodon/pull/15265)) +- Add option to obfuscate domain name in public list of domain blocks ([Gargron](https://github.com/tootsuite/mastodon/pull/15355)) +- Add option to make reasons for joining required on sign-up ([ThibG](https://github.com/tootsuite/mastodon/pull/15326), [ThibG](https://github.com/tootsuite/mastodon/pull/15358), [ThibG](https://github.com/tootsuite/mastodon/pull/15385), [ThibG](https://github.com/tootsuite/mastodon/pull/15405)) +- Add ActivityPub follower synchronization mechanism ([ThibG](https://github.com/tootsuite/mastodon/pull/14510), [ThibG](https://github.com/tootsuite/mastodon/pull/15026)) +- Add outbox attribute to instance actor ([ThibG](https://github.com/tootsuite/mastodon/pull/14721)) +- Add featured hashtags as an ActivityPub collection ([Gargron](https://github.com/tootsuite/mastodon/pull/11595), [noellabo](https://github.com/tootsuite/mastodon/pull/15277)) +- Add support for dereferencing objects through bearcaps ([Gargron](https://github.com/tootsuite/mastodon/pull/14683), [noellabo](https://github.com/tootsuite/mastodon/pull/14981)) +- Add `S3_READ_TIMEOUT` environment variable ([tateisu](https://github.com/tootsuite/mastodon/pull/14952)) +- Add `ALLOWED_PRIVATE_ADDRESSES` environment variable ([ThibG](https://github.com/tootsuite/mastodon/pull/14722)) +- Add `--fix-permissions` option to `tootctl media remove-orphans` ([Gargron](https://github.com/tootsuite/mastodon/pull/14383), [uist1idrju3i](https://github.com/tootsuite/mastodon/pull/14715)) +- Add `tootctl accounts merge` ([Gargron](https://github.com/tootsuite/mastodon/pull/15201), [ThibG](https://github.com/tootsuite/mastodon/pull/15264), [ThibG](https://github.com/tootsuite/mastodon/pull/15256)) + - Has someone changed their domain or subdomain thereby creating two accounts where there should be one? + - This command will fix it on your end +- Add `tootctl maintenance fix-duplicates` ([ThibG](https://github.com/tootsuite/mastodon/pull/14860), [Gargron](https://github.com/tootsuite/mastodon/pull/15223), [ThibG](https://github.com/tootsuite/mastodon/pull/15373)) + - Index corruption in the database? + - This command is for you +- **Add support for managing multiple stream subscriptions in a single connection** ([Gargron](https://github.com/tootsuite/mastodon/pull/14524), [Gargron](https://github.com/tootsuite/mastodon/pull/14566), [mfmfuyu](https://github.com/tootsuite/mastodon/pull/14859), [zunda](https://github.com/tootsuite/mastodon/pull/14608)) + - Previously, getting live updates for multiple timelines required opening a HTTP or WebSocket connection for each + - More connections means more resource consumption on both ends, not to mention the (ever so slight) delay when establishing a new connection + - Now, with just a single WebSocket connection you can subscribe and unsubscribe to and from multiple streams +- Add support for limiting results by both `min_id` and `max_id` at the same time in REST API ([tateisu](https://github.com/tootsuite/mastodon/pull/14776)) +- Add `GET /api/v1/accounts/:id/featured_tags` to REST API ([noellabo](https://github.com/tootsuite/mastodon/pull/11817), [noellabo](https://github.com/tootsuite/mastodon/pull/15270)) +- Add stoplight for object storage failures, return HTTP 503 in REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/13043)) +- Add optional `tootctl remove media` cronjob in Helm chart ([dunn](https://github.com/tootsuite/mastodon/pull/14396)) +- Add clean error message when `RAILS_ENV` is unset ([ThibG](https://github.com/tootsuite/mastodon/pull/15381)) + +### Changed + +- **Change media modals look in web UI** ([Gargron](https://github.com/tootsuite/mastodon/pull/15217), [Gargron](https://github.com/tootsuite/mastodon/pull/15221), [Gargron](https://github.com/tootsuite/mastodon/pull/15284), [Gargron](https://github.com/tootsuite/mastodon/pull/15283), [Kjwon15](https://github.com/tootsuite/mastodon/pull/15308), [noellabo](https://github.com/tootsuite/mastodon/pull/15305), [ThibG](https://github.com/tootsuite/mastodon/pull/15417)) + - Background of the overlay matches the color of the image + - Action bar to interact with or open the toot from the modal +- Change order of announcements in admin UI to be newest-first ([ThibG](https://github.com/tootsuite/mastodon/pull/15091)) +- **Change account suspensions to be reversible by default** ([Gargron](https://github.com/tootsuite/mastodon/pull/14726), [ThibG](https://github.com/tootsuite/mastodon/pull/15152), [ThibG](https://github.com/tootsuite/mastodon/pull/15106), [ThibG](https://github.com/tootsuite/mastodon/pull/15100), [ThibG](https://github.com/tootsuite/mastodon/pull/15099), [noellabo](https://github.com/tootsuite/mastodon/pull/14855), [ThibG](https://github.com/tootsuite/mastodon/pull/15380), [Gargron](https://github.com/tootsuite/mastodon/pull/15420), [Gargron](https://github.com/tootsuite/mastodon/pull/15414)) + - Suspensions no longer equal deletions + - A suspended account can be unsuspended with minimal consequences for 30 days + - Immediate deletion of data is still available as an explicit option + - Suspended accounts can request an archive of their data through the UI +- Change REST API to return empty data for suspended accounts (14765) +- Change web UI to show empty profile for suspended accounts ([Gargron](https://github.com/tootsuite/mastodon/pull/14766), [Gargron](https://github.com/tootsuite/mastodon/pull/15345)) +- Change featured hashtag suggestions to be recently used instead of most used ([abcang](https://github.com/tootsuite/mastodon/pull/14760)) +- Change direct toots to appear in the home feed again ([Gargron](https://github.com/tootsuite/mastodon/pull/14711), [ThibG](https://github.com/tootsuite/mastodon/pull/15182), [noellabo](https://github.com/tootsuite/mastodon/pull/14727)) + - Return to treating all toots the same instead of trying to retrofit direct visibility into an instant messaging model +- Change email address validation to return more specific errors ([ThibG](https://github.com/tootsuite/mastodon/pull/14565)) +- Change HTTP signature requirements to include `Digest` header on `POST` requests ([ThibG](https://github.com/tootsuite/mastodon/pull/15069)) +- Change click area of video/audio player buttons to be bigger in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/15049)) +- Change order of filters by alphabetic by "keyword or phrase" ([ariasuni](https://github.com/tootsuite/mastodon/pull/15050)) +- Change suspension of remote accounts to also undo outgoing follows ([ThibG](https://github.com/tootsuite/mastodon/pull/15188)) +- Change string "Home" to "Home and lists" in the filter creation screen ([ariasuni](https://github.com/tootsuite/mastodon/pull/15139)) +- Change string "Boost to original audience" to "Boost with original visibility" in web UI ([3n-k1](https://github.com/tootsuite/mastodon/pull/14598)) +- Change string "Show more" to "Show newer" and "Show older" on public pages ([ariasuni](https://github.com/tootsuite/mastodon/pull/15052)) +- Change order of announcements to be reverse chronological in web UI ([dariusk](https://github.com/tootsuite/mastodon/pull/15065), [dariusk](https://github.com/tootsuite/mastodon/pull/15070)) +- Change RTL detection to rely on unicode-bidi paragraph by paragraph in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/14573)) +- Change visibility icon next to timestamp to be clickable in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/15053), [mayaeh](https://github.com/tootsuite/mastodon/pull/15055)) +- Change public thread view to hide "Show thread" link ([ThibG](https://github.com/tootsuite/mastodon/pull/15266)) +- Change number format on about page from full to shortened ([Gargron](https://github.com/tootsuite/mastodon/pull/15327)) +- Change how scheduled tasks run in multi-process environments ([noellabo](https://github.com/tootsuite/mastodon/pull/15314)) + - New dedicated queue `scheduler` + - Runs by default when Sidekiq is executed with no options + - Has to be added manually in a multi-process environment + +### Removed + +- Remove fade-in animation from modals in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/15199)) +- Remove auto-redirect to direct messages in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/15142)) +- Remove obsolete IndexedDB operations from web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/14730)) +- Remove dependency on unused and unmaintained http_parser.rb gem ([ThibG](https://github.com/tootsuite/mastodon/pull/14574)) + +### Fixed + +- Fix layout on about page when contact account has a long username ([ThibG](https://github.com/tootsuite/mastodon/pull/15357)) +- Fix follow limit preventing re-following of a moved account ([Gargron](https://github.com/tootsuite/mastodon/pull/14207), [ThibG](https://github.com/tootsuite/mastodon/pull/15384)) +- **Fix deletes not reaching every server that interacted with toot** ([Gargron](https://github.com/tootsuite/mastodon/pull/15200)) + - Previously, delete of a toot would be primarily sent to the followers of its author, people mentioned in the toot, and people who reblogged the toot + - Now, additionally, it is ensured that it is sent to people who replied to it, favourited it, and to the person it replies to even if that person is not mentioned +- Fix resolving an account through its non-canonical form (i.e. alternate domain) ([ThibG](https://github.com/tootsuite/mastodon/pull/15187)) +- Fix sending redundant ActivityPub events when processing remote account deletion ([ThibG](https://github.com/tootsuite/mastodon/pull/15104)) +- Fix Move handler not being triggered when failing to fetch target account ([ThibG](https://github.com/tootsuite/mastodon/pull/15107)) +- Fix downloading remote media files when server returns empty filename ([ThibG](https://github.com/tootsuite/mastodon/pull/14867)) +- Fix account processing failing because of large collections ([ThibG](https://github.com/tootsuite/mastodon/pull/15027)) +- Fix not being able to unfavorite toots one has lost access to ([ThibG](https://github.com/tootsuite/mastodon/pull/15192)) +- Fix not being able to unbookmark toots one has lost access to ([ThibG](https://github.com/tootsuite/mastodon/pull/14604)) +- Fix possible casing inconsistencies in hashtag search ([ThibG](https://github.com/tootsuite/mastodon/pull/14906)) +- Fix updating account counters when association is not yet created ([Gargron](https://github.com/tootsuite/mastodon/pull/15108)) +- Fix cookies not having a SameSite attribute ([Gargron](https://github.com/tootsuite/mastodon/pull/15098)) +- Fix poll ending notifications being created for each vote ([ThibG](https://github.com/tootsuite/mastodon/pull/15071)) +- Fix multiple boosts of a same toot erroneously appearing in TL ([ThibG](https://github.com/tootsuite/mastodon/pull/14759)) +- Fix asset builds not picking up `CDN_HOST` change ([ThibG](https://github.com/tootsuite/mastodon/pull/14381)) +- Fix desktop notifications permission prompt in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/14985), [Gargron](https://github.com/tootsuite/mastodon/pull/15141), [ThibG](https://github.com/tootsuite/mastodon/pull/13543), [ThibG](https://github.com/tootsuite/mastodon/pull/15176)) + - Some time ago, browsers added a requirement that desktop notification prompts could only be displayed in response to a user-generated event (such as a click) + - This means that for some time, users who haven't already given the permission before were not getting a prompt and as such were not receiving desktop notifications +- Fix "Mark media as sensitive" string not supporting pluralizations in other languages in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/15051)) +- Fix glitched image uploads when canvas read access is blocked in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/15180)) +- Fix some account gallery items having empty labels in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/15073)) +- Fix alt-key hotkeys activating while typing in a text field in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14942)) +- Fix wrong seek bar width on media player in web UI ([mfmfuyu](https://github.com/tootsuite/mastodon/pull/15060)) +- Fix logging out on mobile in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14901)) +- Fix wrong click area for GIFVs in media modal in web UI ([noellabo](https://github.com/tootsuite/mastodon/pull/14615)) +- Fix unreadable placeholder text color in high contrast theme in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/14803)) +- Fix scrolling issues when closing some dropdown menus in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14606)) +- Fix notification filter bar incorrectly filtering gaps in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14808)) +- Fix disabled boost icon being replaced by private boost icon on hover in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14456)) +- Fix hashtag detection in compose form being different to server-side in web UI ([kedamaDQ](https://github.com/tootsuite/mastodon/pull/14484), [ThibG](https://github.com/tootsuite/mastodon/pull/14513)) +- Fix home last read marker mishandling gaps in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14809)) +- Fix unnecessary re-rendering of various components when typing in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/15286)) +- Fix notifications being unnecessarily re-rendered in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/15312)) +- Fix column swiping animation logic in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/15301)) +- Fix inefficiency when fetching hashtag timeline ([noellabo](https://github.com/tootsuite/mastodon/pull/14861), [akihikodaki](https://github.com/tootsuite/mastodon/pull/14662)) +- Fix inefficiency when fetching bookmarks ([akihikodaki](https://github.com/tootsuite/mastodon/pull/14674)) +- Fix inefficiency when fetching favourites ([akihikodaki](https://github.com/tootsuite/mastodon/pull/14673)) +- Fix inefficiency when fetching media-only account timeline ([akihikodaki](https://github.com/tootsuite/mastodon/pull/14675)) +- Fix inefficieny when deleting accounts ([Gargron](https://github.com/tootsuite/mastodon/pull/15387), [ThibG](https://github.com/tootsuite/mastodon/pull/15409), [ThibG](https://github.com/tootsuite/mastodon/pull/15407), [ThibG](https://github.com/tootsuite/mastodon/pull/15408), [ThibG](https://github.com/tootsuite/mastodon/pull/15402), [ThibG](https://github.com/tootsuite/mastodon/pull/15416), [Gargron](https://github.com/tootsuite/mastodon/pull/15421)) +- Fix redundant query when processing batch actions on custom emojis ([niwatori24](https://github.com/tootsuite/mastodon/pull/14534)) +- Fix slow distinct queries where grouped queries are faster ([Gargron](https://github.com/tootsuite/mastodon/pull/15287)) +- Fix performance on instances list in admin UI ([Gargron](https://github.com/tootsuite/mastodon/pull/15282)) +- Fix server actor appearing in list of accounts in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14567)) +- Fix "bootstrap timeline accounts" toggle in site settings in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/15325)) +- Fix PostgreSQL secret name for cronjob in Helm chart ([metal3d](https://github.com/tootsuite/mastodon/pull/15072)) +- Fix Procfile not being compatible with herokuish ([acuteaura](https://github.com/tootsuite/mastodon/pull/12685)) +- Fix installation of tini being split into multiple steps in Dockerfile ([ryncsn](https://github.com/tootsuite/mastodon/pull/14686)) + +### Security + +- Fix streaming API allowing connections to persist after access token invalidation ([Gargron](https://github.com/tootsuite/mastodon/pull/15111)) +- Fix 2FA/sign-in token sessions being valid after password change ([Gargron](https://github.com/tootsuite/mastodon/pull/14802)) +- Fix resolving accounts sometimes creating duplicate records for a given ActivityPub identifier ([ThibG](https://github.com/tootsuite/mastodon/pull/15364)) + +## [3.2.2] - 2020-12-19 +### Added + +- Add `tootctl maintenance fix-duplicates` ([ThibG](https://github.com/tootsuite/mastodon/pull/14860), [Gargron](https://github.com/tootsuite/mastodon/pull/15223)) + - Index corruption in the database? + - This command is for you + +### Removed + +- Remove dependency on unused and unmaintained http_parser.rb gem ([ThibG](https://github.com/tootsuite/mastodon/pull/14574)) + +### Fixed + +- Fix Move handler not being triggered when failing to fetch target account ([ThibG](https://github.com/tootsuite/mastodon/pull/15107)) +- Fix downloading remote media files when server returns empty filename ([ThibG](https://github.com/tootsuite/mastodon/pull/14867)) +- Fix possible casing inconsistencies in hashtag search ([ThibG](https://github.com/tootsuite/mastodon/pull/14906)) +- Fix updating account counters when association is not yet created ([Gargron](https://github.com/tootsuite/mastodon/pull/15108)) +- Fix account processing failing because of large collections ([ThibG](https://github.com/tootsuite/mastodon/pull/15027)) +- Fix resolving an account through its non-canonical form (i.e. alternate domain) ([ThibG](https://github.com/tootsuite/mastodon/pull/15187)) +- Fix slow distinct queries where grouped queries are faster ([Gargron](https://github.com/tootsuite/mastodon/pull/15287)) + +### Security + +- Fix 2FA/sign-in token sessions being valid after password change ([Gargron](https://github.com/tootsuite/mastodon/pull/14802)) +- Fix resolving accounts sometimes creating duplicate records for a given ActivityPub identifier ([ThibG](https://github.com/tootsuite/mastodon/pull/15364)) + +## [3.2.1] - 2020-10-19 +### Added + +- Add support for latest HTTP Signatures spec draft ([ThibG](https://github.com/tootsuite/mastodon/pull/14556)) +- Add support for inlined objects in ActivityPub `to`/`cc` ([ThibG](https://github.com/tootsuite/mastodon/pull/14514)) + +### Changed + +- Change actors to not be served at all without authentication in limited federation mode ([ThibG](https://github.com/tootsuite/mastodon/pull/14800)) + - Previously, a bare version of an actor was served when not authenticated, i.e. username and public key + - Because all actor fetch requests are signed using a separate system actor, that is no longer required + +### Fixed + +- Fix `tootctl media` commands not recognizing very large IDs ([ThibG](https://github.com/tootsuite/mastodon/pull/14536)) +- Fix crash when failing to load emoji picker in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14525)) +- Fix contrast requirements in thumbnail color extraction ([ThibG](https://github.com/tootsuite/mastodon/pull/14464)) +- Fix audio/video player not using `CDN_HOST` on public pages ([ThibG](https://github.com/tootsuite/mastodon/pull/14486)) +- Fix private boost icon not being used on public pages ([OmmyZhang](https://github.com/tootsuite/mastodon/pull/14471)) +- Fix audio player on Safari in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14485), [ThibG](https://github.com/tootsuite/mastodon/pull/14465)) +- Fix dereferencing remote statuses not using the correct account for signature when receiving a targeted inbox delivery ([ThibG](https://github.com/tootsuite/mastodon/pull/14656)) +- Fix nil error in `tootctl media remove` ([noellabo](https://github.com/tootsuite/mastodon/pull/14657)) +- Fix videos with near-60 fps being rejected ([Gargron](https://github.com/tootsuite/mastodon/pull/14684)) +- Fix reported statuses not being included in warning e-mail ([Gargron](https://github.com/tootsuite/mastodon/pull/14778)) +- Fix `Reject` activities of `Follow` objects not correctly destroying a follow relationship ([ThibG](https://github.com/tootsuite/mastodon/pull/14479)) +- Fix inefficiencies in fan-out-on-write service ([Gargron](https://github.com/tootsuite/mastodon/pull/14682), [noellabo](https://github.com/tootsuite/mastodon/pull/14709)) +- Fix timeout errors when trying to webfinger some IPv6 configurations ([Gargron](https://github.com/tootsuite/mastodon/pull/14919)) +- Fix files served as `application/octet-stream` being rejected without attempting mime type detection ([ThibG](https://github.com/tootsuite/mastodon/pull/14452)) + +## [3.2.0] - 2020-07-27 ### Added - Add `SMTP_SSL` environment variable ([OmmyZhang](https://github.com/tootsuite/mastodon/pull/14309)) @@ -29,7 +260,7 @@ All notable changes to this project will be documented in this file. - New REST API: `POST /api/v1/accounts/:id/note` with `comment` param - The Relationship entity in REST API has a new `note` attribute - Add Helm chart ([dunn](https://github.com/tootsuite/mastodon/pull/14090), [dunn](https://github.com/tootsuite/mastodon/pull/14256), [dunn](https://github.com/tootsuite/mastodon/pull/14245)) -- **Add customizable thumbnails for audio and video attachments** ([Gargron](https://github.com/tootsuite/mastodon/pull/14145), [Gargron](https://github.com/tootsuite/mastodon/pull/14244), [Gargron](https://github.com/tootsuite/mastodon/pull/14273), [Gargron](https://github.com/tootsuite/mastodon/pull/14203), [ThibG](https://github.com/tootsuite/mastodon/pull/14255), [ThibG](https://github.com/tootsuite/mastodon/pull/14306)) +- **Add customizable thumbnails for audio and video attachments** ([Gargron](https://github.com/tootsuite/mastodon/pull/14145), [Gargron](https://github.com/tootsuite/mastodon/pull/14244), [Gargron](https://github.com/tootsuite/mastodon/pull/14273), [Gargron](https://github.com/tootsuite/mastodon/pull/14203), [ThibG](https://github.com/tootsuite/mastodon/pull/14255), [ThibG](https://github.com/tootsuite/mastodon/pull/14306), [noellabo](https://github.com/tootsuite/mastodon/pull/14358), [noellabo](https://github.com/tootsuite/mastodon/pull/14357)) - Metadata (album, artist, etc) is no longer stripped from audio files - Album art is automatically extracted from audio files - Thumbnail can be manually uploaded for both audio and video attachments @@ -37,6 +268,7 @@ All notable changes to this project will be documented in this file. - On `POST /api/v1/media` and `POST /api/v2/media` - And on `PUT /api/v1/media/:id` - ActivityPub representation of media attachments represents custom thumbnails with an `icon` attribute + - The Media Attachment entity in REST API now has a `preview_remote_url` to its `preview_url`, equivalent to `remote_url` to its `url` - **Add color extraction for thumbnails** ([Gargron](https://github.com/tootsuite/mastodon/pull/14209), [ThibG](https://github.com/tootsuite/mastodon/pull/14264)) - The `meta` attribute on the Media Attachment entity in REST API can now have a `colors` attribute which in turn contains three hex colors: `background`, `foreground`, and `accent` - The background color is chosen from the most dominant color around the edges of the thumbnail @@ -48,6 +280,9 @@ All notable changes to this project will be documented in this file. - Add `tootctl email_domain_blocks` ([tateisu](https://github.com/tootsuite/mastodon/pull/13589), [Gargron](https://github.com/tootsuite/mastodon/pull/14147)) - Add "Add new domain block" to header of federation page in admin UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13934)) - Add ability to keep emoji picker open with ctrl+click in web UI ([bclindner](https://github.com/tootsuite/mastodon/pull/13896), [noellabo](https://github.com/tootsuite/mastodon/pull/14096)) +- Add custom icon for private boosts in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14380)) +- Add support for Create and Update activities that don't inline objects in ActivityPub ([ThibG](https://github.com/tootsuite/mastodon/pull/14359)) +- Add support for Undo activities that don't inline activities in ActivityPub ([ThibG](https://github.com/tootsuite/mastodon/pull/14346)) ### Changed @@ -59,9 +294,9 @@ All notable changes to this project will be documented in this file. - Some websites may not render OpenGraph tags into HTML if that's not the case - Change behaviour to carry blocks over when someone migrates their followers ([ThibG](https://github.com/tootsuite/mastodon/pull/14144)) - Change volume control and download buttons in web UI ([Gargron](https://github.com/tootsuite/mastodon/pull/14122)) -- **Change design of audio players in web UI** ([Gargron](https://github.com/tootsuite/mastodon/pull/14095), [ThibG](https://github.com/tootsuite/mastodon/pull/14281), [Gargron](https://github.com/tootsuite/mastodon/pull/14282), [ThibG](https://github.com/tootsuite/mastodon/pull/14118), [Gargron](https://github.com/tootsuite/mastodon/pull/14199)) +- **Change design of audio players in web UI** ([Gargron](https://github.com/tootsuite/mastodon/pull/14095), [ThibG](https://github.com/tootsuite/mastodon/pull/14281), [Gargron](https://github.com/tootsuite/mastodon/pull/14282), [ThibG](https://github.com/tootsuite/mastodon/pull/14118), [Gargron](https://github.com/tootsuite/mastodon/pull/14199), [ThibG](https://github.com/tootsuite/mastodon/pull/14338)) - Change reply filter to never filter own toots in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14128)) -- Change boost button to no longer serve as visibility indicator in web UI ([noellabo](https://github.com/tootsuite/mastodon/pull/14132)) +- Change boost button to no longer serve as visibility indicator in web UI ([noellabo](https://github.com/tootsuite/mastodon/pull/14132), [ThibG](https://github.com/tootsuite/mastodon/pull/14373)) - Change contrast of flash messages ([cchoi12](https://github.com/tootsuite/mastodon/pull/13892)) - Change wording from "Hide media" to "Hide image/images" in web UI ([ariasuni](https://github.com/tootsuite/mastodon/pull/13834)) - Change appearence of settings pages to be more consistent ([ariasuni](https://github.com/tootsuite/mastodon/pull/13938)) @@ -69,6 +304,7 @@ All notable changes to this project will be documented in this file. - Change how badly contrasting emoji are rendered in web UI ([leo60228](https://github.com/tootsuite/mastodon/pull/13773), [ThibG](https://github.com/tootsuite/mastodon/pull/13772), [mfmfuyu](https://github.com/tootsuite/mastodon/pull/14020), [ThibG](https://github.com/tootsuite/mastodon/pull/14015)) - Change structure of unavailable content section on about page ([ariasuni](https://github.com/tootsuite/mastodon/pull/13930)) - Change behaviour to accept ActivityPub activities relayed through group actor ([noellabo](https://github.com/tootsuite/mastodon/pull/14279)) +- Change amount of processing retries for ActivityPub activities ([noellabo](https://github.com/tootsuite/mastodon/pull/14355)) ### Removed @@ -84,13 +320,18 @@ All notable changes to this project will be documented in this file. ### Fixed +- Fix `following` param not working when exact match is found in account search ([noellabo](https://github.com/tootsuite/mastodon/pull/14394)) +- Fix sometimes occuring duplicate mention notifications ([noellabo](https://github.com/tootsuite/mastodon/pull/14378)) +- Fix RSS feeds not being cachable ([ThibG](https://github.com/tootsuite/mastodon/pull/14368)) +- Fix lack of locking around processing of Announce activities in ActivityPub ([noellabo](https://github.com/tootsuite/mastodon/pull/14365)) +- Fix boosted toots from blocked account not being retroactively removed from TL ([ThibG](https://github.com/tootsuite/mastodon/pull/14339)) - Fix large shortened numbers (like 1.2K) using incorrect pluralization ([Sasha-Sorokin](https://github.com/tootsuite/mastodon/pull/14061)) - Fix streaming server trying to use empty password to connect to Redis when `REDIS_PASSWORD` is given but blank ([ThibG](https://github.com/tootsuite/mastodon/pull/14135)) - Fix being unable to unboost posts when blocked by their author ([ThibG](https://github.com/tootsuite/mastodon/pull/14308)) - Fix account domain block not properly unfollowing accounts from domain ([Gargron](https://github.com/tootsuite/mastodon/pull/14304)) - Fix removing a domain allow wiping known accounts in open federation mode ([ThibG](https://github.com/tootsuite/mastodon/pull/14298)) - Fix blocks and mutes pagination in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14275)) -- Fix new posts pushing down origin of opened dropdown in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14271)) +- Fix new posts pushing down origin of opened dropdown in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14271), [ThibG](https://github.com/tootsuite/mastodon/pull/14348)) - Fix timeline markers not being saved sometimes ([ThibG](https://github.com/tootsuite/mastodon/pull/13887), [ThibG](https://github.com/tootsuite/mastodon/pull/13889), [ThibG](https://github.com/tootsuite/mastodon/pull/14155)) - Fix CSV uploads being rejected ([noellabo](https://github.com/tootsuite/mastodon/pull/13835)) - Fix incompatibility with ElasticSearch 7.x ([noellabo](https://github.com/tootsuite/mastodon/pull/13828)) @@ -112,7 +353,7 @@ All notable changes to this project will be documented in this file. - Use circuit breakers to stop hitting unresponsive servers - Avoid hitting servers that are already known to be generally unavailable - Fix filters ignoring media descriptions ([BenLubar](https://github.com/tootsuite/mastodon/pull/13837)) -- Fix soem actions on custom emojis leading to cryptic errors in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13951)) +- Fix some actions on custom emojis leading to cryptic errors in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13951)) - Fix ActivityPub serialization of replies when some of them are URIs ([ThibG](https://github.com/tootsuite/mastodon/pull/13957)) - Fix `rake mastodon:setup` choking on environment variables containing `%` ([ThibG](https://github.com/tootsuite/mastodon/pull/13940)) - Fix account redirect confirmation message talking about moved followers ([ThibG](https://github.com/tootsuite/mastodon/pull/13950)) @@ -132,7 +373,7 @@ All notable changes to this project will be documented in this file. - Fix unapproved users being able to view profiles when in limited-federation mode *and* requiring approval for sign-ups ([ThibG](https://github.com/tootsuite/mastodon/pull/14093)) - Fix initial audio volume not corresponding to what's displayed in audio player in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14057)) - Fix timelines sometimes jumping when closing modals in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/14019)) -- Fix memory usage of downloading remote files ([Gargron](https://github.com/tootsuite/mastodon/pull/14184), [Gargron](https://github.com/tootsuite/mastodon/pull/14181)) +- Fix memory usage of downloading remote files ([Gargron](https://github.com/tootsuite/mastodon/pull/14184), [Gargron](https://github.com/tootsuite/mastodon/pull/14181), [noellabo](https://github.com/tootsuite/mastodon/pull/14356)) - Don't read entire file (up to 40 MB) into memory - Read and write it to temp file in small chunks - Fix inconsistent account header padding in web UI ([trwnh](https://github.com/tootsuite/mastodon/pull/14179)) @@ -146,14 +387,14 @@ All notable changes to this project will be documented in this file. - Only then proceed to start removing their data (slow) - Clear out media attachments in a separate worker (slow) -## [v3.1.5] - 2020-07-07 +## [3.1.5] - 2020-07-07 ### Security - Fix media attachment enumeration ([ThibG](https://github.com/tootsuite/mastodon/pull/14254)) - Change rate limits for various paths ([Gargron](https://github.com/tootsuite/mastodon/pull/14253)) - Fix other sessions not being logged out on password change ([Gargron](https://github.com/tootsuite/mastodon/pull/14252)) -## [v3.1.4] - 2020-05-14 +## [3.1.4] - 2020-05-14 ### Added - Add `vi` to available locales ([taicv](https://github.com/tootsuite/mastodon/pull/13542)) @@ -220,7 +461,7 @@ All notable changes to this project will be documented in this file. - For apps that self-register on behalf of every individual user (such as most mobile apps), this is a non-issue - The issue only affects developers of apps who are shared between multiple users, such as server-side apps like cross-posters -## [v3.1.3] - 2020-04-05 +## [3.1.3] - 2020-04-05 ### Added - Add ability to filter audit log in admin UI ([Gargron](https://github.com/tootsuite/mastodon/pull/13381)) diff --git a/Dockerfile b/Dockerfile index fa6abad5a1369081d3922a663db636cd27f6e10f..95d45bab427007e1e8fd2538ddc6dca229399927 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM ubuntu:20.04 as build-dep SHELL ["bash", "-c"] # Install Node v12 (LTS) -ENV NODE_VER="12.16.3" +ENV NODE_VER="12.20.0" RUN ARCH= && \ dpkgArch="$(dpkg --print-architecture)" && \ case "${dpkgArch##*-}" in \ @@ -36,10 +36,11 @@ RUN apt update && \ ./autogen.sh && \ ./configure --prefix=/opt/jemalloc && \ make -j$(nproc) > /dev/null && \ - make install_bin install_include install_lib + make install_bin install_include install_lib && \ + cd .. && rm -rf jemalloc-$JE_VER $JE_VER.tar.gz # Install Ruby -ENV RUBY_VER="2.6.6" +ENV RUBY_VER="2.7.2" ENV CPPFLAGS="-I/opt/jemalloc/include" ENV LDFLAGS="-L/opt/jemalloc/lib/" RUN apt update && \ @@ -56,7 +57,8 @@ RUN apt update && \ --disable-install-doc && \ ln -s /opt/jemalloc/lib/* /usr/lib/ && \ make -j$(nproc) > /dev/null && \ - make install + make install && \ + cd .. && rm -rf ruby-$RUBY_VER.tar.gz ruby-$RUBY_VER ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin" @@ -107,11 +109,14 @@ RUN apt -y --no-install-recommends install \ rm -rf /var/lib/apt/lists/* # Add tini -ENV TINI_VERSION="0.18.0" -ENV TINI_SUM="12d20136605531b09a2c2dac02ccee85e1b874eb322ef6baf7561cd93f93c855" -ADD https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini /tini -RUN echo "$TINI_SUM tini" | sha256sum -c - -RUN chmod +x /tini +ENV TINI_VERSION="0.19.0" +RUN dpkgArch="$(dpkg --print-architecture)" && \ + ARCH=$dpkgArch && \ + wget https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH \ + https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH.sha256sum && \ + cat tini-$ARCH.sha256sum | sha256sum -c - && \ + mv tini-$ARCH /tini && rm tini-$ARCH.sha256sum && \ + chmod +x /tini # Copy over mastodon source, and dependencies from building, and set permissions COPY --chown=mastodon:mastodon . /opt/mastodon diff --git a/Gemfile b/Gemfile index 414bd2c305674bdcc25820bcfafaf249d20d617e..6180a1d110946084d9bd20a8907303c6e969cf15 100644 --- a/Gemfile +++ b/Gemfile @@ -5,22 +5,19 @@ ruby '>= 2.5.0', '< 3.0.0' gem 'pkg-config', '~> 1.4' -gem 'puma', '~> 4.3' -gem 'rails', '~> 5.2.4.3' +gem 'puma', '~> 5.1' +gem 'rails', '~> 5.2.4.4' gem 'sprockets', '~> 3.7.2' -gem 'thor', '~> 0.20' +gem 'thor', '~> 1.0' gem 'rack', '~> 2.2.3' -gem 'thwait', '~> 0.1.0' -gem 'e2mmap', '~> 0.1.0' - gem 'hamlit-rails', '~> 0.2' gem 'pg', '~> 1.2' gem 'makara', '~> 0.4' -gem 'pghero', '~> 2.5' +gem 'pghero', '~> 2.7' gem 'dotenv-rails', '~> 2.7' -gem 'aws-sdk-s3', '~> 1.73', require: false +gem 'aws-sdk-s3', '~> 1.87', require: false gem 'fog-core', '<= 2.1.0' gem 'fog-openstack', '~> 0.3', require: false gem 'paperclip', '~> 6.0' @@ -30,12 +27,12 @@ gem 'blurhash', '~> 0.1' gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.7' -gem 'bootsnap', '~> 1.4', require: false +gem 'bootsnap', '~> 1.5', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'iso-639' gem 'chewy', '~> 5.1' -gem 'cld3', '~> 3.3.0' +gem 'cld3', '~> 3.4.1' gem 'devise', '~> 4.7' gem 'devise-two-factor', '~> 3.1' @@ -43,10 +40,11 @@ group :pam_authentication, optional: true do gem 'devise_pam_authenticatable2', '~> 9.2' end -gem 'net-ldap', '~> 0.16' -gem 'omniauth-cas', '~> 1.1' +gem 'net-ldap', '~> 0.17' +gem 'omniauth-cas', '~> 2.0' gem 'omniauth-saml', '~> 1.10' gem 'omniauth', '~> 1.9' +gem 'omniauth-rails_csrf_protection', '~> 0.1' gem 'color_diff', '~> 0.1' gem 'discard', '~> 1.2' @@ -54,14 +52,12 @@ gem 'doorkeeper', '~> 5.4' gem 'ed25519', '~> 1.2' gem 'fast_blank', '~> 1.0' gem 'fastimage' -gem 'goldfinger', '~> 2.1' gem 'hiredis', '~> 0.6' -gem 'redis-namespace', '~> 1.7' +gem 'redis-namespace', '~> 1.8' gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b' gem 'htmlentities', '~> 4.3' gem 'http', '~> 4.4' gem 'http_accept_language', '~> 2.1' -gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2', submodules: true gem 'httplog', '~> 1.4.3' gem 'idn-ruby', require: 'idn' gem 'kaminari', '~> 1.2' @@ -71,10 +67,10 @@ gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b gem 'nokogiri', '~> 1.10' gem 'nsa', '~> 0.2' gem 'oj', '~> 3.10' -gem 'ox', '~> 2.13' +gem 'ox', '~> 2.14' gem 'parslet' -gem 'parallel', '~> 1.19' -gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' +gem 'parallel', '~> 1.20' +gem 'posix-spawn' gem 'pundit', '~> 2.1' gem 'premailer-rails' gem 'rack-attack', '~> 6.3' @@ -83,23 +79,25 @@ gem 'rails-i18n', '~> 5.1' gem 'rails-settings-cached', '~> 0.6' gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis'] gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' -gem 'rqrcode', '~> 1.1' -gem 'ruby-progressbar', '~> 1.10' +gem 'rqrcode', '~> 1.2' +gem 'ruby-progressbar', '~> 1.11' gem 'sanitize', '~> 5.2' -gem 'sidekiq', '~> 6.0' +gem 'scenic', '~> 1.5' +gem 'sidekiq', '~> 6.1' gem 'sidekiq-scheduler', '~> 3.0' gem 'sidekiq-unique-jobs', '~> 6.0' gem 'sidekiq-bulk', '~>0.2.0' gem 'simple-navigation', '~> 4.1' gem 'simple_form', '~> 5.0' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' -gem 'stoplight', '~> 2.2.0' -gem 'strong_migrations', '~> 0.6' -gem 'tty-prompt', '~> 0.21', require: false +gem 'stoplight', '~> 2.2.1' +gem 'strong_migrations', '~> 0.7' +gem 'tty-prompt', '~> 0.23', require: false gem 'twitter-text', '~> 1.14' gem 'tzinfo-data', '~> 1.2020' -gem 'webpacker', '~> 5.1' +gem 'webpacker', '~> 5.2' gem 'webpush' +gem 'webauthn', '~> 3.0.0.alpha1' gem 'json-ld' gem 'json-ld-preloaded', '~> 3.1' @@ -119,35 +117,35 @@ group :production, :test do end group :test do - gem 'capybara', '~> 3.33' + gem 'capybara', '~> 3.34' gem 'climate_control', '~> 0.2' - gem 'faker', '~> 2.13' + gem 'faker', '~> 2.15' gem 'microformats', '~> 4.2' gem 'rails-controller-testing', '~> 1.0' gem 'rspec-sidekiq', '~> 3.1' - gem 'simplecov', '~> 0.18', require: false - gem 'webmock', '~> 3.8' - gem 'parallel_tests', '~> 3.0' + gem 'simplecov', '~> 0.21', require: false + gem 'webmock', '~> 3.11' + gem 'parallel_tests', '~> 3.4' gem 'rspec_junit_formatter', '~> 0.4' end group :development do - gem 'active_record_query_trace', '~> 1.7' + gem 'active_record_query_trace', '~> 1.8' gem 'annotate', '~> 3.1' - gem 'better_errors', '~> 2.7' + gem 'better_errors', '~> 2.9' gem 'binding_of_caller', '~> 0.7' gem 'bullet', '~> 6.1' gem 'letter_opener', '~> 1.7' gem 'letter_opener_web', '~> 1.4' gem 'memory_profiler' - gem 'rubocop', '~> 0.86', require: false - gem 'rubocop-rails', '~> 2.6', require: false - gem 'brakeman', '~> 4.8', require: false + gem 'rubocop', '~> 1.7', require: false + gem 'rubocop-rails', '~> 2.9', require: false + gem 'brakeman', '~> 4.10', require: false gem 'bundler-audit', '~> 0.7', require: false gem 'capistrano', '~> 3.14' - gem 'capistrano-rails', '~> 1.5' - gem 'capistrano-rbenv', '~> 2.1' + gem 'capistrano-rails', '~> 1.6' + gem 'capistrano-rbenv', '~> 2.2' gem 'capistrano-yarn', '~> 2.0' gem 'stackprof' @@ -160,3 +158,6 @@ end gem 'concurrent-ruby', require: false gem 'connection_pool', require: false + +gem 'xorcist', '~> 1.1' +gem 'pluck_each', '~> 0.1.3' diff --git a/Gemfile.lock b/Gemfile.lock index 3d4fce643343ef15a86a5cd9d2be2235942c28ce..46207d01c9670fa6fdf386cdb97ffeb56be72987 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,21 +6,6 @@ GIT health_check (4.0.0.pre) rails (>= 4.0) -GIT - remote: https://github.com/rtomayko/posix-spawn - revision: 58465d2e213991f8afb13b984854a49fcdcc980c - ref: 58465d2e213991f8afb13b984854a49fcdcc980c - specs: - posix-spawn (0.3.13) - -GIT - remote: https://github.com/tmm1/http_parser.rb - revision: 54b17ba8c7d8d20a16dfc65d1775241833219cf2 - ref: 54b17ba8c7d8d20a16dfc65d1775241833219cf2 - submodules: true - specs: - http_parser.rb (0.6.1) - GIT remote: https://github.com/witgo/nilsimsa revision: fd184883048b922b176939f851338d0a4971a532 @@ -31,49 +16,49 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.3) - actionpack (= 5.2.4.3) + actioncable (5.2.4.4) + actionpack (= 5.2.4.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) + actionmailer (5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.3) - actionview (= 5.2.4.3) - activesupport (= 5.2.4.3) + actionpack (5.2.4.4) + actionview (= 5.2.4.4) + activesupport (= 5.2.4.4) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.3) - activesupport (= 5.2.4.3) + actionview (5.2.4.4) + activesupport (= 5.2.4.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - active_model_serializers (0.10.10) - actionpack (>= 4.1, < 6.1) - activemodel (>= 4.1, < 6.1) + active_model_serializers (0.10.12) + actionpack (>= 4.1, < 6.2) + activemodel (>= 4.1, < 6.2) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - active_record_query_trace (1.7) - activejob (5.2.4.3) - activesupport (= 5.2.4.3) + active_record_query_trace (1.8) + activejob (5.2.4.4) + activesupport (= 5.2.4.4) globalid (>= 0.3.6) - activemodel (5.2.4.3) - activesupport (= 5.2.4.3) - activerecord (5.2.4.3) - activemodel (= 5.2.4.3) - activesupport (= 5.2.4.3) + activemodel (5.2.4.4) + activesupport (= 5.2.4.4) + activerecord (5.2.4.4) + activemodel (= 5.2.4.4) + activesupport (= 5.2.4.4) arel (>= 9.0) - activestorage (5.2.4.3) - actionpack (= 5.2.4.3) - activerecord (= 5.2.4.3) + activestorage (5.2.4.4) + actionpack (= 5.2.4.4) + activerecord (= 5.2.4.4) marcel (~> 0.3.1) - activesupport (5.2.4.3) + activesupport (5.2.4.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -82,6 +67,7 @@ GEM public_suffix (>= 2.0.2, < 5.0) airbrussh (1.4.0) sshkit (>= 1.6.1, != 1.7.0) + android_key_attestation (0.3.0) annotate (3.1.1) activerecord (>= 3.2, < 7.0) rake (>= 10.4, < 14.0) @@ -91,37 +77,39 @@ GEM encryptor (~> 3.0.0) av (0.9.0) cocaine (~> 0.5.3) + awrence (1.1.1) aws-eventstream (1.1.0) - aws-partitions (1.338.0) - aws-sdk-core (3.103.0) + aws-partitions (1.413.0) + aws-sdk-core (3.110.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.36.0) - aws-sdk-core (~> 3, >= 3.99.0) + aws-sdk-kms (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.73.0) - aws-sdk-core (~> 3, >= 3.102.1) + aws-sdk-s3 (1.87.0) + aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.1) + aws-sigv4 (1.2.2) aws-eventstream (~> 1, >= 1.0.2) - bcrypt (3.1.13) - better_errors (2.7.1) + bcrypt (3.1.16) + better_errors (2.9.1) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) + bindata (2.4.8) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) blurhash (0.1.4) ffi (~> 1.10.0) - bootsnap (1.4.6) + bootsnap (1.5.1) msgpack (~> 1.0) - brakeman (4.8.2) + brakeman (4.10.1) browser (4.2.0) builder (3.2.4) - bullet (6.1.0) + bullet (6.1.2) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) bundler-audit (0.7.0.1) @@ -133,17 +121,17 @@ GEM i18n rake (>= 10.0.0) sshkit (>= 1.9.0) - capistrano-bundler (1.6.0) + capistrano-bundler (2.0.1) capistrano (~> 3.1) - capistrano-rails (1.5.0) + capistrano-rails (1.6.1) capistrano (~> 3.1) - capistrano-bundler (~> 1.1) - capistrano-rbenv (2.1.6) + capistrano-bundler (>= 1.1, < 3) + capistrano-rbenv (2.2.0) capistrano (~> 3.1) sshkit (~> 1.3) capistrano-yarn (2.0.2) capistrano (~> 3.0) - capybara (3.33.0) + capybara (3.34.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) @@ -153,28 +141,32 @@ GEM xpath (~> 3.2) case_transform (0.2) activesupport + cbor (0.5.9.6) charlock_holmes (0.7.7) chewy (5.1.0) activesupport (>= 4.0) elasticsearch (>= 2.0.0) elasticsearch-dsl - chunky_png (1.3.11) - cld3 (3.3.0) - ffi (>= 1.1.0, < 1.12.0) + chunky_png (1.3.15) + cld3 (3.4.1) + ffi (>= 1.1.0, < 1.15.0) climate_control (0.2.0) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.1.3) color_diff (0.1) - concurrent-ruby (1.1.6) + concurrent-ruby (1.1.7) connection_pool (2.2.3) - crack (0.4.3) - safe_yaml (~> 1.0.0) + cose (1.0.0) + cbor (~> 0.5.9) + openssl-signature_algorithm (~> 0.4.0) + crack (0.4.5) + rexml crass (1.0.6) css_parser (1.7.1) addressable debug_inspector (0.0.3) - devise (4.7.2) + devise (4.7.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -192,39 +184,38 @@ GEM diff-lcs (1.4.4) discard (1.2.0) activerecord (>= 4.2, < 7) - docile (1.3.2) + docile (1.3.4) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) doorkeeper (5.4.0) railties (>= 5) - dotenv (2.7.5) - dotenv-rails (2.7.5) - dotenv (= 2.7.5) - railties (>= 3.2, < 6.1) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) e2mmap (0.1.0) ed25519 (1.2.4) - elasticsearch (7.8.0) - elasticsearch-api (= 7.8.0) - elasticsearch-transport (= 7.8.0) - elasticsearch-api (7.8.0) + elasticsearch (7.9.0) + elasticsearch-api (= 7.9.0) + elasticsearch-transport (= 7.9.0) + elasticsearch-api (7.9.0) multi_json elasticsearch-dsl (0.1.9) - elasticsearch-transport (7.8.0) + elasticsearch-transport (7.9.0) faraday (~> 1) multi_json encryptor (3.0.0) - equatable (0.6.1) - erubi (1.9.0) + erubi (1.10.0) et-orbi (1.2.4) tzinfo - excon (0.75.0) + excon (0.76.0) fabrication (2.21.1) - faker (2.13.0) + faker (2.15.1) i18n (>= 1.6, < 2) faraday (1.0.1) multipart-post (>= 1.2, < 3) fast_blank (1.0.0) - fastimage (2.1.7) + fastimage (2.2.1) ffi (1.10.0) ffi-compiler (1.0.1) ffi (>= 1.0.0) @@ -242,20 +233,15 @@ GEM fog-json (>= 1.0) ipaddress (>= 0.8) formatador (0.2.5) - fugit (1.3.6) + fugit (1.3.9) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.3) - fuubar (2.5.0) + fuubar (2.5.1) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) globalid (0.4.2) activesupport (>= 4.2.0) - goldfinger (2.1.1) - addressable (~> 2.5) - http (~> 4.0) - nokogiri (~> 1.8) - oj (~> 3.0) - hamlit (2.11.0) + hamlit (2.13.0) temple (>= 0.8.2) thor tilt @@ -286,9 +272,9 @@ GEM httplog (1.4.3) rack (>= 1.0) rainbow (>= 2.0.0) - i18n (1.8.3) + i18n (1.8.5) concurrent-ruby (~> 1.0) - i18n-tasks (0.9.31) + i18n-tasks (0.9.33) activesupport (>= 4.0.2) ast (>= 2.1.0) erubi @@ -304,18 +290,18 @@ GEM jmespath (1.4.0) json (2.3.1) json-canonicalization (0.2.0) - json-ld (3.1.4) + json-ld (3.1.7) htmlentities (~> 4.3) json-canonicalization (~> 0.2) link_header (~> 0.0, >= 0.0.8) multi_json (~> 1.14) rack (~> 2.0) rdf (~> 3.1) - json-ld-preloaded (3.1.3) + json-ld-preloaded (3.1.4) json-ld (~> 3.1) rdf (~> 3.1) jsonapi-renderer (0.2.2) - jwt (2.2.1) + jwt (2.2.2) kaminari (1.2.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.1) @@ -342,7 +328,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.6.0) + loofah (2.8.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -353,9 +339,9 @@ GEM mimemagic (~> 0.3.2) mario-redis-lock (1.2.1) redis (>= 3.0.5) - memory_profiler (0.9.14) + memory_profiler (1.0.0) method_source (1.0.0) - microformats (4.2.0) + microformats (4.2.1) json (~> 2.2) nokogiri (~> 1.10) mime-types (3.3.1) @@ -364,17 +350,16 @@ GEM mimemagic (0.3.5) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.14.1) + minitest (5.14.2) msgpack (1.3.3) - multi_json (1.14.1) + multi_json (1.15.0) multipart-post (2.1.1) - necromancer (0.5.1) - net-ldap (0.16.2) + net-ldap (0.17.0) net-scp (3.0.0) net-ssh (>= 2.6.5, < 7.0.0) net-ssh (6.1.0) - nio4r (2.5.2) - nokogiri (1.10.9) + nio4r (2.5.4) + nokogiri (1.10.10) mini_portile2 (~> 2.4.0) nokogumbo (2.0.2) nokogiri (~> 1.8, >= 1.8.4) @@ -383,19 +368,24 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.10.6) + oj (3.10.18) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) - omniauth-cas (1.1.1) + omniauth-cas (2.0.0) addressable (~> 2.3) nokogiri (~> 1.5) omniauth (~> 1.2) - omniauth-saml (1.10.2) + omniauth-rails_csrf_protection (0.1.2) + actionpack (>= 4.2) + omniauth (>= 1.3.1) + omniauth-saml (1.10.3) omniauth (~> 1.3, >= 1.3.2) ruby-saml (~> 1.9) + openssl (2.2.0) + openssl-signature_algorithm (0.4.0) orm_adapter (0.5.0) - ox (2.13.2) + ox (2.14.0) paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) @@ -405,20 +395,23 @@ GEM paperclip-av-transcoder (0.6.4) av (~> 0.9.0) paperclip (>= 2.5.2) - parallel (1.19.2) - parallel_tests (3.0.0) + parallel (1.20.1) + parallel_tests (3.4.0) parallel - parser (2.7.1.4) + parser (3.0.0.0) ast (~> 2.4.1) parslet (2.0.0) - pastel (0.7.4) - equatable (~> 0.6) + pastel (0.8.0) tty-color (~> 0.5) pg (1.2.3) - pghero (2.5.1) + pghero (2.7.3) activerecord (>= 5) - pkg-config (1.4.1) - premailer (1.11.1) + pkg-config (1.4.4) + pluck_each (0.1.3) + activerecord (> 3.2.0) + activesupport (> 3.0.0) + posix-spawn (0.3.15) + premailer (1.14.2) addressable css_parser (>= 1.6.0) htmlentities (>= 4.0.0) @@ -434,12 +427,12 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.5) - puma (4.3.5) + public_suffix (4.0.6) + puma (5.1.1) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) - raabro (1.3.1) + raabro (1.3.3) rack (2.2.3) rack-attack (6.3.1) rack (>= 1.0, < 3) @@ -449,18 +442,18 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.3) - actioncable (= 5.2.4.3) - actionmailer (= 5.2.4.3) - actionpack (= 5.2.4.3) - actionview (= 5.2.4.3) - activejob (= 5.2.4.3) - activemodel (= 5.2.4.3) - activerecord (= 5.2.4.3) - activestorage (= 5.2.4.3) - activesupport (= 5.2.4.3) + rails (5.2.4.4) + actioncable (= 5.2.4.4) + actionmailer (= 5.2.4.4) + actionpack (= 5.2.4.4) + actionview (= 5.2.4.4) + activejob (= 5.2.4.4) + activemodel (= 5.2.4.4) + activerecord (= 5.2.4.4) + activestorage (= 5.2.4.4) + activesupport (= 5.2.4.4) bundler (>= 1.3.0) - railties (= 5.2.4.3) + railties (= 5.2.4.4) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -476,20 +469,20 @@ GEM railties (>= 5.0, < 6) rails-settings-cached (0.6.6) rails (>= 4.2.0) - railties (5.2.4.3) - actionpack (= 5.2.4.3) - activesupport (= 5.2.4.3) + railties (5.2.4.4) + actionpack (= 5.2.4.4) + activesupport (= 5.2.4.4) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (13.0.1) - rdf (3.1.4) + rake (13.0.3) + rdf (3.1.8) hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.4.0) rdf (~> 3.1) - redis (4.2.1) + redis (4.2.5) redis-actionpack (5.2.0) actionpack (>= 5, < 7) redis-rack (>= 2.1.0, < 3) @@ -497,9 +490,9 @@ GEM redis-activesupport (5.2.0) activesupport (>= 3, < 7) redis-store (>= 1.3, < 2) - redis-namespace (1.7.0) + redis-namespace (1.8.0) redis (>= 3.0.4) - redis-rack (2.1.2) + redis-rack (2.1.3) rack (>= 2.0.8, < 3) redis-store (>= 1.2, < 2) redis-rails (5.0.2) @@ -508,7 +501,7 @@ GEM redis-store (>= 1.2, < 2) redis-store (1.9.0) redis (>= 4, < 5) - regexp_parser (1.7.1) + regexp_parser (1.8.2) request_store (1.5.0) rack (>= 1.4) responders (3.0.1) @@ -517,59 +510,64 @@ GEM rexml (3.2.4) rotp (2.1.2) rpam2 (4.0.2) - rqrcode (1.1.2) + rqrcode (1.2.0) chunky_png (~> 1.0) - rqrcode_core (~> 0.1) - rqrcode_core (0.1.2) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rqrcode_core (~> 0.2) + rqrcode_core (0.2.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) + rspec-support (~> 3.10.0) + rspec-rails (4.0.2) actionpack (>= 4.2) activesupport (>= 4.2) railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) rspec-sidekiq (3.1.0) rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) - rspec-support (3.9.3) + rspec-support (3.10.1) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.86.0) + rubocop (1.7.0) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.7) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.0.3, < 1.0) + rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.1.0) - parser (>= 2.7.0.1) - rubocop-rails (2.6.0) + rubocop-ast (1.3.0) + parser (>= 2.7.1.5) + rubocop-rails (2.9.1) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.82.0) - ruby-progressbar (1.10.1) + rubocop (>= 0.90.0, < 2.0) + ruby-progressbar (1.11.0) ruby-saml (1.11.0) nokogiri (>= 1.5.10) rufus-scheduler (3.6.0) fugit (~> 1.1, >= 1.1.6) - safe_yaml (1.0.5) + safety_net_attestation (0.4.0) + jwt (~> 2.0) sanitize (5.2.1) crass (~> 1.0.2) nokogiri (>= 1.8.0) nokogumbo (~> 2.0) + scenic (1.5.4) + activerecord (>= 4.0.0) + railties (>= 4.0.0) + securecompare (1.0.0) semantic_range (2.3.0) - sidekiq (6.1.0) + sidekiq (6.1.2) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -582,74 +580,89 @@ GEM sidekiq (>= 3) thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (6.0.22) + sidekiq-unique-jobs (6.0.25) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 4.0, < 7.0) - thor (~> 0) + thor (>= 0.20, < 2.0) simple-navigation (4.1.0) activesupport (>= 2.3.2) - simple_form (5.0.2) + simple_form (5.0.3) actionpack (>= 5.0) activemodel (>= 5.0) - simplecov (0.18.5) + simplecov (0.21.0) docile (~> 1.1) simplecov-html (~> 0.11) - simplecov-html (0.12.2) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.2) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) sshkit (1.21.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) - stackprof (0.2.15) + stackprof (0.2.16) statsd-ruby (1.4.0) - stoplight (2.2.0) + stoplight (2.2.1) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.6.8) + strong_migrations (0.7.4) activerecord (>= 5) temple (0.8.2) - terminal-table (1.8.0) + terminal-table (2.0.0) unicode-display_width (~> 1.1, >= 1.1.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) - thor (0.20.3) + thor (1.0.1) thread_safe (0.3.6) - thwait (0.1.0) + thwait (0.2.0) + e2mmap tilt (2.0.10) - tty-color (0.5.1) + tpm-key_attestation (0.9.0) + bindata (~> 2.4) + openssl-signature_algorithm (~> 0.4.0) + tty-color (0.6.0) tty-cursor (0.7.1) - tty-prompt (0.21.0) - necromancer (~> 0.5.0) - pastel (~> 0.7.0) - tty-reader (~> 0.7.0) - tty-reader (0.7.0) + tty-prompt (0.23.0) + pastel (~> 0.8) + tty-reader (~> 0.8) + tty-reader (0.9.0) tty-cursor (~> 0.7) - tty-screen (~> 0.7) - wisper (~> 2.0.0) - tty-screen (0.8.0) + tty-screen (~> 0.8) + wisper (~> 2.0) + tty-screen (0.8.1) twitter-text (1.14.7) unf (~> 0.1.0) - tzinfo (1.2.7) + tzinfo (1.2.9) thread_safe (~> 0.1) - tzinfo-data (1.2020.1) + tzinfo-data (1.2020.6) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext unf_ext (0.0.7.7) unicode-display_width (1.7.0) uniform_notifier (1.13.0) - warden (1.2.8) - rack (>= 2.0.6) - webmock (3.8.3) + warden (1.2.9) + rack (>= 2.0.9) + webauthn (3.0.0.alpha1) + android_key_attestation (~> 0.3.0) + awrence (~> 1.1) + bindata (~> 2.4) + cbor (~> 0.5.9) + cose (~> 1.0) + openssl (~> 2.0) + safety_net_attestation (~> 0.4.0) + securecompare (~> 1.0) + tpm-key_attestation (~> 0.9.0) + webmock (3.11.0) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webpacker (5.1.1) + webpacker (5.2.1) activesupport (>= 5.2) rack-proxy (>= 0.6.1) railties (>= 5.2) @@ -657,10 +670,11 @@ GEM webpush (0.3.8) hkdf (~> 0.2) jwt (~> 2.0) - websocket-driver (0.7.2) + websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) wisper (2.0.1) + xorcist (1.1.2) xpath (3.2.0) nokogiri (~> 1.8) @@ -669,26 +683,26 @@ PLATFORMS DEPENDENCIES active_model_serializers (~> 0.10) - active_record_query_trace (~> 1.7) + active_record_query_trace (~> 1.8) addressable (~> 2.7) annotate (~> 3.1) - aws-sdk-s3 (~> 1.73) - better_errors (~> 2.7) + aws-sdk-s3 (~> 1.87) + better_errors (~> 2.9) binding_of_caller (~> 0.7) blurhash (~> 0.1) - bootsnap (~> 1.4) - brakeman (~> 4.8) + bootsnap (~> 1.5) + brakeman (~> 4.10) browser bullet (~> 6.1) bundler-audit (~> 0.7) capistrano (~> 3.14) - capistrano-rails (~> 1.5) - capistrano-rbenv (~> 2.1) + capistrano-rails (~> 1.6) + capistrano-rbenv (~> 2.2) capistrano-yarn (~> 2.0) - capybara (~> 3.33) + capybara (~> 3.34) charlock_holmes (~> 0.7.7) chewy (~> 5.1) - cld3 (~> 3.3.0) + cld3 (~> 3.4.1) climate_control (~> 0.2) color_diff (~> 0.1) concurrent-ruby @@ -699,23 +713,20 @@ DEPENDENCIES discard (~> 1.2) doorkeeper (~> 5.4) dotenv-rails (~> 2.7) - e2mmap (~> 0.1.0) ed25519 (~> 1.2) fabrication (~> 2.21) - faker (~> 2.13) + faker (~> 2.15) fast_blank (~> 1.0) fastimage fog-core (<= 2.1.0) fog-openstack (~> 0.3) fuubar (~> 2.5) - goldfinger (~> 2.1) hamlit-rails (~> 0.2) health_check! hiredis (~> 0.6) htmlentities (~> 4.3) http (~> 4.4) http_accept_language (~> 2.1) - http_parser.rb (~> 0.6)! httplog (~> 1.4.3) i18n-tasks (~> 0.9) idn-ruby @@ -732,67 +743,71 @@ DEPENDENCIES memory_profiler microformats (~> 4.2) mime-types (~> 3.3.1) - net-ldap (~> 0.16) + net-ldap (~> 0.17) nilsimsa! nokogiri (~> 1.10) nsa (~> 0.2) oj (~> 3.10) omniauth (~> 1.9) - omniauth-cas (~> 1.1) + omniauth-cas (~> 2.0) + omniauth-rails_csrf_protection (~> 0.1) omniauth-saml (~> 1.10) - ox (~> 2.13) + ox (~> 2.14) paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) - parallel (~> 1.19) - parallel_tests (~> 3.0) + parallel (~> 1.20) + parallel_tests (~> 3.4) parslet pg (~> 1.2) - pghero (~> 2.5) + pghero (~> 2.7) pkg-config (~> 1.4) - posix-spawn! + pluck_each (~> 0.1.3) + posix-spawn premailer-rails private_address_check (~> 0.5) pry-byebug (~> 3.9) pry-rails (~> 0.3) - puma (~> 4.3) + puma (~> 5.1) pundit (~> 2.1) rack (~> 2.2.3) rack-attack (~> 6.3) rack-cors (~> 1.1) - rails (~> 5.2.4.3) + rails (~> 5.2.4.4) rails-controller-testing (~> 1.0) rails-i18n (~> 5.1) rails-settings-cached (~> 0.6) rdf-normalize (~> 0.4) redis (~> 4.2) - redis-namespace (~> 1.7) + redis-namespace (~> 1.8) redis-rails (~> 5.0) - rqrcode (~> 1.1) + rqrcode (~> 1.2) rspec-rails (~> 4.0) rspec-sidekiq (~> 3.1) rspec_junit_formatter (~> 0.4) - rubocop (~> 0.86) - rubocop-rails (~> 2.6) - ruby-progressbar (~> 1.10) + rubocop (~> 1.7) + rubocop-rails (~> 2.9) + ruby-progressbar (~> 1.11) sanitize (~> 5.2) - sidekiq (~> 6.0) + scenic (~> 1.5) + sidekiq (~> 6.1) sidekiq-bulk (~> 0.2.0) sidekiq-scheduler (~> 3.0) sidekiq-unique-jobs (~> 6.0) simple-navigation (~> 4.1) simple_form (~> 5.0) - simplecov (~> 0.18) + simplecov (~> 0.21) sprockets (~> 3.7.2) sprockets-rails (~> 3.2) stackprof - stoplight (~> 2.2.0) + stoplight (~> 2.2.1) streamio-ffmpeg (~> 3.0) - strong_migrations (~> 0.6) - thor (~> 0.20) - thwait (~> 0.1.0) - tty-prompt (~> 0.21) + strong_migrations (~> 0.7) + thor (~> 1.0) + tty-prompt (~> 0.23) twitter-text (~> 1.14) tzinfo-data (~> 1.2020) - webmock (~> 3.8) - webpacker (~> 5.1) + webauthn (~> 3.0.0.alpha1) + webmock (~> 3.11) + webpacker (~> 5.2) webpush + xorcist (~> 1.1) diff --git a/Procfile b/Procfile index d48b0373b05233df9cb41d2d1a0b33a7feb16529..d15c835b867517918a583987552da231be9c5487 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,4 @@ -web: if [ "$RUN_STREAMING" != "true" ]; then BIND=0.0.0.0 bundle exec puma -C config/puma.rb; else BIND=0.0.0.0 node ./streaming; fi +web: bin/heroku-web worker: bundle exec sidekiq # For the streaming API, you need a separate app that shares Postgres and Redis: diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb index abd1ec0cb647296b08ee042e3c89a8cfe0d7946c..dcad5d3b44efb1a96906e3b305b8f258515d2231 100644 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@ -1,12 +1,15 @@ # frozen_string_literal: true class AboutController < ApplicationController + include RegistrationSpamConcern + layout 'public' before_action :require_open_federation!, only: [:show, :more] before_action :set_body_classes, only: :show before_action :set_instance_presenter - before_action :set_expires_in, only: [:show, :more, :terms] + before_action :set_expires_in, only: [:more, :terms] + before_action :set_registration_form_time, only: :show skip_before_action :require_functional!, only: [:more, :terms] diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index db77b628c9f5b65af3a5271b7669fdc38d0dfe84..b902ada090ae02692cbb756dd828e7950913d5e2 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -7,6 +7,7 @@ class AccountsController < ApplicationController include AccountControllerConcern include SignatureAuthentication + before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_cache_headers before_action :set_body_classes @@ -28,8 +29,7 @@ class AccountsController < ApplicationController end @pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses? - @statuses = filtered_status_page - @statuses = cache_collection(@statuses, Status) + @statuses = cached_filtered_status_page @rss_url = rss_url unless @statuses.empty? @@ -49,7 +49,7 @@ class AccountsController < ApplicationController format.json do expires_in 3.minutes, public: !(authorized_fetch_mode? && signed_request_account.present?) - render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter, fields: restrict_fields_to + render_with_cache json: @account, content_type: 'application/activity+json', serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter end end end @@ -81,7 +81,7 @@ class AccountsController < ApplicationController end def account_media_status_ids - @account.media_attachments.attached.reorder(nil).select(:status_id).distinct + @account.media_attachments.attached.reorder(nil).select(:status_id).group(:status_id) end def no_replies_scope @@ -102,6 +102,10 @@ class AccountsController < ApplicationController params[:username] end + def skip_temporary_suspension_response? + request.format == :json + end + def rss_url if tag_requested? short_account_tag_url(@account, params[:tag], format: 'rss') @@ -142,19 +146,16 @@ class AccountsController < ApplicationController request.path.split('.').first.ends_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize) end - def filtered_status_page - filtered_statuses.paginate_by_id(PAGE_SIZE, params_slice(:max_id, :min_id, :since_id)) + def cached_filtered_status_page + cache_collection_paginated_by_id( + filtered_statuses, + Status, + PAGE_SIZE, + params_slice(:max_id, :min_id, :since_id) + ) end def params_slice(*keys) params.slice(*keys).permit(*keys) end - - def restrict_fields_to - if signed_request_account.present? || public_fetch_mode? - # Return all fields - else - %i(id type preferred_username inbox public_key endpoints) - end - end end diff --git a/app/controllers/activitypub/base_controller.rb b/app/controllers/activitypub/base_controller.rb index 0c2591e9743ee534892adbbd8cc2329e5d1fd180..4cbc3ab8f209ad24fbdb4d8cf7f71ae3c27b71b1 100644 --- a/app/controllers/activitypub/base_controller.rb +++ b/app/controllers/activitypub/base_controller.rb @@ -8,4 +8,8 @@ class ActivityPub::BaseController < Api::BaseController def set_cache_headers response.headers['Vary'] = 'Signature' if authorized_fetch_mode? end + + def skip_temporary_suspension_response? + false + end end diff --git a/app/controllers/activitypub/collections_controller.rb b/app/controllers/activitypub/collections_controller.rb index 380de54f5dc41354174c6f1bbc1947348e3520ac..c8b6dcc88d4fb94b6a2c29baa803f99fdc79dd33 100644 --- a/app/controllers/activitypub/collections_controller.rb +++ b/app/controllers/activitypub/collections_controller.rb @@ -12,7 +12,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController def show expires_in 3.minutes, public: public_fetch_mode? - render_with_cache json: collection_presenter, content_type: 'application/activity+json', serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, skip_activities: true + render_with_cache json: collection_presenter, content_type: 'application/activity+json', serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter end private @@ -20,17 +20,9 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController def set_items case params[:id] when 'featured' - @items = begin - # Because in public fetch mode we cache the response, there would be no - # benefit from performing the check below, since a blocked account or domain - # would likely be served the cache from the reverse proxy anyway - - if authorized_fetch_mode? && !signed_request_account.nil? && (@account.blocking?(signed_request_account) || (!signed_request_account.domain.nil? && @account.domain_blocking?(signed_request_account.domain))) - [] - else - cache_collection(@account.pinned_statuses, Status) - end - end + @items = for_signed_account { cache_collection(@account.pinned_statuses, Status) } + when 'tags' + @items = for_signed_account { @account.featured_tags } when 'devices' @items = @account.devices else @@ -40,7 +32,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController def set_size case params[:id] - when 'featured', 'devices' + when 'featured', 'devices', 'tags' @size = @items.size else not_found @@ -51,7 +43,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController case params[:id] when 'featured' @type = :ordered - when 'devices' + when 'devices', 'tags' @type = :unordered else not_found @@ -66,4 +58,16 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController items: @items ) end + + def for_signed_account + # Because in public fetch mode we cache the response, there would be no + # benefit from performing the check below, since a blocked account or domain + # would likely be served the cache from the reverse proxy anyway + + if authorized_fetch_mode? && !signed_request_account.nil? && (@account.blocking?(signed_request_account) || (!signed_request_account.domain.nil? && @account.domain_blocking?(signed_request_account.domain))) + [] + else + yield + end + end end diff --git a/app/controllers/activitypub/followers_synchronizations_controller.rb b/app/controllers/activitypub/followers_synchronizations_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..52503110582b03c43fa9dcf8fa4e89ce63ca1f76 --- /dev/null +++ b/app/controllers/activitypub/followers_synchronizations_controller.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseController + include SignatureVerification + include AccountOwnedConcern + + before_action :require_signature! + before_action :set_items + before_action :set_cache_headers + + def show + expires_in 0, public: false + render json: collection_presenter, + serializer: ActivityPub::CollectionSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' + end + + private + + def uri_prefix + signed_request_account.uri[/http(s?):\/\/[^\/]+\//] + end + + def set_items + @items = @account.followers.where(Account.arel_table[:uri].matches(uri_prefix + '%', false, true)).pluck(:uri) + end + + def collection_presenter + ActivityPub::CollectionPresenter.new( + id: account_followers_synchronization_url(@account), + type: :ordered, + items: @items + ) + end +end diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index 0a561e7f0fab37c05c3dd82c4c4f06181a1ec98a..d3044f180f819a6ce2fe15540280e8a106729097 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -11,6 +11,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController def create upgrade_account + process_collection_synchronization process_payload head 202 end @@ -32,6 +33,10 @@ class ActivityPub::InboxesController < ActivityPub::BaseController params[:account_username].present? end + def skip_temporary_suspension_response? + true + end + def body return @body if defined?(@body) @@ -52,6 +57,19 @@ class ActivityPub::InboxesController < ActivityPub::BaseController DeliveryFailureTracker.reset!(signed_request_account.inbox_url) end + def process_collection_synchronization + raw_params = request.headers['Collection-Synchronization'] + return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' + + # Re-using the syntax for signature parameters + tree = SignatureParamsParser.new.parse(raw_params) + params = SignatureParamsTransformer.new.apply(tree) + + ActivityPub::PrepareFollowersSynchronizationService.new.call(signed_request_account, params) + rescue Parslet::ParseFailed + Rails.logger.warn 'Error parsing Collection-Synchronization header' + end + def process_payload ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body, @account&.id) end diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index e25a4bc0797b402d9bd26d1c6045e0987dfb0180..5fd735ad6af3d6467f08c6659aa21f95e0e4943e 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -20,9 +20,9 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController def outbox_presenter if page_requested? ActivityPub::CollectionPresenter.new( - id: account_outbox_url(@account, page_params), + id: outbox_url(page_params), type: :ordered, - part_of: account_outbox_url(@account), + part_of: outbox_url, prev: prev_page, next: next_page, items: @statuses @@ -32,12 +32,20 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController id: account_outbox_url(@account), type: :ordered, size: @account.statuses_count, - first: account_outbox_url(@account, page: true), - last: account_outbox_url(@account, page: true, min_id: 0) + first: outbox_url(page: true), + last: outbox_url(page: true, min_id: 0) ) end end + def outbox_url(**kwargs) + if params[:account_username].present? + account_outbox_url(@account, **kwargs) + else + instance_actor_outbox_url(**kwargs) + end + end + def next_page account_outbox_url(@account, page: true, max_id: @statuses.last.id) if @statuses.size == LIMIT end @@ -49,9 +57,12 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController def set_statuses return unless page_requested? - @statuses = @account.statuses.permitted_for(@account, signed_request_account) - @statuses = @statuses.paginate_by_id(LIMIT, params_slice(:max_id, :min_id, :since_id)) - @statuses = cache_collection(@statuses, Status) + @statuses = cache_collection_paginated_by_id( + @account.statuses.permitted_for(@account, signed_request_account), + Status, + LIMIT, + params_slice(:max_id, :min_id, :since_id) + ) end def page_requested? @@ -61,4 +72,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController def page_params { page: true, max_id: params[:max_id], min_id: params[:min_id] }.compact end + + def set_account + @account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative + end end diff --git a/app/controllers/activitypub/replies_controller.rb b/app/controllers/activitypub/replies_controller.rb index 43bf4e657d12db09605a612fa954aef8dcadd204..fde6c861f28619b52ddfa7a8950502dd8ba87107 100644 --- a/app/controllers/activitypub/replies_controller.rb +++ b/app/controllers/activitypub/replies_controller.rb @@ -31,7 +31,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController end def set_replies - @replies = only_other_accounts? ? Status.where.not(account_id: @account.id) : @account.statuses + @replies = only_other_accounts? ? Status.where.not(account_id: @account.id).joins(:account).merge(Account.without_suspended) : @account.statuses @replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted]) @replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id]) end diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 7b17835429974bbb76958e1097ee86619d443b71..1dd7430e098295c88e0d5282dcd7bbe114f63aff 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -2,7 +2,7 @@ module Admin class AccountsController < BaseController - before_action :set_account, only: [:show, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize, :approve, :reject] + before_action :set_account, except: [:index] before_action :require_remote_account!, only: [:redownload] before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject] @@ -14,49 +14,65 @@ module Admin def show authorize @account, :show? + @deletion_request = @account.deletion_request @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account) @moderation_notes = @account.targeted_moderation_notes.latest @warnings = @account.targeted_account_warnings.latest.custom + @domain_block = DomainBlock.rule_for(@account.domain) end def memorialize authorize @account, :memorialize? @account.memorialize! log_action :memorialize, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.memorialized_msg', username: @account.acct) end def enable authorize @account.user, :enable? @account.user.enable! log_action :enable, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.enabled_msg', username: @account.acct) end def approve authorize @account.user, :approve? @account.user.approve! - redirect_to admin_pending_accounts_path + redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.approved_msg', username: @account.acct) end def reject authorize @account.user, :reject? - SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false) - redirect_to admin_pending_accounts_path + DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) + redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct) + end + + def destroy + authorize @account, :destroy? + Admin::AccountDeletionWorker.perform_async(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct) + end + + def unsensitive + authorize @account, :unsensitive? + @account.unsensitize! + log_action :unsensitive, @account + redirect_to admin_account_path(@account.id) end def unsilence authorize @account, :unsilence? @account.unsilence! log_action :unsilence, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsilenced_msg', username: @account.acct) end def unsuspend authorize @account, :unsuspend? @account.unsuspend! + Admin::UnsuspensionWorker.perform_async(@account.id) log_action :unsuspend, @account - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unsuspended_msg', username: @account.acct) end def redownload @@ -65,7 +81,7 @@ module Admin @account.update!(last_webfingered_at: nil) ResolveAccountService.new.call(@account) - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.redownloaded_msg', username: @account.acct) end def remove_avatar @@ -76,7 +92,7 @@ module Admin log_action :remove_avatar, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_avatar_msg', username: @account.acct) end def remove_header @@ -87,7 +103,7 @@ module Admin log_action :remove_header, @account.user - redirect_to admin_account_path(@account.id) + redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_header_msg', username: @account.acct) end private diff --git a/app/controllers/admin/announcements_controller.rb b/app/controllers/admin/announcements_controller.rb index 494fd13d0f634b9450ff95c6bd8f63cc1df2da6e..351b9a9910709f721270e4f13ea8790e762cae02 100644 --- a/app/controllers/admin/announcements_controller.rb +++ b/app/controllers/admin/announcements_controller.rb @@ -71,7 +71,7 @@ class Admin::AnnouncementsController < Admin::BaseController private def set_announcements - @announcements = AnnouncementFilter.new(filter_params).results.page(params[:page]) + @announcements = AnnouncementFilter.new(filter_params).results.reverse_chronological.page(params[:page]) end def set_announcement diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 74a36b79ca3a2106308079e4f2065682445fb1bf..ba927b04adab1f809a9334cb7011e85e8f49c85f 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -29,6 +29,7 @@ module Admin @domain_block = existing_domain_block @domain_block.update(resource_params) end + if @domain_block.save DomainBlockWorker.perform_async(@domain_block.id) log_action :create, @domain_block @@ -40,7 +41,7 @@ module Admin end def update - authorize :domain_block, :create? + authorize :domain_block, :update? @domain_block.update(update_params) @@ -48,7 +49,7 @@ module Admin if @domain_block.save DomainBlockWorker.perform_async(@domain_block.id, severity_changed) - log_action :create, @domain_block + log_action :update, @domain_block redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg') else render :edit @@ -73,11 +74,11 @@ module Admin end def update_params - params.require(:domain_block).permit(:severity, :reject_media, :reject_reports, :private_comment, :public_comment) + params.require(:domain_block).permit(:severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate) end def resource_params - params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment) + params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate) end end end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index c2591972624e3076ae5ad5328aa43daa0a780a0f..f7bdfb0c5f6f8b3aa4a23bdca00d9fd07622cedc 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -27,7 +27,7 @@ module Admin ips = [] Resolv::DNS.open do |dns| - dns.timeouts = 1 + dns.timeouts = 5 hostnames = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb index 1790becbf2fe66fa1e16db1f34696d429f78b9e2..b5918d231c7e680f07e5c7112fc4740db54b39f6 100644 --- a/app/controllers/admin/instances_controller.rb +++ b/app/controllers/admin/instances_controller.rb @@ -2,65 +2,31 @@ module Admin class InstancesController < BaseController - before_action :set_domain_block, only: :show - before_action :set_domain_allow, only: :show + before_action :set_instances, only: :index before_action :set_instance, only: :show def index authorize :instance, :index? - - @instances = ordered_instances end def show authorize :instance, :show? - - @following_count = Follow.where(account: Account.where(domain: params[:id])).count - @followers_count = Follow.where(target_account: Account.where(domain: params[:id])).count - @reports_count = Report.where(target_account: Account.where(domain: params[:id])).count - @blocks_count = Block.where(target_account: Account.where(domain: params[:id])).count - @available = DeliveryFailureTracker.available?(params[:id]) - @media_storage = MediaAttachment.where(account: Account.where(domain: params[:id])).sum(:file_file_size) - @private_comment = @domain_block&.private_comment - @public_comment = @domain_block&.public_comment end private - def set_domain_block - @domain_block = DomainBlock.rule_for(params[:id]) - end - - def set_domain_allow - @domain_allow = DomainAllow.rule_for(params[:id]) - end - def set_instance - resource = Account.by_domain_accounts.find_by(domain: params[:id]) - resource ||= @domain_block - resource ||= @domain_allow + @instance = Instance.find(params[:id]) + end - if resource - @instance = Instance.new(resource) - else - not_found - end + def set_instances + @instances = filtered_instances.page(params[:page]) end def filtered_instances InstanceFilter.new(whitelist_mode? ? { allowed: true } : filter_params).results end - def paginated_instances - filtered_instances.page(params[:page]) - end - - helper_method :paginated_instances - - def ordered_instances - paginated_instances.map { |resource| Instance.new(resource) } - end - def filter_params params.slice(*InstanceFilter::KEYS).permit(*InstanceFilter::KEYS) end diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..92b8b0d2b8a260feeda929d228a15465f2d36678 --- /dev/null +++ b/app/controllers/admin/ip_blocks_controller.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Admin + class IpBlocksController < BaseController + def index + authorize :ip_block, :index? + + @ip_blocks = IpBlock.page(params[:page]) + @form = Form::IpBlockBatch.new + end + + def new + authorize :ip_block, :create? + + @ip_block = IpBlock.new(ip: '', severity: :no_access, expires_in: 1.year) + end + + def create + authorize :ip_block, :create? + + @ip_block = IpBlock.new(resource_params) + + if @ip_block.save + log_action :create, @ip_block + redirect_to admin_ip_blocks_path, notice: I18n.t('admin.ip_blocks.created_msg') + else + render :new + end + end + + def batch + @form = Form::IpBlockBatch.new(form_ip_block_batch_params.merge(current_account: current_account, action: action_from_button)) + @form.save + rescue ActionController::ParameterMissing + flash[:alert] = I18n.t('admin.ip_blocks.no_ip_block_selected') + rescue Mastodon::NotPermittedError + flash[:alert] = I18n.t('admin.custom_emojis.not_permitted') + ensure + redirect_to admin_ip_blocks_path + end + + private + + def resource_params + params.require(:ip_block).permit(:ip, :severity, :comment, :expires_in) + end + + def action_from_button + 'delete' if params[:delete] + end + + def form_ip_block_batch_params + params.require(:form_ip_block_batch).permit(ip_block_ids: []) + end + end +end diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index 650195034691663baea2e47244abbf5c56da89d0..d7c192f0d6c9ed448d196339421f2f771253f811 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -14,7 +14,7 @@ module Admin @statuses = @account.statuses.where(visibility: [:public, :unlisted]) if params[:media] - account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct + account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).group(:status_id) @statuses.merge!(Status.where(id: account_media_status_ids)) end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 045e7dd2666061991c45f00bbb3e4757a42bd718..85f4cc7681a511461b29b42bf54f9b92c8f73ac3 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -40,7 +40,7 @@ class Api::BaseController < ApplicationController render json: { error: 'This action is not allowed' }, status: 403 end - rescue_from Mastodon::RaceConditionError do + rescue_from Mastodon::RaceConditionError, Seahorse::Client::NetworkingError, Stoplight::Error::RedLight do render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503 end @@ -71,6 +71,7 @@ class Api::BaseController < ApplicationController def limit_param(default_limit) return default_limit unless params[:limit] + [params[:limit].to_i.abs, default_limit * 2].min end @@ -95,14 +96,14 @@ class Api::BaseController < ApplicationController def require_user! if !current_user render json: { error: 'This method requires an authenticated user' }, status: 422 - elsif current_user.disabled? - render json: { error: 'Your login is currently disabled' }, status: 403 elsif !current_user.confirmed? render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403 elsif !current_user.approved? render json: { error: 'Your login is currently pending approval' }, status: 403 + elsif !current_user.functional? + render json: { error: 'Your login is currently disabled' }, status: 403 else - set_user_activity + update_user_sign_in end end diff --git a/app/controllers/api/v1/accounts/featured_tags_controller.rb b/app/controllers/api/v1/accounts/featured_tags_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..0101fb469b8bfabd4956363d44a918fca56c1e7a --- /dev/null +++ b/app/controllers/api/v1/accounts/featured_tags_controller.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class Api::V1::Accounts::FeaturedTagsController < Api::BaseController + before_action :set_account + before_action :set_featured_tags + + respond_to :json + + def index + render json: @featured_tags, each_serializer: REST::FeaturedTagSerializer + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end + + def set_featured_tags + @featured_tags = @account.suspended? ? [] : @account.featured_tags + end +end diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 2277067c9f45dd35800fd1ec9af3ad41eb463106..a665863ebf4816993aca4fdac80701ca3dd8babc 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController end def hide_results? - (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 93d4bd3a4a1efcf1c1ba5c076285f23c3708b356..7d885a212f2c349ad1490f0053f8654ae9bd32da 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController end def hide_results? - (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb index 8dad6fee9627488efca4b3b99395ff8b96f8dc8b..4b5f6902c7df95345cbbf3677d977f639b040813 100644 --- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController before_action :set_account def index - @proofs = @account.identity_proofs.active + @proofs = @account.suspended? ? [] : @account.identity_proofs.active render json: @proofs, each_serializer: REST::IdentityProofSerializer end diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb index ccb751f8f7dc64601e6cf3a23427be6ae24a9b70..c92f1f8a08d10ce54f6984a548f229056d71ae7c 100644 --- a/app/controllers/api/v1/accounts/lists_controller.rb +++ b/app/controllers/api/v1/accounts/lists_controller.rb @@ -6,7 +6,7 @@ class Api::V1::Accounts::ListsController < Api::BaseController before_action :set_account def index - @lists = @account.lists.where(account: current_account) + @lists = @account.suspended? ? [] : @account.lists.where(account: current_account) render json: @lists, each_serializer: REST::ListSerializer end diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index 1d3992a285770c93eb3c8a10696f2ba6faf8bbd8..503f85c97d79fca46fdf15009a04867e339ede46 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController before_action :require_user! def index - accounts = Account.where(id: account_ids).select('id') + accounts = Account.without_suspended.where(id: account_ids).select('id') # .where doesn't guarantee that our results are in the same order # we requested them, so return the "right" order to the requestor. @accounts = accounts.index_by(&:id).values_at(*account_ids).compact diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 114ee0a8244b9b964f2677c7356a08b238c97393..92ccb80615da26ad94dbebf6edccefe7c7c14fa0 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -18,14 +18,10 @@ class Api::V1::Accounts::StatusesController < Api::BaseController end def load_statuses - cached_account_statuses + @account.suspended? ? [] : cached_account_statuses end def cached_account_statuses - cache_collection account_statuses, Status - end - - def account_statuses statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses statuses.merge!(only_media_scope) if truthy_param?(:only_media) @@ -33,7 +29,12 @@ class Api::V1::Accounts::StatusesController < Api::BaseController statuses.merge!(no_reblogs_scope) if truthy_param?(:exclude_reblogs) statuses.merge!(hashtag_scope) if params[:tagged].present? - statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id)) + cache_collection_paginated_by_id( + statuses, + Status, + limit_param(DEFAULT_STATUSES_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) end def permitted_account_statuses @@ -41,17 +42,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController end def only_media_scope - Status.where(id: account_media_status_ids) - end - - def account_media_status_ids - # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. - # Also, Avoid getting slow by not narrowing down by `statuses.account_id`. - # When narrowing down by `statuses.account_id`, `index_statuses_20180106` will be used - # and the table will be joined by `Merge Semi Join`, so the query will be slow. - @account.statuses.joins(:media_attachments).merge(@account.media_attachments).permitted_for(@account, current_account) - .paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id]) - .reorder(id: :desc).distinct(:id).pluck(:id) + Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) end def pinned_scope diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 0080faf33071c5d36cfd7949c03f2da70e681407..3e66ff212eba9b9127f38ab25453a4b2ae900b77 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -9,7 +9,6 @@ class Api::V1::AccountsController < Api::BaseController before_action :require_user!, except: [:show, :create] before_action :set_account, except: [:create] - before_action :check_account_suspension, only: [:show] before_action :check_enabled_registrations, only: [:create] skip_before_action :require_authenticated_user!, only: :create @@ -21,7 +20,7 @@ class Api::V1::AccountsController < Api::BaseController end def create - token = AppSignUpService.new.call(doorkeeper_token.application, account_params) + token = AppSignUpService.new.call(doorkeeper_token.application, request.remote_ip, account_params) response = Doorkeeper::OAuth::TokenResponse.new(token) headers.merge!(response.headers) @@ -31,9 +30,8 @@ class Api::V1::AccountsController < Api::BaseController end def follow - FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true) - - options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } } + follow = FollowService.new.call(current_user.account, @account, reblogs: params.key?(:reblogs) ? truthy_param?(:reblogs) : nil, notify: params.key?(:notify) ? truthy_param?(:notify) : nil, with_rate_limit: true) + options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: follow.show_reblogs?, notify: follow.notify? } }, requested_map: { @account.id => false } } render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options) end @@ -44,7 +42,7 @@ class Api::V1::AccountsController < Api::BaseController end def mute - MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications)) + MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration] || 0)) render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships end @@ -73,10 +71,6 @@ class Api::V1::AccountsController < Api::BaseController AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options) end - def check_account_suspension - gone if @account.suspended? - end - def account_params params.permit(:username, :email, :password, :agreement, :locale, :reason) end diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb index c35ea5ab254ffe77f33f193ec9febb3818fae72b..63cc521ed0119912d5f6b9149bb03a0b2b5c2470 100644 --- a/app/controllers/api/v1/admin/accounts_controller.rb +++ b/app/controllers/api/v1/admin/accounts_controller.rb @@ -22,6 +22,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController active pending disabled + sensitized silenced suspended username @@ -58,7 +59,20 @@ class Api::V1::Admin::AccountsController < Api::BaseController def reject authorize @account.user, :reject? - SuspendAccountService.new.call(@account, reserve_email: false, reserve_username: false) + DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false) + render json: @account, serializer: REST::Admin::AccountSerializer + end + + def destroy + authorize @account, :destroy? + Admin::AccountDeletionWorker.perform_async(@account.id) + render json: @account, serializer: REST::Admin::AccountSerializer + end + + def unsensitive + authorize @account, :unsensitive? + @account.unsensitize! + log_action :unsensitive, @account render json: @account, serializer: REST::Admin::AccountSerializer end @@ -72,6 +86,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController def unsuspend authorize @account, :unsuspend? @account.unsuspend! + Admin::UnsuspensionWorker.perform_async(@account.id) log_action :unsuspend, @account render json: @account, serializer: REST::Admin::AccountSerializer end @@ -79,7 +94,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController private def set_accounts - @accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + @accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def set_account diff --git a/app/controllers/api/v1/admin/reports_controller.rb b/app/controllers/api/v1/admin/reports_controller.rb index 1d48d3160fc7b28e54bf5f1932ddd53ef3ef1aac..c8f4cd8d80c828cf94e32df107720a81733ab19a 100644 --- a/app/controllers/api/v1/admin/reports_controller.rb +++ b/app/controllers/api/v1/admin/reports_controller.rb @@ -63,7 +63,7 @@ class Api::V1::Admin::ReportsController < Api::BaseController private def set_reports - @reports = filtered_reports.order(id: :desc).with_accounts.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + @reports = filtered_reports.order(id: :desc).with_accounts.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def set_report diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index a2baeef900cbf6a84aceef8d871948d781e62ba6..586cdfca9d4e6b71be8a25debf30389a33ff3f80 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -18,6 +18,8 @@ class Api::V1::BlocksController < Api::BaseController def paginated_blocks @paginated_blocks ||= Block.eager_load(target_account: :account_stat) + .joins(:target_account) + .merge(Account.without_suspended) .where(account: current_account) .paginate_by_max_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index c15212f0a91dd4be00891f91dd3ebf0f1d7fa1a8..aa3fb88f08f19267b896dbb8d9b196f8699a9c4e 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -17,14 +17,11 @@ class Api::V1::BookmarksController < Api::BaseController end def cached_bookmarks - cache_collection( - Status.reorder(nil).joins(:bookmarks).merge(results), - Status - ) + cache_collection(results.map(&:status), Status) end def results - @_results ||= account_bookmarks.paginate_by_id( + @_results ||= account_bookmarks.eager_load(:status).to_a_paginated_by_id( limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id) ) diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb index bc801337945d6d1019caad248a5518317a36f5b5..6c7583403758e2e2877b58c563a0a5ed60fd675f 100644 --- a/app/controllers/api/v1/conversations_controller.rb +++ b/app/controllers/api/v1/conversations_controller.rb @@ -32,7 +32,7 @@ class Api::V1::ConversationsController < Api::BaseController def paginated_conversations AccountConversation.where(account: current_account) - .paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + .to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def insert_pagination_headers diff --git a/app/controllers/api/v1/crypto/encrypted_messages_controller.rb b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb index c764915e578e19dbd249fdcf503b7c8827079e6a..68cf4384f79bd0c5d2f0389f67f021b4a3628146 100644 --- a/app/controllers/api/v1/crypto/encrypted_messages_controller.rb +++ b/app/controllers/api/v1/crypto/encrypted_messages_controller.rb @@ -26,7 +26,7 @@ class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController end def set_encrypted_messages - @encrypted_messages = @current_device.encrypted_messages.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) + @encrypted_messages = @current_device.encrypted_messages.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) end def insert_pagination_headers diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb index c87dbc4ce836a7de5d70b5ed170d2415da2ff98e..9e80f468a780251ba20c3726597bd5c6c2abfe6b 100644 --- a/app/controllers/api/v1/endorsements_controller.rb +++ b/app/controllers/api/v1/endorsements_controller.rb @@ -25,7 +25,7 @@ class Api::V1::EndorsementsController < Api::BaseController end def endorsed_accounts - current_account.endorsed_accounts.includes(:account_stat) + current_account.endorsed_accounts.includes(:account_stat).without_suspended end def insert_pagination_headers diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb index 3e242905da753f466229cae40f9c36a24b4fb913..21836bc170cbbc7915cd188c84e90e2163ab83e0 100644 --- a/app/controllers/api/v1/favourites_controller.rb +++ b/app/controllers/api/v1/favourites_controller.rb @@ -17,14 +17,11 @@ class Api::V1::FavouritesController < Api::BaseController end def cached_favourites - cache_collection( - Status.reorder(nil).joins(:favourites).merge(results), - Status - ) + cache_collection(results.map(&:status), Status) end def results - @_results ||= account_favourites.paginate_by_id( + @_results ||= account_favourites.eager_load(:status).to_a_paginated_by_id( limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id) ) diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index 8c1b81a0f007add18175283368216c494d09500c..75545d3c7f7930546e13d4d6421840f29831b860 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -3,15 +3,15 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index before_action :require_user! - before_action :set_most_used_tags, only: :index + before_action :set_recently_used_tags, only: :index def index - render json: @most_used_tags, each_serializer: REST::TagSerializer + render json: @recently_used_tags, each_serializer: REST::TagSerializer end private - def set_most_used_tags - @most_used_tags = Tag.most_used(current_account).where.not(id: current_account.featured_tags).limit(10) + def set_recently_used_tags + @recently_used_tags = Tag.recently_used(current_account).where.not(id: current_account.featured_tags).limit(10) end end diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb index 0ee6e531f07a4abacea52ccae938a14fdd92deb1..b34c76f29e97e12b421193b607800175b5952d3e 100644 --- a/app/controllers/api/v1/follow_requests_controller.rb +++ b/app/controllers/api/v1/follow_requests_controller.rb @@ -13,7 +13,7 @@ class Api::V1::FollowRequestsController < Api::BaseController def authorize AuthorizeFollowService.new.call(account, current_account) - NotifyService.new.call(current_account, Follow.find_by(account: account, target_account: current_account)) + NotifyService.new.call(current_account, :follow, Follow.find_by(account: account, target_account: current_account)) render json: account, serializer: REST::RelationshipSerializer, relationships: relationships end @@ -37,7 +37,7 @@ class Api::V1::FollowRequestsController < Api::BaseController end def default_accounts - Account.includes(:follow_requests, :account_stat).references(:follow_requests) + Account.without_suspended.includes(:follow_requests, :account_stat).references(:follow_requests) end def paginated_follow_requests diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb index 9fa4409357b62dc526889f44d6ef777d320b59af..2877fec52d8020bf55878662c6a03093cab2e48c 100644 --- a/app/controllers/api/v1/instances/peers_controller.rb +++ b/app/controllers/api/v1/instances/peers_controller.rb @@ -8,7 +8,7 @@ class Api::V1::Instances::PeersController < Api::BaseController def index expires_in 1.day, public: true - render_with_cache(expires_in: 1.day) { Account.remote.domains } + render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) } end private diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb index 23078263e7abdd70843a62906245afd35774fb3b..b66ea9bfe609d8b988fdce90bfcf070830b292b9 100644 --- a/app/controllers/api/v1/lists/accounts_controller.rb +++ b/app/controllers/api/v1/lists/accounts_controller.rb @@ -37,9 +37,9 @@ class Api::V1::Lists::AccountsController < Api::BaseController def load_accounts if unlimited? - @list.accounts.includes(:account_stat).all + @list.accounts.without_suspended.includes(:account_stat).all else - @list.accounts.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]) + @list.accounts.without_suspended.includes(:account_stat).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]) end end diff --git a/app/controllers/api/v1/lists_controller.rb b/app/controllers/api/v1/lists_controller.rb index 054172bee3aa64e25a19751bda99d814854bdc61..e5ac45fefb3bd3d479e619d0a603089060cdc79f 100644 --- a/app/controllers/api/v1/lists_controller.rb +++ b/app/controllers/api/v1/lists_controller.rb @@ -38,6 +38,6 @@ class Api::V1::ListsController < Api::BaseController end def list_params - params.permit(:title) + params.permit(:title, :replies_policy) end end diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb index 65439fe9bc1505e9005b1d8719ab4b1483df1541..fd52511d7eb0497d018551d61233a7a5b1d33666 100644 --- a/app/controllers/api/v1/mutes_controller.rb +++ b/app/controllers/api/v1/mutes_controller.rb @@ -7,7 +7,7 @@ class Api::V1::MutesController < Api::BaseController def index @accounts = load_accounts - render json: @accounts, each_serializer: REST::AccountSerializer + render json: @accounts, each_serializer: REST::MutedAccountSerializer end private @@ -18,6 +18,8 @@ class Api::V1::MutesController < Api::BaseController def paginated_mutes @paginated_mutes ||= Mute.eager_load(:target_account) + .joins(:target_account) + .merge(Account.without_suspended) .where(account: current_account) .paginate_by_max_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index 8ac22776500b9bdaaccf30a83b561391313f9e40..522c35ba5483e5fb89f0c1003dc2519e7ecb2b94 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -14,7 +14,7 @@ class Api::V1::NotificationsController < Api::BaseController end def show - @notification = current_account.notifications.find(params[:id]) + @notification = current_account.notifications.without_suspended.find(params[:id]) render json: @notification, serializer: REST::NotificationSerializer end @@ -31,18 +31,16 @@ class Api::V1::NotificationsController < Api::BaseController private def load_notifications - cache_collection paginated_notifications, Notification - end - - def paginated_notifications - browserable_account_notifications.paginate_by_id( + cache_collection_paginated_by_id( + browserable_account_notifications, + Notification, limit_param(DEFAULT_NOTIFICATIONS_LIMIT), params_slice(:max_id, :since_id, :min_id) ) end def browserable_account_notifications - current_account.notifications.browserable(exclude_types, from_account) + current_account.notifications.without_suspended.browserable(exclude_types, from_account) end def target_statuses_from_notifications diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb index d34b333eb3ae8a3bfd423c6ac25d5b0e576bed1a..0918c61e972747c4ded6fbfc599cbacf3659bd20 100644 --- a/app/controllers/api/v1/push/subscriptions_controller.rb +++ b/app/controllers/api/v1/push/subscriptions_controller.rb @@ -52,6 +52,6 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController def data_params return {} if params[:data].blank? - params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll]) + params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status]) end end diff --git a/app/controllers/api/v1/scheduled_statuses_controller.rb b/app/controllers/api/v1/scheduled_statuses_controller.rb index 9950296f3bc8f72b2ccd9930144daf4e6d630aa9..f90642a7389d7a540621ff8b03ac68952a4357c5 100644 --- a/app/controllers/api/v1/scheduled_statuses_controller.rb +++ b/app/controllers/api/v1/scheduled_statuses_controller.rb @@ -32,7 +32,7 @@ class Api::V1::ScheduledStatusesController < Api::BaseController private def set_statuses - @statuses = current_account.scheduled_statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id)) + @statuses = current_account.scheduled_statuses.to_a_paginated_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id)) end def set_status diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb index 3954af3c9bf2f16e9dd9574f7884c88e221c1889..19963c002ad3d46043052f6afc17d85ce9060b4d 100644 --- a/app/controllers/api/v1/statuses/bookmarks_controller.rb +++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' } before_action :require_user! - before_action :set_status + before_action :set_status, only: [:create] def create current_account.bookmarks.find_or_create_by!(account: current_account, status: @status) @@ -13,10 +13,20 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController end def destroy - bookmark = current_account.bookmarks.find_by(status: @status) + bookmark = current_account.bookmarks.find_by(status_id: params[:status_id]) + + if bookmark + @status = bookmark.status + else + @status = Status.find(params[:status_id]) + authorize @status, :show? + end + bookmark&.destroy! render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, bookmarks_map: { @status.id => false }) + rescue Mastodon::NotPermittedError + not_found end private diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 8229786d6cccaba018e9535b1be0be87533ce192..2b614a83756a251f94371e414733ba8539fc2c0f 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -22,6 +22,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController def default_accounts Account + .without_suspended .includes(:favourites, :account_stat) .references(:favourites) .where(favourites: { status_id: @status.id }) diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb index 7afa822ed8740c2a1cd9b732fb673b015fa6fb3e..2e21ce6a06180122a98f159fa05079bb9117eb12 100644 --- a/app/controllers/api/v1/statuses/favourites_controller.rb +++ b/app/controllers/api/v1/statuses/favourites_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:favourites' } before_action :require_user! - before_action :set_status + before_action :set_status, only: [:create] def create FavouriteService.new.call(current_account, @status) @@ -13,8 +13,19 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController end def destroy - UnfavouriteWorker.perform_async(current_account.id, @status.id) + fav = current_account.favourites.find_by(status_id: params[:status_id]) + + if fav + @status = fav.status + UnfavouriteWorker.perform_async(current_account.id, @status.id) + else + @status = Status.find(params[:status_id]) + authorize @status, :show? + end + render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, favourites_map: { @status.id => false }) + rescue Mastodon::NotPermittedError + not_found end private diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index 6c9e49d903a4124770b81a21b64668873c796ab7..24db30fcc015d9e018b73afea62eba8c4a222c62 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -21,7 +21,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController end def default_accounts - Account.includes(:statuses, :account_stat).references(:statuses) + Account.without_suspended.includes(:statuses, :account_stat).references(:statuses) end def paginated_statuses diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 03bbd59affb4c5df8bb2db23be4fb670fbf74989..eb828e9420ffca244a6127183ef3fb049963993b 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -59,6 +59,7 @@ class Api::V1::StatusesController < Api::BaseController @status.discard RemovalWorker.perform_async(@status.id, redraft: true) + @status.account.statuses_count = @status.account.statuses_count - 1 render json: @status, serializer: REST::StatusSerializer, source_requested: true end diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index c6e7854d93008fc328a1f8f6757cdd3176385eb6..d253b744f99bf9d24ff29369b3f4e307cbec1217 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -16,30 +16,29 @@ class Api::V1::Timelines::PublicController < Api::BaseController end def load_statuses - cached_public_statuses + cached_public_statuses_page end - def cached_public_statuses - cache_collection public_statuses, Status + def cached_public_statuses_page + cache_collection(public_statuses, Status) end def public_statuses - statuses = public_timeline_statuses.paginate_by_id( + public_feed.get( limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) + params[:max_id], + params[:since_id], + params[:min_id] ) - - if truthy_param?(:only_media) - # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. - status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id) - statuses.where(id: status_ids) - else - statuses - end end - def public_timeline_statuses - Status.as_public_timeline(current_account, truthy_param?(:remote) ? :remote : truthy_param?(:local)) + def public_feed + PublicFeed.new( + current_account, + local: truthy_param?(:local), + remote: truthy_param?(:remote), + only_media: truthy_param?(:only_media) + ) end def insert_pagination_headers diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 2d6ad5a80c5bc3fc09ec8020cf112027cdf3c6ab..64a1db58df3ae76094012d1789ad0d3b1c97a84f 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -20,30 +20,29 @@ class Api::V1::Timelines::TagController < Api::BaseController end def cached_tagged_statuses - cache_collection tagged_statuses, Status + @tag.nil? ? [] : cache_collection(tag_timeline_statuses, Status) end - def tagged_statuses - if @tag.nil? - [] - else - statuses = tag_timeline_statuses.paginate_by_id( - limit_param(DEFAULT_STATUSES_LIMIT), - params_slice(:max_id, :since_id, :min_id) - ) - - if truthy_param?(:only_media) - # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids. - status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id) - statuses.where(id: status_ids) - else - statuses - end - end + def tag_timeline_statuses + tag_feed.get( + limit_param(DEFAULT_STATUSES_LIMIT), + params[:max_id], + params[:since_id], + params[:min_id] + ) end - def tag_timeline_statuses - HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none), current_account, truthy_param?(:local)) + def tag_feed + TagFeed.new( + @tag, + current_account, + any: params[:any], + all: params[:all], + none: params[:none], + local: truthy_param?(:local), + remote: truthy_param?(:remote), + only_media: truthy_param?(:only_media) + ) end def insert_pagination_headers diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index 7916b82fa081535f5d692a1f0639c944d834114b..1dce3e70f2aec090499e8debba0745dec3a17879 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -22,6 +22,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController reblog: alerts_enabled, mention: alerts_enabled, poll: alerts_enabled, + status: alerts_enabled, }, } @@ -57,6 +58,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController end def data_params - @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll]) + @data_params ||= params.require(:data).permit(alerts: [:follow, :follow_request, :favourite, :reblog, :mention, :poll, :status]) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 973db6aca97654a173468715f42a86959251eec1..44616d6e5ee45e35a8609946126d5fd9cfe2f38c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -28,7 +28,7 @@ class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from Mastodon::NotPermittedError, with: :forbidden rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error - rescue_from Mastodon::RaceConditionError, with: :service_unavailable + rescue_from Mastodon::RaceConditionError, Seahorse::Client::NetworkingError, Stoplight::Error::RedLight, with: :service_unavailable rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? @@ -55,7 +55,7 @@ class ApplicationController < ActionController::Base end def store_current_location - store_location_for(:user, request.url) unless request.format == :json + store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym) end def require_admin! diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index d319662486a87babafd7e6946566054741139bcc..a3114ab2532aad6a9b201b5f0ee6ad8f15163bf3 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -2,6 +2,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController include Devise::Controllers::Rememberable + include RegistrationSpamConcern layout :determine_layout @@ -13,6 +14,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController before_action :set_body_classes, only: [:new, :create, :edit, :update] before_action :require_not_suspended!, only: [:update] before_action :set_cache_headers, only: [:edit, :update] + before_action :set_registration_form_time, only: :new skip_before_action :require_functional!, only: [:edit, :update] @@ -45,16 +47,17 @@ class Auth::RegistrationsController < Devise::RegistrationsController def build_resource(hash = nil) super(hash) - resource.locale = I18n.locale - resource.invite_code = params[:invite_code] if resource.invite_code.blank? - resource.current_sign_in_ip = request.remote_ip + resource.locale = I18n.locale + resource.invite_code = params[:invite_code] if resource.invite_code.blank? + resource.registration_form_time = session[:registration_form_time] + resource.sign_up_ip = request.remote_ip resource.build_account if resource.account.nil? end def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up) do |u| - u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement) + u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password) end end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 1fd755334b359e3bfdaeaf018636ace9100e69c8..13d158c67613a8ed9f0ab8b450eff2e31db6d271 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -7,6 +7,7 @@ class Auth::SessionsController < Devise::SessionsController skip_before_action :require_no_authentication, only: [:create] skip_before_action :require_functional! + skip_before_action :update_user_sign_in include TwoFactorAuthenticationConcern include SignInTokenAuthenticationConcern @@ -24,6 +25,7 @@ class Auth::SessionsController < Devise::SessionsController def create super do |resource| + resource.update_sign_in!(request, new_sign_in: true) remember_me(resource) flash.delete(:notice) end @@ -37,11 +39,27 @@ class Auth::SessionsController < Devise::SessionsController store_location_for(:user, tmp_stored_location) if continue_after? end + def webauthn_options + user = find_user + + if user.webauthn_enabled? + options_for_get = WebAuthn::Credential.options_for_get( + allow: user.webauthn_credentials.pluck(:external_id) + ) + + session[:webauthn_challenge] = options_for_get.challenge + + render json: options_for_get, status: :ok + else + render json: { error: t('webauthn_credentials.not_enabled') }, status: :unauthorized + end + end + protected def find_user if session[:attempt_user_id] - User.find(session[:attempt_user_id]) + User.find_by(id: session[:attempt_user_id]) else user = User.authenticate_with_ldap(user_params) if Devise.ldap_authentication user ||= User.authenticate_with_pam(user_params) if Devise.pam_authentication @@ -51,7 +69,7 @@ class Auth::SessionsController < Devise::SessionsController end def user_params - params.require(:user).permit(:email, :password, :otp_attempt, :sign_in_token_attempt) + params.require(:user).permit(:email, :password, :otp_attempt, :sign_in_token_attempt, credential: {}) end def after_sign_in_path_for(resource) @@ -74,6 +92,7 @@ class Auth::SessionsController < Devise::SessionsController def require_no_authentication super + # Delete flash message that isn't entirely useful and may be confusing in # most cases because /web doesn't display/clear flash messages. flash.delete(:alert) if flash[:alert] == I18n.t('devise.failure.already_authenticated') @@ -91,13 +110,30 @@ class Auth::SessionsController < Devise::SessionsController def home_paths(resource) paths = [about_path] + if single_user_mode? && resource.is_a?(User) paths << short_account_path(username: resource.account) end + paths end def continue_after? truthy_param?(:continue) end + + def restart_session + clear_attempt_from_session + redirect_to new_user_session_path, alert: I18n.t('devise.failure.timeout') + end + + def set_attempt_session(user) + session[:attempt_user_id] = user.id + session[:attempt_user_updated_at] = user.updated_at.to_s + end + + def clear_attempt_from_session + session.delete(:attempt_user_id) + session.delete(:attempt_user_updated_at) + end end diff --git a/app/controllers/concerns/account_owned_concern.rb b/app/controllers/concerns/account_owned_concern.rb index 460f71f65faf8da8f90d00ef4a36d4c9960ece43..62e379846a6a62c616a8cd879e2b89acc70de493 100644 --- a/app/controllers/concerns/account_owned_concern.rb +++ b/app/controllers/concerns/account_owned_concern.rb @@ -29,6 +29,24 @@ module AccountOwnedConcern end def check_account_suspension - expires_in(3.minutes, public: true) && gone if @account.suspended? + if @account.suspended_permanently? + permanent_suspension_response + elsif @account.suspended? && !skip_temporary_suspension_response? + temporary_suspension_response + end + end + + def skip_temporary_suspension_response? + false + end + + def permanent_suspension_response + expires_in(3.minutes, public: true) + gone + end + + def temporary_suspension_response + expires_in(3.minutes, public: true) + forbidden end end diff --git a/app/controllers/concerns/cache_concern.rb b/app/controllers/concerns/cache_concern.rb index c7d25ae00c85e019093284d5ef288bdd8c9ef068..abbdb410a59fb8d7fd626c4272b72061c23a0c05 100644 --- a/app/controllers/concerns/cache_concern.rb +++ b/app/controllers/concerns/cache_concern.rb @@ -47,4 +47,8 @@ module CacheConcern raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact end + + def cache_collection_paginated_by_id(raw, klass, limit, options) + cache_collection raw.cache_ids.to_a_paginated_by_id(limit, options), klass + end end diff --git a/app/controllers/concerns/challengable_concern.rb b/app/controllers/concerns/challengable_concern.rb index b29d90b3cc32d62c0d66e49d139ff44d6aee4841..2995a25e096296218adf23d244cf09d265119371 100644 --- a/app/controllers/concerns/challengable_concern.rb +++ b/app/controllers/concerns/challengable_concern.rb @@ -32,7 +32,6 @@ module ChallengableConcern if params.key?(:form_challenge) if challenge_passed? session[:challenge_passed_at] = Time.now.utc - return else flash.now[:alert] = I18n.t('challenge.invalid_password') render_challenge diff --git a/app/controllers/concerns/export_controller_concern.rb b/app/controllers/concerns/export_controller_concern.rb index bfe990c827d1bf9cf085e05553fc1b375a372b84..24cfc7a01248325e39db739b61b53f8745bce813 100644 --- a/app/controllers/concerns/export_controller_concern.rb +++ b/app/controllers/concerns/export_controller_concern.rb @@ -5,7 +5,6 @@ module ExportControllerConcern included do before_action :authenticate_user! - before_action :require_not_suspended! before_action :load_export skip_before_action :require_functional! @@ -30,8 +29,4 @@ module ExportControllerConcern def export_filename "#{controller_name}.csv" end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/concerns/registration_spam_concern.rb b/app/controllers/concerns/registration_spam_concern.rb new file mode 100644 index 0000000000000000000000000000000000000000..af434c985a0c962dd208f5d7316b85281b057acb --- /dev/null +++ b/app/controllers/concerns/registration_spam_concern.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module RegistrationSpamConcern + extend ActiveSupport::Concern + + def set_registration_form_time + session[:registration_form_time] = Time.now.utc + end +end diff --git a/app/controllers/concerns/sign_in_token_authentication_concern.rb b/app/controllers/concerns/sign_in_token_authentication_concern.rb index 91f813acc3508c06d88de491734290d6a92a6ab2..3c95a4afd2cf664cd465c0a40f2e3b9683bf3f7f 100644 --- a/app/controllers/concerns/sign_in_token_authentication_concern.rb +++ b/app/controllers/concerns/sign_in_token_authentication_concern.rb @@ -18,7 +18,9 @@ module SignInTokenAuthenticationConcern def authenticate_with_sign_in_token user = self.resource = find_user - if user_params[:sign_in_token_attempt].present? && session[:attempt_user_id] + if user.present? && session[:attempt_user_id].present? && session[:attempt_user_updated_at] != user.updated_at.to_s + restart_session + elsif user_params.key?(:sign_in_token_attempt) && session[:attempt_user_id] authenticate_with_sign_in_token_attempt(user) elsif user.present? && user.external_or_valid_password?(user_params[:password]) prompt_for_sign_in_token(user) @@ -27,7 +29,7 @@ module SignInTokenAuthenticationConcern def authenticate_with_sign_in_token_attempt(user) if valid_sign_in_token_attempt?(user) - session.delete(:attempt_user_id) + clear_attempt_from_session remember_me(user) sign_in(user) else @@ -42,10 +44,10 @@ module SignInTokenAuthenticationConcern UserMailer.sign_in_token(user, request.remote_ip, request.user_agent, Time.now.utc.to_s).deliver_later! end - set_locale do - session[:attempt_user_id] = user.id - @body_classes = 'lighter' - render :sign_in_token - end + set_attempt_session(user) + + @body_classes = 'lighter' + + set_locale { render :sign_in_token } end end diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 10efbf2e0b8befbc997294d4076c06c8732338ed..fc3978fbbdd4f31099a7891fc4522bf816c8725e 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -7,6 +7,44 @@ module SignatureVerification include DomainControlHelper + EXPIRATION_WINDOW_LIMIT = 12.hours + CLOCK_SKEW_MARGIN = 1.hour + + class SignatureVerificationError < StandardError; end + + class SignatureParamsParser < Parslet::Parser + rule(:token) { match("[0-9a-zA-Z!#$%&'*+.^_`|~-]").repeat(1).as(:token) } + rule(:quoted_string) { str('"') >> (qdtext | quoted_pair).repeat.as(:quoted_string) >> str('"') } + # qdtext and quoted_pair are not exactly according to spec but meh + rule(:qdtext) { match('[^\\\\"]') } + rule(:quoted_pair) { str('\\') >> any } + rule(:bws) { match('\s').repeat } + rule(:param) { (token.as(:key) >> bws >> str('=') >> bws >> (token | quoted_string).as(:value)).as(:param) } + rule(:comma) { bws >> str(',') >> bws } + # Old versions of node-http-signature add an incorrect "Signature " prefix to the header + rule(:buggy_prefix) { str('Signature ') } + rule(:params) { buggy_prefix.maybe >> (param >> (comma >> param).repeat).as(:params) } + root(:params) + end + + class SignatureParamsTransformer < Parslet::Transform + rule(params: subtree(:p)) do + (p.is_a?(Array) ? p : [p]).each_with_object({}) { |(key, val), h| h[key] = val } + end + + rule(param: { key: simple(:key), value: simple(:val) }) do + [key, val] + end + + rule(quoted_string: simple(:string)) do + string.to_s + end + + rule(token: simple(:string)) do + string.to_s + end + end + def require_signature! render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account end @@ -24,72 +62,41 @@ module SignatureVerification end def signature_key_id - raw_signature = request.headers['Signature'] - signature_params = {} - - raw_signature.split(',').each do |part| - parsed_parts = part.match(/([a-z]+)="([^"]+)"/i) - next if parsed_parts.nil? || parsed_parts.size != 3 - signature_params[parsed_parts[1]] = parsed_parts[2] - end - signature_params['keyId'] + rescue SignatureVerificationError + nil end def signed_request_account return @signed_request_account if defined?(@signed_request_account) - unless signed_request? - @signature_verification_failure_reason = 'Request not signed' - @signed_request_account = nil - return - end - - if request.headers['Date'].present? && !matches_time_window? - @signature_verification_failure_reason = 'Signed request date outside acceptable time window' - @signed_request_account = nil - return - end - - raw_signature = request.headers['Signature'] - signature_params = {} - - raw_signature.split(',').each do |part| - parsed_parts = part.match(/([a-z]+)="([^"]+)"/i) - next if parsed_parts.nil? || parsed_parts.size != 3 - signature_params[parsed_parts[1]] = parsed_parts[2] - end + raise SignatureVerificationError, 'Request not signed' unless signed_request? + raise SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters? + raise SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm) + raise SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window? - if incompatible_signature?(signature_params) - @signature_verification_failure_reason = 'Incompatible request signature' - @signed_request_account = nil - return - end + verify_signature_strength! + verify_body_digest! account = account_from_key_id(signature_params['keyId']) - if account.nil? - @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}" - @signed_request_account = nil - return - end + raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil? signature = Base64.decode64(signature_params['signature']) - compare_signed_string = build_signed_string(signature_params['headers']) + compare_signed_string = build_signed_string return account unless verify_signature(account, signature, compare_signed_string).nil? account = stoplight_wrap_request { account.possibly_stale? ? account.refresh! : account_refresh_key(account) } - if account.nil? - @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}" - @signed_request_account = nil - return - end + raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil? return account unless verify_signature(account, signature, compare_signed_string).nil? - @signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}" + @signature_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)" + @signed_request_account = nil + rescue SignatureVerificationError => e + @signature_verification_failure_reason = e.message @signed_request_account = nil end @@ -99,8 +106,42 @@ module SignatureVerification private + def signature_params + @signature_params ||= begin + raw_signature = request.headers['Signature'] + tree = SignatureParamsParser.new.parse(raw_signature) + SignatureParamsTransformer.new.apply(tree) + end + rescue Parslet::ParseFailed + raise SignatureVerificationError, 'Error parsing signature parameters' + end + + def signature_algorithm + signature_params.fetch('algorithm', 'hs2019') + end + + def signed_headers + signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split(' ') + end + + def verify_signature_strength! + raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)') + raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(Request::REQUEST_TARGET) || signed_headers.include?('digest') + raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host') + raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest') + end + + def verify_body_digest! + return unless signed_headers.include?('digest') + + digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] } + sha256 = digests.assoc('sha-256') + raise SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil? + raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}" if body_digest != sha256[1] + end + def verify_signature(account, signature, compare_signed_string) - if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string) + if account.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string) @signed_request_account = account @signed_request_account end @@ -108,14 +149,20 @@ module SignatureVerification nil end - def build_signed_string(signed_headers) - signed_headers = 'date' if signed_headers.blank? - - signed_headers.downcase.split(' ').map do |signed_header| + def build_signed_string + signed_headers.map do |signed_header| if signed_header == Request::REQUEST_TARGET "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" - elsif signed_header == 'digest' - "digest: #{body_digest}" + elsif signed_header == '(created)' + raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019' + raise SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank? + + "(created): #{signature_params['created']}" + elsif signed_header == '(expires)' + raise SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019' + raise SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank? + + "(expires): #{signature_params['expires']}" else "#{signed_header}: #{request.headers[to_header_name(signed_header)]}" end @@ -123,26 +170,40 @@ module SignatureVerification end def matches_time_window? + created_time = nil + expires_time = nil + begin - time_sent = Time.httpdate(request.headers['Date']) + if signature_algorithm == 'hs2019' && signature_params['created'].present? + created_time = Time.at(signature_params['created'].to_i).utc + elsif request.headers['Date'].present? + created_time = Time.httpdate(request.headers['Date']).utc + end + + expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present? rescue ArgumentError return false end - (Time.now.utc - time_sent).abs <= 12.hours + expires_time ||= created_time + 5.minutes unless created_time.nil? + expires_time = [expires_time, created_time + EXPIRATION_WINDOW_LIMIT].min unless created_time.nil? + + return false if created_time.present? && created_time > Time.now.utc + CLOCK_SKEW_MARGIN + return false if expires_time.present? && Time.now.utc > expires_time + CLOCK_SKEW_MARGIN + + true end def body_digest - "SHA-256=#{Digest::SHA256.base64digest(request_body)}" + @body_digest ||= Digest::SHA256.base64digest(request_body) end def to_header_name(name) name.split(/-/).map(&:capitalize).join('-') end - def incompatible_signature?(signature_params) - signature_params['keyId'].blank? || - signature_params['signature'].blank? + def missing_required_signature_parameters? + signature_params['keyId'].blank? || signature_params['signature'].blank? end def account_from_key_id(key_id) diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index daafe56f4602d4cab477359ccf968c38e7ef30c0..4d4ccf49c8ce67d8f9778563f9190335d98b9edd 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -8,7 +8,23 @@ module TwoFactorAuthenticationConcern end def two_factor_enabled? - find_user&.otp_required_for_login? + find_user&.two_factor_enabled? + end + + def valid_webauthn_credential?(user, webauthn_credential) + user_credential = user.webauthn_credentials.find_by!(external_id: webauthn_credential.id) + + begin + webauthn_credential.verify( + session[:webauthn_challenge], + public_key: user_credential.public_key, + sign_count: user_credential.sign_count + ) + + user_credential.update!(sign_count: webauthn_credential.sign_count) + rescue WebAuthn::Error + false + end end def valid_otp_attempt?(user) @@ -21,16 +37,33 @@ module TwoFactorAuthenticationConcern def authenticate_with_two_factor user = self.resource = find_user - if user_params[:otp_attempt].present? && session[:attempt_user_id] - authenticate_with_two_factor_attempt(user) + if user.present? && session[:attempt_user_id].present? && session[:attempt_user_updated_at] != user.updated_at.to_s + restart_session + elsif user.webauthn_enabled? && user_params.key?(:credential) && session[:attempt_user_id] + authenticate_with_two_factor_via_webauthn(user) + elsif user_params.key?(:otp_attempt) && session[:attempt_user_id] + authenticate_with_two_factor_via_otp(user) elsif user.present? && user.external_or_valid_password?(user_params[:password]) prompt_for_two_factor(user) end end - def authenticate_with_two_factor_attempt(user) + def authenticate_with_two_factor_via_webauthn(user) + webauthn_credential = WebAuthn::Credential.from_get(user_params[:credential]) + + if valid_webauthn_credential?(user, webauthn_credential) + clear_attempt_from_session + remember_me(user) + sign_in(user) + render json: { redirect_path: root_path }, status: :ok + else + render json: { error: t('webauthn_credentials.invalid_credential') }, status: :unprocessable_entity + end + end + + def authenticate_with_two_factor_via_otp(user) if valid_otp_attempt?(user) - session.delete(:attempt_user_id) + clear_attempt_from_session remember_me(user) sign_in(user) else @@ -40,10 +73,18 @@ module TwoFactorAuthenticationConcern end def prompt_for_two_factor(user) - set_locale do - session[:attempt_user_id] = user.id - @body_classes = 'lighter' - render :two_factor + set_attempt_session(user) + + @body_classes = 'lighter' + @webauthn_enabled = user.webauthn_enabled? + @scheme_type = begin + if user.webauthn_enabled? && user_params[:otp_attempt].blank? + 'webauthn' + else + 'totp' + end end + + set_locale { render :two_factor } end end diff --git a/app/controllers/concerns/user_tracking_concern.rb b/app/controllers/concerns/user_tracking_concern.rb index be10705fcc1d8b69bfef7ae672ae5b1494513bdb..efda37fae75cb7649b960c1748dc173c81c0a260 100644 --- a/app/controllers/concerns/user_tracking_concern.rb +++ b/app/controllers/concerns/user_tracking_concern.rb @@ -6,14 +6,13 @@ module UserTrackingConcern UPDATE_SIGN_IN_HOURS = 24 included do - before_action :set_user_activity + before_action :update_user_sign_in end private - def set_user_activity - return unless user_needs_sign_in_update? - current_user.update_tracked_fields!(request) + def update_user_sign_in + current_user.update_sign_in!(request) if user_needs_sign_in_update? end def user_needs_sign_in_update? diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index 63d9d9cd37244fe81d84db26b413f7040c4ec0ec..79a1ab02b1fb7fbe7b03a0bc3b5b3d30221f609a 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -9,7 +9,7 @@ class FiltersController < ApplicationController before_action :set_body_classes def index - @filters = current_account.custom_filters + @filters = current_account.custom_filters.order(:phrase) end def new diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index ab0749963403544d7324c44743ecd4fd4a0fef16..ff4df2adfca9c1ad9fc8cd6f96f07b0a7e42084c 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -52,6 +52,14 @@ class FollowerAccountsController < ApplicationController account_followers_url(@account, page: page) unless page.nil? end + def next_page_url + page_url(follows.next_page) if follows.respond_to?(:next_page) + end + + def prev_page_url + page_url(follows.prev_page) if follows.respond_to?(:prev_page) + end + def collection_presenter if page_requested? ActivityPub::CollectionPresenter.new( @@ -60,8 +68,8 @@ class FollowerAccountsController < ApplicationController size: @account.followers_count, items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) }, part_of: account_followers_url(@account), - next: page_url(follows.next_page), - prev: page_url(follows.prev_page) + next: next_page_url, + prev: prev_page_url ) else ActivityPub::CollectionPresenter.new( diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 918bdac0a826e14d9818c0865149709095245d84..6bb95c4549838dda91c395b537a3a37e95c46b89 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -52,6 +52,14 @@ class FollowingAccountsController < ApplicationController account_following_index_url(@account, page: page) unless page.nil? end + def next_page_url + page_url(follows.next_page) if follows.respond_to?(:next_page) + end + + def prev_page_url + page_url(follows.prev_page) if follows.respond_to?(:prev_page) + end + def collection_presenter if page_requested? ActivityPub::CollectionPresenter.new( @@ -60,8 +68,8 @@ class FollowingAccountsController < ApplicationController size: @account.following_count, items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) }, part_of: account_following_index_url(@account), - next: page_url(follows.next_page), - prev: page_url(follows.prev_page) + next: next_page_url, + prev: prev_page_url ) else ActivityPub::CollectionPresenter.new( diff --git a/app/controllers/instance_actors_controller.rb b/app/controllers/instance_actors_controller.rb index 6f02d6a358f00cea153da012ad0f7a11de9fafea..4b074ca19267fcf214e7b058d6a8f988e8ab95b8 100644 --- a/app/controllers/instance_actors_controller.rb +++ b/app/controllers/instance_actors_controller.rb @@ -17,6 +17,6 @@ class InstanceActorsController < ApplicationController end def restrict_fields_to - %i(id type preferred_username inbox public_key endpoints url manually_approves_followers) + %i(id type preferred_username inbox outbox public_key endpoints url manually_approves_followers) end end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index fb8389034b9b20cffeab89b0579000db992bdf7e..45151cdd7754d016121379410abdea4df3d25925 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -5,6 +5,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio before_action :store_current_location before_action :authenticate_resource_owner! + before_action :require_not_suspended!, only: :destroy before_action :set_body_classes skip_before_action :require_functional! @@ -25,4 +26,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio def store_current_location store_location_for(:user, request.url) end + + def require_not_suspended! + forbidden if current_account.suspended? + end end diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index 0835758f2dfac88d9f81f4870085eeba3707e093..96cce55e9e4f6ecf30066d16f169113086a2607b 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -5,6 +5,7 @@ class RelationshipsController < ApplicationController before_action :authenticate_user! before_action :set_accounts, only: :show + before_action :set_relationships, only: :show before_action :set_body_classes helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship? @@ -28,6 +29,10 @@ class RelationshipsController < ApplicationController @accounts = RelationshipFilter.new(current_account, filter_params).results.page(params[:page]).per(40) end + def set_relationships + @relationships = AccountRelationshipsPresenter.new(@accounts.pluck(:id), current_user.account_id) + end + def form_account_batch_params params.require(:form_account_batch).permit(:action, account_ids: []) end @@ -49,7 +54,9 @@ class RelationshipsController < ApplicationController end def action_from_button - if params[:unfollow] + if params[:follow] + 'follow' + elsif params[:unfollow] 'unfollow' elsif params[:remove_from_followers] 'remove_from_followers' diff --git a/app/controllers/settings/aliases_controller.rb b/app/controllers/settings/aliases_controller.rb index b7c9a409d1f8d7fb18adadbfcce531118d9c8a31..a421b8ede312920d3bc969917c418b358a0f13a2 100644 --- a/app/controllers/settings/aliases_controller.rb +++ b/app/controllers/settings/aliases_controller.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true class Settings::AliasesController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! + before_action :require_not_suspended! before_action :set_aliases, except: :destroy before_action :set_alias, only: :destroy diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb index ed3f82a8e06e693e8107c0fbdf2211d7ec48a3a0..d3ac268d862018095561f295c222ff169e25d6c2 100644 --- a/app/controllers/settings/applications_controller.rb +++ b/app/controllers/settings/applications_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ApplicationsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_application, only: [:show, :update, :destroy, :regenerate] before_action :prepare_scopes, only: [:create, :update] diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 3c404cfff20b308de7c997e2efb8e3d782acdbe0..8311538a5694419f6c5676ebd323837b5f933531 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class Settings::BaseController < ApplicationController + layout 'admin' + + before_action :authenticate_user! before_action :set_body_classes before_action :set_cache_headers @@ -13,4 +16,8 @@ class Settings::BaseController < ApplicationController def set_cache_headers response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' end + + def require_not_suspended! + forbidden if current_account.suspended? + end end diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index 15a59c999dffe219c06b7e2099ee1fe4fb2875db..7b8f8d20788d9f20bde77755ea7136b064b56444 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true class Settings::DeletesController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :check_enabled_deletion - before_action :authenticate_user! before_action :require_not_suspended! - - skip_before_action :require_functional! + before_action :check_enabled_deletion def show @confirmation = Form::DeleteConfirmation.new @@ -45,8 +42,8 @@ class Settings::DeletesController < Settings::BaseController end def destroy_account! - current_account.suspend! - Admin::SuspensionWorker.perform_async(current_user.account_id, true) + current_account.suspend!(origin: :local) + AccountDeletionWorker.perform_async(current_user.account_id) sign_out end end diff --git a/app/controllers/settings/exports/blocked_accounts_controller.rb b/app/controllers/settings/exports/blocked_accounts_controller.rb index 2092104e01d1d147103d52de5f2b03b7213e042f..2190caa3619e6c4df92452101f651bfa715a7e17 100644 --- a/app/controllers/settings/exports/blocked_accounts_controller.rb +++ b/app/controllers/settings/exports/blocked_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class BlockedAccountsController < ApplicationController + class BlockedAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb index 6676ce340148f9488398f78612d311f59bec2c29..bee4b2431e374e6e651ea3da4b9f4f13b34d9521 100644 --- a/app/controllers/settings/exports/blocked_domains_controller.rb +++ b/app/controllers/settings/exports/blocked_domains_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class BlockedDomainsController < ApplicationController + class BlockedDomainsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/bookmarks_controller.rb b/app/controllers/settings/exports/bookmarks_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..c12e2f147ac0cf73d9c75923efc8a07caf530133 --- /dev/null +++ b/app/controllers/settings/exports/bookmarks_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Settings + module Exports + class BookmarksController < BaseController + include ExportControllerConcern + + def index + send_export_file + end + + private + + def export_data + @export.to_bookmarks_csv + end + end + end +end diff --git a/app/controllers/settings/exports/following_accounts_controller.rb b/app/controllers/settings/exports/following_accounts_controller.rb index 74281ddca267ac298be567d1f25d2c85ec07b870..acefcb15da67aa1ce340e7340dab4585046b34fe 100644 --- a/app/controllers/settings/exports/following_accounts_controller.rb +++ b/app/controllers/settings/exports/following_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class FollowingAccountsController < ApplicationController + class FollowingAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/lists_controller.rb b/app/controllers/settings/exports/lists_controller.rb index cf5a9de44b33bd3bd3c1cea91fbc4a79a345a9c1..bc65f56a0eff651ccea131cc42151fc9ab026e93 100644 --- a/app/controllers/settings/exports/lists_controller.rb +++ b/app/controllers/settings/exports/lists_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class ListsController < ApplicationController + class ListsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports/muted_accounts_controller.rb b/app/controllers/settings/exports/muted_accounts_controller.rb index e511619ca6ab7aeb8fa01ebbd204f173a50c9028..50b7bf1f7911924618bf1a97c723fe8d032ee532 100644 --- a/app/controllers/settings/exports/muted_accounts_controller.rb +++ b/app/controllers/settings/exports/muted_accounts_controller.rb @@ -2,7 +2,7 @@ module Settings module Exports - class MutedAccountsController < ApplicationController + class MutedAccountsController < BaseController include ExportControllerConcern def index diff --git a/app/controllers/settings/exports_controller.rb b/app/controllers/settings/exports_controller.rb index 0e93d07a9b2d509aa1738c855f4e2df49764af53..30138d29ed6412ab3c39f67b3f9b44cd207f92eb 100644 --- a/app/controllers/settings/exports_controller.rb +++ b/app/controllers/settings/exports_controller.rb @@ -3,11 +3,6 @@ class Settings::ExportsController < Settings::BaseController include Authorization - layout 'admin' - - before_action :authenticate_user! - before_action :require_not_suspended! - skip_before_action :require_functional! def show @@ -16,8 +11,6 @@ class Settings::ExportsController < Settings::BaseController end def create - raise Mastodon::NotPermittedError unless user_signed_in? - backup = nil RedisLock.acquire(lock_options) do |lock| @@ -37,8 +30,4 @@ class Settings::ExportsController < Settings::BaseController def lock_options { redis: Redis.current, key: "backup:#{current_user.id}" } end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 3a3241425d6066e0876e71c24ca0076be9028247..e805527d07c63ad3b95ee18b0465a408d587234f 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -1,12 +1,9 @@ # frozen_string_literal: true class Settings::FeaturedTagsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_featured_tags, only: :index before_action :set_featured_tag, except: [:index, :create] - before_action :set_most_used_tags, only: :index + before_action :set_recently_used_tags, only: :index def index @featured_tag = FeaturedTag.new @@ -20,7 +17,7 @@ class Settings::FeaturedTagsController < Settings::BaseController redirect_to settings_featured_tags_path else set_featured_tags - set_most_used_tags + set_recently_used_tags render :index end @@ -41,8 +38,8 @@ class Settings::FeaturedTagsController < Settings::BaseController @featured_tags = current_account.featured_tags.order(statuses_count: :desc).reject(&:new_record?) end - def set_most_used_tags - @most_used_tags = Tag.most_used(current_account).where.not(id: @featured_tags.map(&:id)).limit(10) + def set_recently_used_tags + @recently_used_tags = Tag.recently_used(current_account).where.not(id: @featured_tags.map(&:id)).limit(10) end def featured_tag_params diff --git a/app/controllers/settings/identity_proofs_controller.rb b/app/controllers/settings/identity_proofs_controller.rb index 3a90b7c4df04117b6228478c6c579a905a4e7ff6..bf2899da66fc4424b0d72abbd7617f4d78822371 100644 --- a/app/controllers/settings/identity_proofs_controller.rb +++ b/app/controllers/settings/identity_proofs_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::IdentityProofsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :check_required_params, only: :new def index diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 7b8c4ae235050acd1df905df0cf0299b7c81b6fe..d4516526eee037b8a70c5c05e1aa53806041a60c 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ImportsController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_account def show diff --git a/app/controllers/settings/migration/redirects_controller.rb b/app/controllers/settings/migration/redirects_controller.rb index 97193ade02d58dbd941484850ea514c6bc3a6d62..6d469f3842c77fbe1c3c19584dbbb044e3f6e40c 100644 --- a/app/controllers/settings/migration/redirects_controller.rb +++ b/app/controllers/settings/migration/redirects_controller.rb @@ -1,13 +1,10 @@ # frozen_string_literal: true class Settings::Migration::RedirectsController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_not_suspended! - skip_before_action :require_functional! - def new @redirect = Form::Redirect.new end @@ -38,8 +35,4 @@ class Settings::Migration::RedirectsController < Settings::BaseController def resource_params params.require(:form_redirect).permit(:acct, :current_password, :current_username) end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/migrations_controller.rb b/app/controllers/settings/migrations_controller.rb index 68304bb513f3a62afd7e13a4dfb862b11d6770a0..62603aba819783eb6d41d344a19d5331b0d0583b 100644 --- a/app/controllers/settings/migrations_controller.rb +++ b/app/controllers/settings/migrations_controller.rb @@ -1,15 +1,12 @@ # frozen_string_literal: true class Settings::MigrationsController < Settings::BaseController - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_not_suspended! before_action :set_migrations before_action :set_cooldown - skip_before_action :require_functional! - def show @migration = current_account.migrations.build end @@ -44,8 +41,4 @@ class Settings::MigrationsController < Settings::BaseController def on_cooldown? @cooldown.present? end - - def require_not_suspended! - forbidden if current_account.suspended? - end end diff --git a/app/controllers/settings/pictures_controller.rb b/app/controllers/settings/pictures_controller.rb index df2a6eed3ec13e92264c7873d21f664aefa9203a..58a4325307f3b42c028e14e71b9061c3fd982ad7 100644 --- a/app/controllers/settings/pictures_controller.rb +++ b/app/controllers/settings/pictures_controller.rb @@ -2,14 +2,17 @@ module Settings class PicturesController < BaseController - before_action :authenticate_user! before_action :set_account before_action :set_picture def destroy if valid_picture? - msg = I18n.t('generic.changes_saved_msg') if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' }) - redirect_to settings_profile_path, notice: msg, status: 303 + if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' }) + ActivityPub::UpdateDistributionWorker.perform_async(@account.id) + redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg'), status: 303 + else + redirect_to settings_profile_path + end else bad_request end diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index bac9b329d4658bf1382411c97053166312d19988..32b5d79487b7411c7a08071e6e1832db76cd038d 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -1,10 +1,6 @@ # frozen_string_literal: true class Settings::PreferencesController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! - def show; end def update @@ -47,6 +43,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_display_media, :setting_expand_spoilers, :setting_reduce_motion, + :setting_disable_swiping, :setting_system_font_ui, :setting_noindex, :setting_theme, diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb index 19a7ce157f0a782c6b62ac22f39878d01f8c266b..0c15447a6c134315d079a4df8ada0e07831f46c8 100644 --- a/app/controllers/settings/profiles_controller.rb +++ b/app/controllers/settings/profiles_controller.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class Settings::ProfilesController < Settings::BaseController - layout 'admin' - - before_action :authenticate_user! before_action :set_account def show diff --git a/app/controllers/settings/sessions_controller.rb b/app/controllers/settings/sessions_controller.rb index df5ace80368ccc1f0c210c1b7fb1ad388cf5dfed..ee2fc5dc80f2b50d9b6f88b2c0dcfc932aed222a 100644 --- a/app/controllers/settings/sessions_controller.rb +++ b/app/controllers/settings/sessions_controller.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true class Settings::SessionsController < Settings::BaseController - before_action :authenticate_user! - before_action :set_session, only: :destroy - skip_before_action :require_functional! + before_action :require_not_suspended! + before_action :set_session, only: :destroy + def destroy @session.destroy! flash[:notice] = I18n.t('sessions.revoke_success') diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb index ef4df33390aff8403b0b63f8bc2881ed28a0063a..1a0afe58b05490da8daa1f914894fdb22323e197 100644 --- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb +++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb @@ -5,31 +5,31 @@ module Settings class ConfirmationsController < BaseController include ChallengableConcern - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_challenge! before_action :ensure_otp_secret - skip_before_action :require_functional! - def new prepare_two_factor_form end def create - if current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt]) + if current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt], otp_secret: session[:new_otp_secret]) flash.now[:notice] = I18n.t('two_factor_authentication.enabled_success') current_user.otp_required_for_login = true + current_user.otp_secret = session[:new_otp_secret] @recovery_codes = current_user.generate_otp_backup_codes! current_user.save! UserMailer.two_factor_enabled(current_user).deliver_later! + session.delete(:new_otp_secret) + render 'settings/two_factor_authentication/recovery_codes/index' else - flash.now[:alert] = I18n.t('two_factor_authentication.wrong_code') + flash.now[:alert] = I18n.t('otp_authentication.wrong_code') prepare_two_factor_form render :new end @@ -43,12 +43,15 @@ module Settings def prepare_two_factor_form @confirmation = Form::TwoFactorConfirmation.new - @provision_url = current_user.otp_provisioning_uri(current_user.email, issuer: Rails.configuration.x.local_domain) + @new_otp_secret = session[:new_otp_secret] + @provision_url = current_user.otp_provisioning_uri(current_user.email, + otp_secret: @new_otp_secret, + issuer: Rails.configuration.x.local_domain) @qrcode = RQRCode::QRCode.new(@provision_url) end def ensure_otp_secret - redirect_to settings_two_factor_authentication_path unless current_user.otp_secret + redirect_to settings_otp_authentication_path if session[:new_otp_secret].blank? end end end diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..cbba842a980d0709548ee6dc9fc149aa3cc73bd1 --- /dev/null +++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Settings + module TwoFactorAuthentication + class OtpAuthenticationController < BaseController + include ChallengableConcern + + skip_before_action :require_functional! + + before_action :verify_otp_not_enabled, only: [:show] + before_action :require_challenge!, only: [:create] + + def show + @confirmation = Form::TwoFactorConfirmation.new + end + + def create + session[:new_otp_secret] = User.generate_otp_secret(32) + + redirect_to new_settings_two_factor_authentication_confirmation_path + end + + private + + def confirmation_params + params.require(:form_two_factor_confirmation).permit(:otp_attempt) + end + + def verify_otp_not_enabled + redirect_to settings_two_factor_authentication_methods_path if current_user.otp_enabled? + end + + def acceptable_code? + current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt]) || + current_user.invalidate_otp_backup_code!(confirmation_params[:otp_attempt]) + end + end + end +end diff --git a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb index 0c4f5bff762c591c8c4d14f56de5671edbffc0d8..6ec53224d384c35e7aa8c4504bd6c07c664e1563 100644 --- a/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb +++ b/app/controllers/settings/two_factor_authentication/recovery_codes_controller.rb @@ -5,13 +5,10 @@ module Settings class RecoveryCodesController < BaseController include ChallengableConcern - layout 'admin' + skip_before_action :require_functional! - before_action :authenticate_user! before_action :require_challenge!, on: :create - skip_before_action :require_functional! - def create @recovery_codes = current_user.generate_otp_backup_codes! current_user.save! diff --git a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..1c557092ba53b7cedfc4e0e8a181b330c5a0fe4f --- /dev/null +++ b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +module Settings + module TwoFactorAuthentication + class WebauthnCredentialsController < BaseController + skip_before_action :require_functional! + + before_action :require_otp_enabled + before_action :require_webauthn_enabled, only: [:index, :destroy] + + def new; end + + def index; end + + def options + current_user.update(webauthn_id: WebAuthn.generate_user_id) unless current_user.webauthn_id + + options_for_create = WebAuthn::Credential.options_for_create( + user: { + name: current_user.account.username, + display_name: current_user.account.username, + id: current_user.webauthn_id, + }, + exclude: current_user.webauthn_credentials.pluck(:external_id) + ) + + session[:webauthn_challenge] = options_for_create.challenge + + render json: options_for_create, status: :ok + end + + def create + webauthn_credential = WebAuthn::Credential.from_create(params[:credential]) + + if webauthn_credential.verify(session[:webauthn_challenge]) + user_credential = current_user.webauthn_credentials.build( + external_id: webauthn_credential.id, + public_key: webauthn_credential.public_key, + nickname: params[:nickname], + sign_count: webauthn_credential.sign_count + ) + + if user_credential.save + flash[:success] = I18n.t('webauthn_credentials.create.success') + status = :ok + + if current_user.webauthn_credentials.size == 1 + UserMailer.webauthn_enabled(current_user).deliver_later! + else + UserMailer.webauthn_credential_added(current_user, user_credential).deliver_later! + end + else + flash[:error] = I18n.t('webauthn_credentials.create.error') + status = :internal_server_error + end + else + flash[:error] = t('webauthn_credentials.create.error') + status = :unauthorized + end + + render json: { redirect_path: settings_two_factor_authentication_methods_path }, status: status + end + + def destroy + credential = current_user.webauthn_credentials.find_by(id: params[:id]) + if credential + credential.destroy + if credential.destroyed? + flash[:success] = I18n.t('webauthn_credentials.destroy.success') + + if current_user.webauthn_credentials.empty? + UserMailer.webauthn_disabled(current_user).deliver_later! + else + UserMailer.webauthn_credential_deleted(current_user, credential).deliver_later! + end + else + flash[:error] = I18n.t('webauthn_credentials.destroy.error') + end + else + flash[:error] = I18n.t('webauthn_credentials.destroy.error') + end + redirect_to settings_two_factor_authentication_methods_path + end + + private + + def require_otp_enabled + unless current_user.otp_enabled? + flash[:error] = t('webauthn_credentials.otp_required') + redirect_to settings_two_factor_authentication_methods_path + end + end + + def require_webauthn_enabled + unless current_user.webauthn_enabled? + flash[:error] = t('webauthn_credentials.not_enabled') + redirect_to settings_two_factor_authentication_methods_path + end + end + end + end +end diff --git a/app/controllers/settings/two_factor_authentication_methods_controller.rb b/app/controllers/settings/two_factor_authentication_methods_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..205933ea81482eb8371b743544302dcd959cf48e --- /dev/null +++ b/app/controllers/settings/two_factor_authentication_methods_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Settings + class TwoFactorAuthenticationMethodsController < BaseController + include ChallengableConcern + + skip_before_action :require_functional! + + before_action :require_challenge!, only: :disable + before_action :require_otp_enabled + + def index; end + + def disable + current_user.disable_two_factor! + UserMailer.two_factor_disabled(current_user).deliver_later! + + redirect_to settings_otp_authentication_path, flash: { notice: I18n.t('two_factor_authentication.disabled_success') } + end + + private + + def require_otp_enabled + redirect_to settings_otp_authentication_path unless current_user.otp_enabled? + end + end +end diff --git a/app/controllers/settings/two_factor_authentications_controller.rb b/app/controllers/settings/two_factor_authentications_controller.rb deleted file mode 100644 index 9118a79332c4ef6b50d7c9345b9dc669e5e8bf41..0000000000000000000000000000000000000000 --- a/app/controllers/settings/two_factor_authentications_controller.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -module Settings - class TwoFactorAuthenticationsController < BaseController - include ChallengableConcern - - layout 'admin' - - before_action :authenticate_user! - before_action :verify_otp_required, only: [:create] - before_action :require_challenge!, only: [:create] - - skip_before_action :require_functional! - - def show - @confirmation = Form::TwoFactorConfirmation.new - end - - def create - current_user.otp_secret = User.generate_otp_secret(32) - current_user.save! - redirect_to new_settings_two_factor_authentication_confirmation_path - end - - def destroy - if acceptable_code? - current_user.otp_required_for_login = false - current_user.save! - UserMailer.two_factor_disabled(current_user).deliver_later! - redirect_to settings_two_factor_authentication_path - else - flash.now[:alert] = I18n.t('two_factor_authentication.wrong_code') - @confirmation = Form::TwoFactorConfirmation.new - render :show - end - end - - private - - def confirmation_params - params.require(:form_two_factor_confirmation).permit(:otp_attempt) - end - - def verify_otp_required - redirect_to settings_two_factor_authentication_path if current_user.otp_required_for_login? - end - - def acceptable_code? - current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt]) || - current_user.invalidate_otp_backup_code!(confirmation_params[:otp_attempt]) - end - end -end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 6426a7d695260faad5db9f5907a8642f321eab64..6616ba107c83f3d4836582b68ecf3940ac1d4e70 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -10,8 +10,9 @@ class TagsController < ApplicationController before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :authenticate_user!, if: :whitelist_mode? - before_action :set_tag before_action :set_local + before_action :set_tag + before_action :set_statuses before_action :set_body_classes before_action :set_instance_presenter @@ -25,20 +26,11 @@ class TagsController < ApplicationController format.rss do expires_in 0, public: true - - limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE - @statuses = HashtagQueryService.new.call(@tag, filter_params, nil, @local).limit(limit) - @statuses = cache_collection(@statuses, Status) - render xml: RSS::TagSerializer.render(@tag, @statuses) end format.json do expires_in 3.minutes, public: public_fetch_mode? - - @statuses = HashtagQueryService.new.call(@tag, filter_params, current_account, @local).paginate_by_max_id(PAGE_SIZE, params[:max_id]) - @statuses = cache_collection(@statuses, Status) - render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' end end @@ -54,6 +46,15 @@ class TagsController < ApplicationController @local = truthy_param?(:local) end + def set_statuses + case request.format&.to_sym + when :json + @statuses = cache_collection(TagFeed.new(@tag, current_account, local: @local).get(PAGE_SIZE, params[:max_id], params[:since_id], params[:min_id]), Status) + when :rss + @statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status) + end + end + def set_body_classes @body_classes = 'with-modals' end @@ -62,16 +63,16 @@ class TagsController < ApplicationController @instance_presenter = InstancePresenter.new end + def limit_param + params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE + end + def collection_presenter ActivityPub::CollectionPresenter.new( - id: tag_url(@tag, filter_params), + id: tag_url(@tag), type: :ordered, size: @tag.statuses.count, items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) } ) end - - def filter_params - params.slice(:any, :all, :none).permit(:any, :all, :none) - end end diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb index 9de9db6ba8c1b4448b2982df71d9211b33169f2a..0227f722a77c6d90846ed05e558555a9b9277325 100644 --- a/app/controllers/well_known/webfinger_controller.rb +++ b/app/controllers/well_known/webfinger_controller.rb @@ -35,7 +35,7 @@ module WellKnown end def check_account_suspension - expires_in(3.minutes, public: true) && gone if @account.suspended? + expires_in(3.minutes, public: true) && gone if @account.suspended_permanently? end def bad_request diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index 8e398c3b2696271d3f2e8ebe1f70d0e33369c13f..0f3ca36e2df0f0c2d060c439c12cebed19006743 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -29,6 +29,8 @@ module Admin::ActionLogsHelper link_to record.target_account.acct, admin_account_path(record.target_account_id) when 'Announcement' link_to truncate(record.text), edit_admin_announcement_path(record.id) + when 'IpBlock' + "#{record.ip}/#{record.ip.prefix} (#{I18n.t("simple_form.labels.ip_block.severities.#{record.severity}")})" end end @@ -48,6 +50,8 @@ module Admin::ActionLogsHelper end when 'Announcement' truncate(attributes['text'].is_a?(Array) ? attributes['text'].last : attributes['text']) + when 'IpBlock' + "#{attributes['ip']}/#{attributes['ip'].prefix} (#{I18n.t("simple_form.labels.ip_block.severities.#{attributes['severity']}")})" end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 716df0baccd97e45e9f70c9ef44e6beffac42f42..bf5742d34f2ff4107c2d6d73db99482e83cd274c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7,6 +7,13 @@ module ApplicationHelper follow ).freeze + RTL_LOCALES = %i( + ar + fa + he + ku + ).freeze + def active_nav_class(*paths) paths.any? { |path| current_page?(path) } ? 'active' : '' end @@ -44,7 +51,7 @@ module ApplicationHelper end def locale_direction - if [:ar, :fa, :he].include?(I18n.locale) + if RTL_LOCALES.include?(I18n.locale) 'rtl' else 'ltr' @@ -89,6 +96,16 @@ module ApplicationHelper end end + def interrelationships_icon(relationships, account_id) + if relationships.following[account_id] && relationships.followed_by[account_id] + fa_icon('exchange', title: I18n.t('relationships.mutual'), class: 'fa-fw active passive') + elsif relationships.following[account_id] + fa_icon(locale_direction == 'ltr' ? 'arrow-right' : 'arrow-left', title: I18n.t('relationships.following'), class: 'fa-fw active') + elsif relationships.followed_by[account_id] + fa_icon(locale_direction == 'ltr' ? 'arrow-left' : 'arrow-right', title: I18n.t('relationships.followers'), class: 'fa-fw passive') + end + end + def custom_emoji_tag(custom_emoji, animate = true) if animate image_tag(custom_emoji.image.url, class: 'emojione', alt: ":#{custom_emoji.shortcode}:") @@ -162,6 +179,8 @@ module ApplicationHelper end json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json + # rubocop:disable Rails/OutputSafety content_tag(:script, json_escape(json).html_safe, id: 'initial-state', type: 'application/json') + # rubocop:enable Rails/OutputSafety end end diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 87718dc0584363997f67f974d0815a4ab463a897..5b39497b6bda4d42c28f46746ecbe2efbee588a0 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -40,6 +40,7 @@ module SettingsHelper kk: 'Қазақша', kn: 'ಕನà³à²¨à²¡', ko: '한êµì–´', + ku: 'سۆرانی', lt: 'Lietuvių', lv: 'LatvieÅ¡u', mk: 'МакедонÑки', @@ -56,6 +57,8 @@ module SettingsHelper pt: 'Português', ro: 'Română', ru: 'РуÑÑкий', + sa: 'संसà¥à¤•ृतमà¥', + sc: 'Sardu', sk: 'SlovenÄina', sl: 'SlovenÅ¡Äina', sq: 'Shqip', @@ -69,6 +72,7 @@ module SettingsHelper uk: 'УкраїнÑька', ur: 'Ø§ÙØ±Ø¯ÙÙˆ', vi: 'Tiếng Việt', + zgh: 'ⵜⴰⵎⴰⵣⵉⵖⵜ', 'zh-CN': 'ç®€ä½“ä¸æ–‡', 'zh-HK': 'ç¹é«”䏿–‡ï¼ˆé¦™æ¸¯ï¼‰', 'zh-TW': 'ç¹é«”䏿–‡ï¼ˆè‡ºç£ï¼‰', diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index a51597cf353e013c159ed61c0728c9d017f12150..1f654f34fc9fe6eddeb5813f695828a65a54b56a 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -4,8 +4,12 @@ module StatusesHelper EMBEDDED_CONTROLLER = 'statuses' EMBEDDED_ACTION = 'embed' - def link_to_more(url) - link_to t('statuses.show_more'), url, class: 'load-more load-gap' + def link_to_newer(url) + link_to t('statuses.show_newer'), url, class: 'load-more load-gap' + end + + def link_to_older(url) + link_to t('statuses.show_older'), url, class: 'load-more load-gap' end def nothing_here(extra_classes = '') @@ -88,22 +92,6 @@ module StatusesHelper end end - def rtl_status?(status) - status.local? ? rtl?(status.text) : rtl?(strip_tags(status.text)) - end - - def rtl?(text) - text = simplified_text(text) - rtl_words = text.scan(/[\p{Hebrew}\p{Arabic}\p{Syriac}\p{Thaana}\p{Nko}]+/m) - - if rtl_words.present? - total_size = text.size.to_f - rtl_size(rtl_words) / total_size > 0.3 - else - false - end - end - def fa_visibility_icon(status) case status.visibility when 'public' @@ -117,6 +105,14 @@ module StatusesHelper end end + def sensitized?(status, account) + if !account.nil? && account.id == status.account_id + status.sensitive + else + status.account.sensitized? || status.sensitive + end + end + private def simplified_text(text) @@ -131,10 +127,6 @@ module StatusesHelper end end - def rtl_size(words) - words.reduce(0) { |acc, elem| acc + elem.size }.to_f - end - def embedded_view? params[:controller] == EMBEDDED_CONTROLLER && params[:action] == EMBEDDED_ACTION end diff --git a/app/helpers/webfinger_helper.rb b/app/helpers/webfinger_helper.rb index ab7ca469811f12e44d87550abc9ea10ddc97a09b..482f4e19eabef0e0a1bbbd43fddf63fb1fd9ed54 100644 --- a/app/helpers/webfinger_helper.rb +++ b/app/helpers/webfinger_helper.rb @@ -1,38 +1,7 @@ # frozen_string_literal: true -# Monkey-patch on monkey-patch. -# Because it conflicts with the request.rb patch. -class HTTP::Timeout::PerOperationOriginal < HTTP::Timeout::PerOperation - def connect(socket_class, host, port, nodelay = false) - ::Timeout.timeout(@connect_timeout, HTTP::TimeoutError) do - @socket = socket_class.open(host, port) - @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay - end - end -end - module WebfingerHelper def webfinger!(uri) - hidden_service_uri = /\.(onion|i2p)(:\d+)?$/.match(uri) - - raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && hidden_service_uri - - opts = { - ssl: !hidden_service_uri, - - headers: { - 'User-Agent': Mastodon::Version.user_agent, - }, - - timeout_class: HTTP::Timeout::PerOperationOriginal, - - timeout_options: { - write_timeout: 10, - connect_timeout: 5, - read_timeout: 10, - }, - } - - Goldfinger::Client.new(uri, opts.merge(Rails.configuration.x.http_client_proxy)).finger + Webfinger.new(uri).perform end end diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index cb2c682a45ba1844073736de6784485fbab076c8..58b636602609718a41453f3ec0a310ba20b280c4 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -1,6 +1,5 @@ import api, { getLinks } from '../api'; -import openDB from '../storage/db'; -import { importAccount, importFetchedAccount, importFetchedAccounts } from './importer'; +import { importFetchedAccount, importFetchedAccounts } from './importer'; export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'; export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'; @@ -74,45 +73,13 @@ export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST'; export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS'; export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL'; -function getFromDB(dispatch, getState, index, id) { - return new Promise((resolve, reject) => { - const request = index.get(id); - - request.onerror = reject; - - request.onsuccess = () => { - if (!request.result) { - reject(); - return; - } - - dispatch(importAccount(request.result)); - resolve(request.result.moved && getFromDB(dispatch, getState, index, request.result.moved)); - }; - }); -} - export function fetchAccount(id) { return (dispatch, getState) => { dispatch(fetchRelationships([id])); - - if (getState().getIn(['accounts', id], null) !== null) { - return; - } - dispatch(fetchAccountRequest(id)); - openDB().then(db => getFromDB( - dispatch, - getState, - db.transaction('accounts', 'read').objectStore('accounts').index('id'), - id, - ).then(() => db.close(), error => { - db.close(); - throw error; - })).catch(() => api(getState).get(`/api/v1/accounts/${id}`).then(response => { + api(getState).get(`/api/v1/accounts/${id}`).then(response => { dispatch(importFetchedAccount(response.data)); - })).then(() => { dispatch(fetchAccountSuccess()); }).catch(error => { dispatch(fetchAccountFail(id, error)); @@ -142,14 +109,14 @@ export function fetchAccountFail(id, error) { }; }; -export function followAccount(id, reblogs = true) { +export function followAccount(id, options = { reblogs: true }) { return (dispatch, getState) => { const alreadyFollowing = getState().getIn(['relationships', id, 'following']); const locked = getState().getIn(['accounts', id, 'locked'], false); dispatch(followAccountRequest(id, locked)); - api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then(response => { + api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => { dispatch(followAccountSuccess(response.data, alreadyFollowing)); }).catch(error => { dispatch(followAccountFail(error, locked)); @@ -290,11 +257,11 @@ export function unblockAccountFail(error) { }; -export function muteAccount(id, notifications) { +export function muteAccount(id, notifications, duration=0) { return (dispatch, getState) => { dispatch(muteAccountRequest(id)); - api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications }).then(response => { + api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => { // Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers dispatch(muteAccountSuccess(response.data, getState().get('statuses'))); }).catch(error => { diff --git a/app/javascript/mastodon/actions/app.js b/app/javascript/mastodon/actions/app.js index 414968f7de47cfef7cf1abe27742efc03ed92959..c817c87080a005ef3b922bf663746fefd2e8b430 100644 --- a/app/javascript/mastodon/actions/app.js +++ b/app/javascript/mastodon/actions/app.js @@ -8,3 +8,10 @@ export const focusApp = () => ({ export const unfocusApp = () => ({ type: APP_UNFOCUS, }); + +export const APP_LAYOUT_CHANGE = 'APP_LAYOUT_CHANGE'; + +export const changeLayout = layout => ({ + type: APP_LAYOUT_CHANGE, + layout, +}); diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 20341f9ec0e2425bb71631d9c9888ba842b0a1d8..891403969e2f1d640aed67cce864d5e5b0cbd7f3 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -152,9 +152,7 @@ export function submitCompose(routerHistory) { 'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']), }, }).then(function (response) { - if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0 && routerHistory) { - routerHistory.push('/timelines/direct'); - } else if (routerHistory && routerHistory.location.pathname === '/statuses/new' && window.history.state) { + if (routerHistory && routerHistory.location.pathname === '/statuses/new' && window.history.state) { routerHistory.goBack(); } @@ -163,7 +161,6 @@ export function submitCompose(routerHistory) { // To make the app more responsive, immediately push the status // into the columns - const insertIfOnline = timelineId => { const timeline = getState().getIn(['timelines', timelineId]); @@ -179,6 +176,7 @@ export function submitCompose(routerHistory) { if (response.data.in_reply_to_id === null && response.data.visibility === 'public') { insertIfOnline('community'); insertIfOnline('public'); + insertIfOnline(`account:${response.data.account.id}`); } }).catch(function (error) { dispatch(submitComposeFail(error)); diff --git a/app/javascript/mastodon/actions/lists.js b/app/javascript/mastodon/actions/lists.js index d736bacef4805770713765b24ca29cae1a5d7598..5ab9224363fe6f61a6291e3d3567712b0d7b26bc 100644 --- a/app/javascript/mastodon/actions/lists.js +++ b/app/javascript/mastodon/actions/lists.js @@ -150,10 +150,10 @@ export const createListFail = error => ({ error, }); -export const updateList = (id, title, shouldReset) => (dispatch, getState) => { +export const updateList = (id, title, shouldReset, replies_policy) => (dispatch, getState) => { dispatch(updateListRequest(id)); - api(getState).put(`/api/v1/lists/${id}`, { title }).then(({ data }) => { + api(getState).put(`/api/v1/lists/${id}`, { title, replies_policy }).then(({ data }) => { dispatch(updateListSuccess(data)); if (shouldReset) { diff --git a/app/javascript/mastodon/actions/markers.js b/app/javascript/mastodon/actions/markers.js index 37d1ddccfeecae8414a202d4a61c43e3d3aadde6..16a3df8f6381c6c7f1ca6d2a47cb9e72122a3fae 100644 --- a/app/javascript/mastodon/actions/markers.js +++ b/app/javascript/mastodon/actions/markers.js @@ -1,8 +1,10 @@ import api from '../api'; import { debounce } from 'lodash'; import compareId from '../compare_id'; -import { showAlertForError } from './alerts'; +export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST'; +export const MARKERS_FETCH_SUCCESS = 'MARKERS_FETCH_SUCCESS'; +export const MARKERS_FETCH_FAIL = 'MARKERS_FETCH_FAIL'; export const MARKERS_SUBMIT_SUCCESS = 'MARKERS_SUBMIT_SUCCESS'; export const synchronouslySubmitMarkers = () => (dispatch, getState) => { @@ -26,15 +28,19 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => { }, body: JSON.stringify(params), }); + return; } else if (navigator && navigator.sendBeacon) { // Failing that, we can use sendBeacon, but we have to encode the data as // FormData for DoorKeeper to recognize the token. const formData = new FormData(); + formData.append('bearer_token', accessToken); + for (const [id, value] of Object.entries(params)) { formData.append(`${id}[last_read_id]`, value.last_read_id); } + if (navigator.sendBeacon('/api/v1/markers', formData)) { return; } @@ -57,8 +63,8 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => { const _buildParams = (state) => { const params = {}; - const lastHomeId = state.getIn(['timelines', 'home', 'items', 0]); - const lastNotificationId = state.getIn(['notifications', 'items', 0, 'id']); + const lastHomeId = state.getIn(['timelines', 'home', 'items']).find(item => item !== null); + const lastNotificationId = state.getIn(['notifications', 'lastReadId']); if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) { params.home = { @@ -82,11 +88,9 @@ const debouncedSubmitMarkers = debounce((dispatch, getState) => { return; } - api().post('/api/v1/markers', params).then(() => { + api(getState).post('/api/v1/markers', params).then(() => { dispatch(submitMarkersSuccess(params)); - }).catch(error => { - dispatch(showAlertForError(error)); - }); + }).catch(() => {}); }, 300000, { leading: true, trailing: true }); export function submitMarkersSuccess({ home, notifications }) { @@ -97,6 +101,48 @@ export function submitMarkersSuccess({ home, notifications }) { }; }; -export function submitMarkers() { - return (dispatch, getState) => debouncedSubmitMarkers(dispatch, getState); +export function submitMarkers(params = {}) { + const result = (dispatch, getState) => debouncedSubmitMarkers(dispatch, getState); + + if (params.immediate === true) { + debouncedSubmitMarkers.flush(); + } + + return result; +}; + +export const fetchMarkers = () => (dispatch, getState) => { + const params = { timeline: ['notifications'] }; + + dispatch(fetchMarkersRequest()); + + api(getState).get('/api/v1/markers', { params }).then(response => { + dispatch(fetchMarkersSuccess(response.data)); + }).catch(error => { + dispatch(fetchMarkersFail(error)); + }); +}; + +export function fetchMarkersRequest() { + return { + type: MARKERS_FETCH_REQUEST, + skipLoading: true, + }; +}; + +export function fetchMarkersSuccess(markers) { + return { + type: MARKERS_FETCH_SUCCESS, + markers, + skipLoading: true, + }; +}; + +export function fetchMarkersFail(error) { + return { + type: MARKERS_FETCH_FAIL, + error, + skipLoading: true, + skipAlert: true, + }; }; diff --git a/app/javascript/mastodon/actions/mutes.js b/app/javascript/mastodon/actions/mutes.js index 9f645faee17bbf50579e26c7b001f057e0e68543..d8874f353f42c43cd9a88aa9aecd3089977eb4d8 100644 --- a/app/javascript/mastodon/actions/mutes.js +++ b/app/javascript/mastodon/actions/mutes.js @@ -13,6 +13,7 @@ export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL'; export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL'; export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS'; +export const MUTES_CHANGE_DURATION = 'MUTES_CHANGE_DURATION'; export function fetchMutes() { return (dispatch, getState) => { @@ -104,3 +105,12 @@ export function toggleHideNotifications() { dispatch({ type: MUTES_TOGGLE_HIDE_NOTIFICATIONS }); }; } + +export function changeMuteDuration(duration) { + return dispatch => { + dispatch({ + type: MUTES_CHANGE_DURATION, + duration, + }); + }; +} diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index a26844f84821d34ec783fd74b3c61cdd58dfd9ca..3464ac995979d3a3395ad65421e490f4c11fd146 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -16,6 +16,7 @@ import { getFiltersRegex } from '../selectors'; import { usePendingItems as preferPendingItems } from 'mastodon/initial_state'; import compareId from 'mastodon/compare_id'; import { searchTextFromRawStatus } from 'mastodon/actions/importer/normalizer'; +import { requestNotificationPermission } from '../utils/notifications'; export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP'; @@ -33,6 +34,12 @@ export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING'; export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT'; export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; + +export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ'; + +export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT'; +export const NOTIFICATIONS_SET_BROWSER_PERMISSION = 'NOTIFICATIONS_SET_BROWSER_PERMISSION'; + defineMessages({ mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, group: { id: 'notifications.group', defaultMessage: '{count} notifications' }, @@ -59,7 +66,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) { let filtered = false; - if (notification.type === 'mention') { + if (['mention', 'status'].includes(notification.type)) { const dropRegex = filters[0]; const regex = filters[1]; const searchIndex = searchTextFromRawStatus(notification.status); @@ -232,3 +239,47 @@ export const mountNotifications = () => ({ export const unmountNotifications = () => ({ type: NOTIFICATIONS_UNMOUNT, }); + + +export const markNotificationsAsRead = () => ({ + type: NOTIFICATIONS_MARK_AS_READ, +}); + +// Browser support +export function setupBrowserNotifications() { + return dispatch => { + dispatch(setBrowserSupport('Notification' in window)); + if ('Notification' in window) { + dispatch(setBrowserPermission(Notification.permission)); + } + + if ('Notification' in window && 'permissions' in navigator) { + navigator.permissions.query({ name: 'notifications' }).then((status) => { + status.onchange = () => dispatch(setBrowserPermission(Notification.permission)); + }).catch(console.warn); + } + }; +} + +export function requestBrowserPermission(callback = noOp) { + return dispatch => { + requestNotificationPermission((permission) => { + dispatch(setBrowserPermission(permission)); + callback(permission); + }); + }; +}; + +export function setBrowserSupport (value) { + return { + type: NOTIFICATIONS_SET_BROWSER_SUPPORT, + value, + }; +} + +export function setBrowserPermission (value) { + return { + type: NOTIFICATIONS_SET_BROWSER_PERMISSION, + value, + }; +} diff --git a/app/javascript/mastodon/actions/onboarding.js b/app/javascript/mastodon/actions/onboarding.js index a1dd3a731eddc1ceda9a76d05ed5f7feff7bf74f..42d8ea33fdd79d9593e95445952db842eebf7c10 100644 --- a/app/javascript/mastodon/actions/onboarding.js +++ b/app/javascript/mastodon/actions/onboarding.js @@ -1,8 +1,21 @@ import { changeSetting, saveSettings } from './settings'; +import { requestBrowserPermission } from './notifications'; export const INTRODUCTION_VERSION = 20181216044202; export const closeOnboarding = () => dispatch => { dispatch(changeSetting(['introductionVersion'], INTRODUCTION_VERSION)); dispatch(saveSettings()); + + dispatch(requestBrowserPermission((permission) => { + if (permission === 'granted') { + dispatch(changeSetting(['notifications', 'alerts', 'follow'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'favourite'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'reblog'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'mention'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'poll'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'status'], true)); + dispatch(saveSettings()); + } + })); }; diff --git a/app/javascript/mastodon/actions/picture_in_picture.js b/app/javascript/mastodon/actions/picture_in_picture.js new file mode 100644 index 0000000000000000000000000000000000000000..4085cb59e0097f326624ad8d7214e3f70205d3d7 --- /dev/null +++ b/app/javascript/mastodon/actions/picture_in_picture.js @@ -0,0 +1,38 @@ +// @ts-check + +export const PICTURE_IN_PICTURE_DEPLOY = 'PICTURE_IN_PICTURE_DEPLOY'; +export const PICTURE_IN_PICTURE_REMOVE = 'PICTURE_IN_PICTURE_REMOVE'; + +/** + * @typedef MediaProps + * @property {string} src + * @property {boolean} muted + * @property {number} volume + * @property {number} currentTime + * @property {string} poster + * @property {string} backgroundColor + * @property {string} foregroundColor + * @property {string} accentColor + */ + +/** + * @param {string} statusId + * @param {string} accountId + * @param {string} playerType + * @param {MediaProps} props + * @return {object} + */ +export const deployPictureInPicture = (statusId, accountId, playerType, props) => ({ + type: PICTURE_IN_PICTURE_DEPLOY, + statusId, + accountId, + playerType, + props, +}); + +/* + * @return {object} + */ +export const removePictureInPicture = () => ({ + type: PICTURE_IN_PICTURE_REMOVE, +}); diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 5640201c621f0f494afb96d731ace606a899c69b..3fc7c07023d6274aabf2ec955266a862aef2e5e0 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -1,9 +1,7 @@ import api from '../api'; -import openDB from '../storage/db'; -import { evictStatus } from '../storage/modifier'; import { deleteFromTimelines } from './timelines'; -import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer'; +import { importFetchedStatus, importFetchedStatuses, importFetchedAccount } from './importer'; import { ensureComposeIsVisible } from './compose'; export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST'; @@ -40,48 +38,6 @@ export function fetchStatusRequest(id, skipLoading) { }; }; -function getFromDB(dispatch, getState, accountIndex, index, id) { - return new Promise((resolve, reject) => { - const request = index.get(id); - - request.onerror = reject; - - request.onsuccess = () => { - const promises = []; - - if (!request.result) { - reject(); - return; - } - - dispatch(importStatus(request.result)); - - if (getState().getIn(['accounts', request.result.account], null) === null) { - promises.push(new Promise((accountResolve, accountReject) => { - const accountRequest = accountIndex.get(request.result.account); - - accountRequest.onerror = accountReject; - accountRequest.onsuccess = () => { - if (!request.result) { - accountReject(); - return; - } - - dispatch(importAccount(accountRequest.result)); - accountResolve(); - }; - })); - } - - if (request.result.reblog && getState().getIn(['statuses', request.result.reblog], null) === null) { - promises.push(getFromDB(dispatch, getState, accountIndex, index, request.result.reblog)); - } - - resolve(Promise.all(promises)); - }; - }); -} - export function fetchStatus(id) { return (dispatch, getState) => { const skipLoading = getState().getIn(['statuses', id], null) !== null; @@ -94,23 +50,10 @@ export function fetchStatus(id) { dispatch(fetchStatusRequest(id, skipLoading)); - openDB().then(db => { - const transaction = db.transaction(['accounts', 'statuses'], 'read'); - const accountIndex = transaction.objectStore('accounts').index('id'); - const index = transaction.objectStore('statuses').index('id'); - - return getFromDB(dispatch, getState, accountIndex, index, id).then(() => { - db.close(); - }, error => { - db.close(); - throw error; - }); - }).then(() => { - dispatch(fetchStatusSuccess(skipLoading)); - }, () => api(getState).get(`/api/v1/statuses/${id}`).then(response => { + api(getState).get(`/api/v1/statuses/${id}`).then(response => { dispatch(importFetchedStatus(response.data)); dispatch(fetchStatusSuccess(skipLoading)); - })).catch(error => { + }).catch(error => { dispatch(fetchStatusFail(id, error, skipLoading)); }); }; @@ -152,9 +95,9 @@ export function deleteStatus(id, routerHistory, withRedraft = false) { dispatch(deleteStatusRequest(id)); api(getState).delete(`/api/v1/statuses/${id}`).then(response => { - evictStatus(id); dispatch(deleteStatusSuccess(id)); dispatch(deleteFromTimelines(id)); + dispatch(importFetchedAccount(response.data.account)); if (withRedraft) { dispatch(redraft(status, response.data.text)); diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index d998fcac48023831e29d8ae04dea3c72b6b76e9e..beb5c6a4a9de6cb52e844fcc6315c082cdb5e0c9 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -1,3 +1,5 @@ +// @ts-check + import { connectStream } from '../stream'; import { updateTimeline, @@ -19,24 +21,59 @@ import { getLocale } from '../locales'; const { messages } = getLocale(); -export function connectTimelineStream (timelineId, path, pollingRefresh = null, accept = null) { +/** + * @param {number} max + * @return {number} + */ +const randomUpTo = max => + Math.floor(Math.random() * Math.floor(max)); - return connectStream (path, pollingRefresh, (dispatch, getState) => { +/** + * @param {string} timelineId + * @param {string} channelName + * @param {Object.<string, string>} params + * @param {Object} options + * @param {function(Function, Function): void} [options.fallback] + * @param {function(object): boolean} [options.accept] + * @return {function(): void} + */ +export const connectTimelineStream = (timelineId, channelName, params = {}, options = {}) => + connectStream(channelName, params, (dispatch, getState) => { const locale = getState().getIn(['meta', 'locale']); + let pollingId; + + /** + * @param {function(Function, Function): void} fallback + */ + const useFallback = fallback => { + fallback(dispatch, () => { + pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000)); + }); + }; + return { onConnect() { dispatch(connectTimeline(timelineId)); + + if (pollingId) { + clearTimeout(pollingId); + pollingId = null; + } }, onDisconnect() { dispatch(disconnectTimeline(timelineId)); + + if (options.fallback) { + pollingId = setTimeout(() => useFallback(options.fallback), randomUpTo(40000)); + } }, onReceive (data) { switch(data.event) { case 'update': - dispatch(updateTimeline(timelineId, JSON.parse(data.payload), accept)); + dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept)); break; case 'delete': dispatch(deleteFromTimelines(data.payload)); @@ -63,17 +100,59 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null, }, }; }); -} +/** + * @param {Function} dispatch + * @param {function(): void} done + */ const refreshHomeTimelineAndNotification = (dispatch, done) => { dispatch(expandHomeTimeline({}, () => dispatch(expandNotifications({}, () => dispatch(fetchAnnouncements(done)))))); }; -export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); -export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); -export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); -export const connectHashtagStream = (id, tag, local, accept) => connectTimelineStream(`hashtag:${id}${local ? ':local' : ''}`, `hashtag${local ? ':local' : ''}&tag=${tag}`, null, accept); -export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); -export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); +/** + * @return {function(): void} + */ +export const connectUserStream = () => + connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification }); + +/** + * @param {Object} options + * @param {boolean} [options.onlyMedia] + * @return {function(): void} + */ +export const connectCommunityStream = ({ onlyMedia } = {}) => + connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); + +/** + * @param {Object} options + * @param {boolean} [options.onlyMedia] + * @param {boolean} [options.onlyRemote] + * @return {function(): void} + */ +export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => + connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); + +/** + * @param {string} columnId + * @param {string} tagName + * @param {boolean} onlyLocal + * @param {function(object): boolean} accept + * @return {function(): void} + */ +export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) => + connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ':local' : ''}`, `hashtag${onlyLocal ? ':local' : ''}`, { tag: tagName }, { accept }); + +/** + * @return {function(): void} + */ +export const connectDirectStream = () => + connectTimelineStream('direct', 'direct'); + +/** + * @param {string} listId + * @return {function(): void} + */ +export const connectListStream = listId => + connectTimelineStream(`list:${listId}`, 'list', { list: listId }); diff --git a/app/javascript/mastodon/blurhash.js b/app/javascript/mastodon/blurhash.js new file mode 100644 index 0000000000000000000000000000000000000000..5adcc3e77021e17091e4cae9737be5e2f6bd37a6 --- /dev/null +++ b/app/javascript/mastodon/blurhash.js @@ -0,0 +1,112 @@ +const DIGIT_CHARACTERS = [ + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + '#', + '$', + '%', + '*', + '+', + ',', + '-', + '.', + ':', + ';', + '=', + '?', + '@', + '[', + ']', + '^', + '_', + '{', + '|', + '}', + '~', +]; + +export const decode83 = (str) => { + let value = 0; + let c, digit; + + for (let i = 0; i < str.length; i++) { + c = str[i]; + digit = DIGIT_CHARACTERS.indexOf(c); + value = value * 83 + digit; + } + + return value; +}; + +export const intToRGB = int => ({ + r: Math.max(0, (int >> 16)), + g: Math.max(0, (int >> 8) & 255), + b: Math.max(0, (int & 255)), +}); + +export const getAverageFromBlurhash = blurhash => { + if (!blurhash) { + return null; + } + + return intToRGB(decode83(blurhash.slice(2, 6))); +}; diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap index 5c04e09799f022cf9a30a19bc841dcc9731b0360..86fbba917b7391c33fd29b051d6a9b93e334c899 100644 --- a/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap +++ b/app/javascript/mastodon/components/__tests__/__snapshots__/button-test.js.snap @@ -4,13 +4,6 @@ exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] = <button className="button button-secondary" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } /> `; @@ -18,13 +11,6 @@ exports[`<Button /> renders a button element 1`] = ` <button className="button" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } /> `; @@ -33,13 +19,6 @@ exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = ` className="button" disabled={true} onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } /> `; @@ -47,13 +26,6 @@ exports[`<Button /> renders class="button--block" if props.block given 1`] = ` <button className="button button--block" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } /> `; @@ -61,13 +33,6 @@ exports[`<Button /> renders the children 1`] = ` <button className="button" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } > <p> children @@ -79,13 +44,6 @@ exports[`<Button /> renders the given text 1`] = ` <button className="button" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } > foo </button> @@ -95,13 +53,6 @@ exports[`<Button /> renders the props.text instead of children 1`] = ` <button className="button" onClick={[Function]} - style={ - Object { - "height": "36px", - "lineHeight": "36px", - "padding": "0 16px", - } - } > foo </button> diff --git a/app/javascript/mastodon/components/account.js b/app/javascript/mastodon/components/account.js index 2705a6001341bff0ad06bbfd060fe0c42f5248ca..0e40ee1d6a5543d6e28f1fdeae28fb0e898a1978 100644 --- a/app/javascript/mastodon/components/account.js +++ b/app/javascript/mastodon/components/account.js @@ -8,6 +8,7 @@ import IconButton from './icon_button'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { me } from '../initial_state'; +import RelativeTimestamp from './relative_timestamp'; const messages = defineMessages({ follow: { id: 'account.follow', defaultMessage: 'Follow' }, @@ -107,11 +108,17 @@ class Account extends ImmutablePureComponent { } } + let mute_expires_at; + if (account.get('mute_expires_at')) { + mute_expires_at = <div><RelativeTimestamp timestamp={account.get('mute_expires_at')} futureDate /></div>; + } + return ( <div className='account'> <div className='account__wrapper'> <Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/accounts/${account.get('id')}`}> <div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div> + {mute_expires_at} <DisplayName account={account} /> </Permalink> diff --git a/app/javascript/mastodon/components/animated_number.js b/app/javascript/mastodon/components/animated_number.js index f3127c88ef1a485f287adaa7a77f06a9488e7ac3..fbe948c5b02371dc824951e78e13478b2a601f4e 100644 --- a/app/javascript/mastodon/components/animated_number.js +++ b/app/javascript/mastodon/components/animated_number.js @@ -5,10 +5,21 @@ import TransitionMotion from 'react-motion/lib/TransitionMotion'; import spring from 'react-motion/lib/spring'; import { reduceMotion } from 'mastodon/initial_state'; +const obfuscatedCount = count => { + if (count < 0) { + return 0; + } else if (count <= 1) { + return count; + } else { + return '1+'; + } +}; + export default class AnimatedNumber extends React.PureComponent { static propTypes = { value: PropTypes.number.isRequired, + obfuscate: PropTypes.bool, }; state = { @@ -36,11 +47,11 @@ export default class AnimatedNumber extends React.PureComponent { } render () { - const { value } = this.props; + const { value, obfuscate } = this.props; const { direction } = this.state; if (reduceMotion) { - return <FormattedNumber value={value} />; + return obfuscate ? obfuscatedCount(value) : <FormattedNumber value={value} />; } const styles = [{ @@ -54,7 +65,7 @@ export default class AnimatedNumber extends React.PureComponent { {items => ( <span className='animated-number'> {items.map(({ key, data, style }) => ( - <span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}><FormattedNumber value={data} /></span> + <span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}>{obfuscate ? obfuscatedCount(data) : <FormattedNumber value={data} />}</span> ))} </span> )} diff --git a/app/javascript/mastodon/components/autosuggest_emoji.js b/app/javascript/mastodon/components/autosuggest_emoji.js index ce4383a607f609568921920ba454702153d53c1a..4937e4d9845f4d46221fe002f2936d91460efe62 100644 --- a/app/javascript/mastodon/components/autosuggest_emoji.js +++ b/app/javascript/mastodon/components/autosuggest_emoji.js @@ -1,8 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import unicodeMapping from '../features/emoji/emoji_unicode_mapping_light'; - -const assetHost = process.env.CDN_HOST || ''; +import { assetHost } from 'mastodon/utils/config'; export default class AutosuggestEmoji extends React.PureComponent { diff --git a/app/javascript/mastodon/components/autosuggest_input.js b/app/javascript/mastodon/components/autosuggest_input.js index 6d2035add0184c51dfa1a4522240e8fe4845c781..5187f95c847f487cf0fa01067ba8e5d3aa70b150 100644 --- a/app/javascript/mastodon/components/autosuggest_input.js +++ b/app/javascript/mastodon/components/autosuggest_input.js @@ -4,7 +4,6 @@ import AutosuggestEmoji from './autosuggest_emoji'; import AutosuggestHashtag from './autosuggest_hashtag'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import { isRtl } from '../rtl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import classNames from 'classnames'; import { List as ImmutableList } from 'immutable'; @@ -189,11 +188,6 @@ export default class AutosuggestInput extends ImmutablePureComponent { render () { const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength } = this.props; const { suggestionsHidden } = this.state; - const style = { direction: 'ltr' }; - - if (isRtl(value)) { - style.direction = 'rtl'; - } return ( <div className='autosuggest-input'> @@ -212,7 +206,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { onKeyUp={onKeyUp} onFocus={this.onFocus} onBlur={this.onBlur} - style={style} + dir='auto' aria-autocomplete='list' id={id} className={className} diff --git a/app/javascript/mastodon/components/autosuggest_textarea.js b/app/javascript/mastodon/components/autosuggest_textarea.js index 58ec4f6eb66fb2356591e2587ae465c0b10596d2..08b9cd80bbf7aaaec010887e64e638195b9afc59 100644 --- a/app/javascript/mastodon/components/autosuggest_textarea.js +++ b/app/javascript/mastodon/components/autosuggest_textarea.js @@ -4,7 +4,6 @@ import AutosuggestEmoji from './autosuggest_emoji'; import AutosuggestHashtag from './autosuggest_hashtag'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import { isRtl } from '../rtl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Textarea from 'react-textarea-autosize'; import classNames from 'classnames'; @@ -195,11 +194,6 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { render () { const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, children } = this.props; const { suggestionsHidden } = this.state; - const style = { direction: 'ltr' }; - - if (isRtl(value)) { - style.direction = 'rtl'; - } return [ <div className='compose-form__autosuggest-wrapper' key='autosuggest-wrapper'> @@ -220,7 +214,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { onFocus={this.onFocus} onBlur={this.onBlur} onPaste={this.onPaste} - style={style} + dir='auto' aria-autocomplete='list' /> </label> diff --git a/app/javascript/mastodon/components/button.js b/app/javascript/mastodon/components/button.js index eb8dd7dc8eb9c9501c0ce0be83e33f41d5c35c81..85b2d78ca9ee69702320ef7ad58063c915cfae2b 100644 --- a/app/javascript/mastodon/components/button.js +++ b/app/javascript/mastodon/components/button.js @@ -10,17 +10,11 @@ export default class Button extends React.PureComponent { disabled: PropTypes.bool, block: PropTypes.bool, secondary: PropTypes.bool, - size: PropTypes.number, className: PropTypes.string, title: PropTypes.string, - style: PropTypes.object, children: PropTypes.node, }; - static defaultProps = { - size: 36, - }; - handleClick = (e) => { if (!this.props.disabled) { this.props.onClick(e); @@ -36,13 +30,6 @@ export default class Button extends React.PureComponent { } render () { - const style = { - padding: `0 ${this.props.size / 2.25}px`, - height: `${this.props.size}px`, - lineHeight: `${this.props.size}px`, - ...this.props.style, - }; - const className = classNames('button', this.props.className, { 'button-secondary': this.props.secondary, 'button--block': this.props.block, @@ -54,7 +41,6 @@ export default class Button extends React.PureComponent { disabled={this.props.disabled} onClick={this.handleClick} ref={this.setRef} - style={style} title={this.props.title} > {this.props.text || this.props.children} diff --git a/app/javascript/mastodon/components/column.js b/app/javascript/mastodon/components/column.js index 55e3bfd5e0b4312e4cf8ade94b8a0556971f4810..239824a4fec593385804cc05602376c242bde1ff 100644 --- a/app/javascript/mastodon/components/column.js +++ b/app/javascript/mastodon/components/column.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; import { scrollTop } from '../scroll'; export default class Column extends React.PureComponent { @@ -35,9 +35,9 @@ export default class Column extends React.PureComponent { componentDidMount () { if (this.props.bindToDocument) { - document.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); } else { - this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); } } diff --git a/app/javascript/mastodon/components/column_header.js b/app/javascript/mastodon/components/column_header.js index 1bb583583a35585e105a1547be383a1a9264ee80..236e922969d770f866111de9affa27cf5d560400 100644 --- a/app/javascript/mastodon/components/column_header.js +++ b/app/javascript/mastodon/components/column_header.js @@ -34,6 +34,7 @@ class ColumnHeader extends React.PureComponent { onMove: PropTypes.func, onClick: PropTypes.func, appendContent: PropTypes.node, + collapseIssues: PropTypes.bool, }; state = { @@ -83,7 +84,7 @@ class ColumnHeader extends React.PureComponent { } render () { - const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent } = this.props; + const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props; const { collapsed, animating } = this.state; const wrapperClassName = classNames('column-header__wrapper', { @@ -145,7 +146,20 @@ class ColumnHeader extends React.PureComponent { } if (children || (multiColumn && this.props.onPin)) { - collapseButton = <button className={collapsibleButtonClassName} title={formatMessage(collapsed ? messages.show : messages.hide)} aria-label={formatMessage(collapsed ? messages.show : messages.hide)} aria-pressed={collapsed ? 'false' : 'true'} onClick={this.handleToggleClick}><Icon id='sliders' /></button>; + collapseButton = ( + <button + className={collapsibleButtonClassName} + title={formatMessage(collapsed ? messages.show : messages.hide)} + aria-label={formatMessage(collapsed ? messages.show : messages.hide)} + aria-pressed={collapsed ? 'false' : 'true'} + onClick={this.handleToggleClick} + > + <i className='icon-with-badge'> + <Icon id='sliders' /> + {collapseIssues && <i className='icon-with-badge__issue-badge' />} + </i> + </button> + ); } const hasTitle = icon && title; diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js index 4734e0f3fc4a6c09729984e3bd0af272ce58c527..c6b4b118736ed9420dce19b649257c0a99494e88 100644 --- a/app/javascript/mastodon/components/dropdown_menu.js +++ b/app/javascript/mastodon/components/dropdown_menu.js @@ -5,9 +5,9 @@ import IconButton from './icon_button'; import Overlay from 'react-overlays/lib/Overlay'; import Motion from '../features/ui/util/optional_motion'; import spring from 'react-motion/lib/spring'; -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; -const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false; +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; let id = 0; class DropdownMenu extends React.PureComponent { @@ -205,7 +205,7 @@ export default class Dropdown extends React.PureComponent { handleClose = () => { if (this.activeElement) { - this.activeElement.focus(); + this.activeElement.focus({ preventScroll: true }); this.activeElement = null; } this.props.onClose(this.state.id); diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js index ca3012276bc4b0f664662539e8f122dd98ae9ba7..ca4a2cfe14bed1d06b704db422bce6783929c444 100644 --- a/app/javascript/mastodon/components/error_boundary.js +++ b/app/javascript/mastodon/components/error_boundary.js @@ -66,17 +66,31 @@ export default class ErrorBoundary extends React.PureComponent { } render() { - const { hasError, copied } = this.state; + const { hasError, copied, errorMessage } = this.state; if (!hasError) { return this.props.children; } + const likelyBrowserAddonIssue = errorMessage && errorMessage.includes('NotFoundError'); + return ( <div className='error-boundary'> <div> - <p className='error-boundary__error'><FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /></p> - <p><FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /></p> + <p className='error-boundary__error'> + { likelyBrowserAddonIssue ? ( + <FormattedMessage id='error.unexpected_crash.explanation_addons' defaultMessage='This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.' /> + ) : ( + <FormattedMessage id='error.unexpected_crash.explanation' defaultMessage='Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.' /> + )} + </p> + <p> + { likelyBrowserAddonIssue ? ( + <FormattedMessage id='error.unexpected_crash.next_steps_addons' defaultMessage='Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /> + ) : ( + <FormattedMessage id='error.unexpected_crash.next_steps' defaultMessage='Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.' /> + )} + </p> <p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p> </div> </div> diff --git a/app/javascript/mastodon/components/gifv.js b/app/javascript/mastodon/components/gifv.js index 83cfae49c494d752759db8b969d5b4ef2b4c3889..b775e52005b417f9f1b3f09edd94a77be2c3878b 100644 --- a/app/javascript/mastodon/components/gifv.js +++ b/app/javascript/mastodon/components/gifv.js @@ -54,8 +54,6 @@ export default class GIFV extends React.PureComponent { <video src={src} - width={width} - height={height} role='button' tabIndex='0' aria-label={alt} diff --git a/app/javascript/mastodon/components/icon_button.js b/app/javascript/mastodon/components/icon_button.js index fd715bc3c83ac83fadc5fb9de2fee1b74fdff3d5..7ec39198a4cb4854de7a473af79e599a735e37c3 100644 --- a/app/javascript/mastodon/components/icon_button.js +++ b/app/javascript/mastodon/components/icon_button.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; +import AnimatedNumber from 'mastodon/components/animated_number'; export default class IconButton extends React.PureComponent { @@ -24,6 +25,8 @@ export default class IconButton extends React.PureComponent { animate: PropTypes.bool, overlay: PropTypes.bool, tabIndex: PropTypes.string, + counter: PropTypes.number, + obfuscateCount: PropTypes.bool, }; static defaultProps = { @@ -97,6 +100,8 @@ export default class IconButton extends React.PureComponent { pressed, tabIndex, title, + counter, + obfuscateCount, } = this.props; const { @@ -111,8 +116,13 @@ export default class IconButton extends React.PureComponent { activate, deactivate, overlayed: overlay, + 'icon-button--with-counter': typeof counter !== 'undefined', }); + if (typeof counter !== 'undefined') { + style.width = 'auto'; + } + return ( <button aria-label={title} @@ -128,7 +138,7 @@ export default class IconButton extends React.PureComponent { tabIndex={tabIndex} disabled={disabled} > - <Icon id={icon} fixedWidth aria-hidden='true' /> + <Icon id={icon} fixedWidth aria-hidden='true' /> {typeof counter !== 'undefined' && <span className='icon-button__counter'><AnimatedNumber value={counter} obfuscate={obfuscateCount} /></span>} </button> ); } diff --git a/app/javascript/mastodon/components/icon_with_badge.js b/app/javascript/mastodon/components/icon_with_badge.js index 7851eb4be99704f66379ef6084668e17ee5b0d8c..4214eccfde9405c38ac9a6fb1ae65214f7b2866d 100644 --- a/app/javascript/mastodon/components/icon_with_badge.js +++ b/app/javascript/mastodon/components/icon_with_badge.js @@ -4,16 +4,18 @@ import Icon from 'mastodon/components/icon'; const formatNumber = num => num > 40 ? '40+' : num; -const IconWithBadge = ({ id, count, className }) => ( +const IconWithBadge = ({ id, count, issueBadge, className }) => ( <i className='icon-with-badge'> <Icon id={id} fixedWidth className={className} /> {count > 0 && <i className='icon-with-badge__badge'>{formatNumber(count)}</i>} + {issueBadge && <i className='icon-with-badge__issue-badge' />} </i> ); IconWithBadge.propTypes = { id: PropTypes.string.isRequired, count: PropTypes.number.isRequired, + issueBadge: PropTypes.bool, className: PropTypes.string, }; diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index 124b34b02f9eca53e8986073a2683de8a463efde..2d87f19b53525b6f602d7d19db7013c32db328a1 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -2,10 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import scheduleIdleTask from '../features/ui/util/schedule_idle_task'; import getRectFromEntry from '../features/ui/util/get_rect_from_entry'; -import { is } from 'immutable'; -// Diff these props in the "rendered" state -const updateOnPropsForRendered = ['id', 'index', 'listLength']; // Diff these props in the "unrendered" state const updateOnPropsForUnrendered = ['id', 'index', 'listLength', 'cachedHeight']; @@ -33,9 +30,12 @@ export default class IntersectionObserverArticle extends React.Component { // If we're going from rendered to unrendered (or vice versa) then update return true; } - // Otherwise, diff based on props - const propsToDiff = isUnrendered ? updateOnPropsForUnrendered : updateOnPropsForRendered; - return !propsToDiff.every(prop => is(nextProps[prop], this.props[prop])); + // If we are and remain hidden, diff based on props + if (isUnrendered) { + return !updateOnPropsForUnrendered.every(prop => nextProps[prop] === this.props[prop]); + } + // Else, assume the children have changed + return true; } componentDidMount () { diff --git a/app/javascript/mastodon/components/modal_root.js b/app/javascript/mastodon/components/modal_root.js index 6297b5e2938f694d2d9e4b65c947d52f909792e1..26344528ea79c4f8151d92e7c0fc91de824d0e72 100644 --- a/app/javascript/mastodon/components/modal_root.js +++ b/app/javascript/mastodon/components/modal_root.js @@ -1,19 +1,21 @@ import React from 'react'; import PropTypes from 'prop-types'; import 'wicg-inert'; +import { multiply } from 'color-blend'; export default class ModalRoot extends React.PureComponent { static propTypes = { children: PropTypes.node, onClose: PropTypes.func.isRequired, + backgroundColor: PropTypes.shape({ + r: PropTypes.number, + g: PropTypes.number, + b: PropTypes.number, + }), }; - state = { - revealed: !!this.props.children, - }; - - activeElement = this.state.revealed ? document.activeElement : null; + activeElement = this.props.children ? document.activeElement : null; handleKeyUp = (e) => { if ((e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27) @@ -53,8 +55,6 @@ export default class ModalRoot extends React.PureComponent { this.activeElement = document.activeElement; this.getSiblings().forEach(sibling => sibling.setAttribute('inert', true)); - } else if (!nextProps.children) { - this.setState({ revealed: false }); } } @@ -68,14 +68,7 @@ export default class ModalRoot extends React.PureComponent { Promise.resolve().then(() => { this.activeElement.focus({ preventScroll: true }); this.activeElement = null; - }).catch((error) => { - console.error(error); - }); - } - if (this.props.children) { - requestAnimationFrame(() => { - this.setState({ revealed: true }); - }); + }).catch(console.error); } } @@ -94,7 +87,6 @@ export default class ModalRoot extends React.PureComponent { render () { const { children, onClose } = this.props; - const { revealed } = this.state; const visible = !!children; if (!visible) { @@ -103,10 +95,16 @@ export default class ModalRoot extends React.PureComponent { ); } + let backgroundColor = null; + + if (this.props.backgroundColor) { + backgroundColor = multiply({ ...this.props.backgroundColor, a: 1 }, { r: 0, g: 0, b: 0, a: 0.7 }); + } + return ( - <div className='modal-root' ref={this.setRef} style={{ opacity: revealed ? 1 : 0 }}> + <div className='modal-root' ref={this.setRef}> <div style={{ pointerEvents: visible ? 'auto' : 'none' }}> - <div role='presentation' className='modal-root__overlay' onClick={onClose} /> + <div role='presentation' className='modal-root__overlay' onClick={onClose} style={{ backgroundColor: backgroundColor ? `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, 0.7)` : null }} /> <div role='dialog' className='modal-root__container'>{children}</div> </div> </div> diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.js b/app/javascript/mastodon/components/picture_in_picture_placeholder.js new file mode 100644 index 0000000000000000000000000000000000000000..19d15c18b16e379250a7193a7f04f2b0b444d2cf --- /dev/null +++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.js @@ -0,0 +1,69 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Icon from 'mastodon/components/icon'; +import { removePictureInPicture } from 'mastodon/actions/picture_in_picture'; +import { connect } from 'react-redux'; +import { debounce } from 'lodash'; +import { FormattedMessage } from 'react-intl'; + +export default @connect() +class PictureInPicturePlaceholder extends React.PureComponent { + + static propTypes = { + width: PropTypes.number, + dispatch: PropTypes.func.isRequired, + }; + + state = { + width: this.props.width, + height: this.props.width && (this.props.width / (16/9)), + }; + + handleClick = () => { + const { dispatch } = this.props; + dispatch(removePictureInPicture()); + } + + setRef = c => { + this.node = c; + + if (this.node) { + this._setDimensions(); + } + } + + _setDimensions () { + const width = this.node.offsetWidth; + const height = width / (16/9); + + this.setState({ width, height }); + } + + componentDidMount () { + window.addEventListener('resize', this.handleResize, { passive: true }); + } + + componentWillUnmount () { + window.removeEventListener('resize', this.handleResize); + } + + handleResize = debounce(() => { + if (this.node) { + this._setDimensions(); + } + }, 250, { + trailing: true, + }); + + render () { + const { height } = this.state; + + return ( + <div ref={this.setRef} className='picture-in-picture-placeholder' style={{ height }} role='button' tabIndex='0' onClick={this.handleClick}> + <Icon id='window-restore' /> + <FormattedMessage id='picture_in_picture.restore' defaultMessage='Put it back' /> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 174e401b7250c6f40b7b3f4c2a2266f6a48278e5..295e83f5819607cf5ada9250c30741d2e9fdb9b8 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -17,6 +17,7 @@ import { HotKeys } from 'react-hotkeys'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; import { displayMedia } from '../initial_state'; +import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder'; // We use the component (and not the container) since we do not want // to use the progress bar to show download progress @@ -95,6 +96,11 @@ class Status extends ImmutablePureComponent { cacheMediaWidth: PropTypes.func, cachedMediaWidth: PropTypes.number, scrollKey: PropTypes.string, + deployPictureInPicture: PropTypes.func, + pictureInPicture: ImmutablePropTypes.contains({ + inUse: PropTypes.bool, + available: PropTypes.bool, + }), }; // Avoid checking props that are functions (and whose equality will always @@ -104,6 +110,8 @@ class Status extends ImmutablePureComponent { 'account', 'muted', 'hidden', + 'unread', + 'pictureInPicture', ]; state = { @@ -184,8 +192,13 @@ class Status extends ImmutablePureComponent { return <div className='audio-player' style={{ height: '110px' }} />; } - handleOpenVideo = (media, options) => { - this.props.onOpenVideo(media, options); + handleOpenVideo = (options) => { + const status = this._properStatus(); + this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), options); + } + + handleOpenMedia = (media, index) => { + this.props.onOpenMedia(this._properStatus().get('id'), media, index); } handleHotkeyOpenMedia = e => { @@ -195,16 +208,21 @@ class Status extends ImmutablePureComponent { e.preventDefault(); if (status.get('media_attachments').size > 0) { - if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { - // TODO: toggle play/paused? - } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - onOpenVideo(status.getIn(['media_attachments', 0]), { startTime: 0 }); + if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), { startTime: 0 }); } else { - onOpenMedia(status.get('media_attachments'), 0); + onOpenMedia(status.get('id'), status.get('media_attachments'), 0); } } } + handleDeployPictureInPicture = (type, mediaProps) => { + const { deployPictureInPicture } = this.props; + const status = this._properStatus(); + + deployPictureInPicture(status, type, mediaProps); + } + handleHotkeyReply = e => { e.preventDefault(); this.props.onReply(this._properStatus(), this.context.router.history); @@ -265,7 +283,7 @@ class Status extends ImmutablePureComponent { let media = null; let statusAvatar, prepend, rebloggedByText; - const { intl, hidden, featured, otherAccounts, unread, showThread, scrollKey } = this.props; + const { intl, hidden, featured, otherAccounts, unread, showThread, scrollKey, pictureInPicture } = this.props; let { status, account, ...other } = this.props; @@ -336,7 +354,9 @@ class Status extends ImmutablePureComponent { status = status.get('reblog'); } - if (status.get('media_attachments').size > 0) { + if (pictureInPicture.get('inUse')) { + media = <PictureInPicturePlaceholder width={this.props.cachedMediaWidth} />; + } else if (status.get('media_attachments').size > 0) { if (this.props.muted) { media = ( <AttachmentList @@ -361,6 +381,7 @@ class Status extends ImmutablePureComponent { width={this.props.cachedMediaWidth} height={110} cacheWidth={this.props.cacheMediaWidth} + deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined} /> )} </Bundle> @@ -373,6 +394,7 @@ class Status extends ImmutablePureComponent { {Component => ( <Component preview={attachment.get('preview_url')} + frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])} blurhash={attachment.get('blurhash')} src={attachment.get('url')} alt={attachment.get('description')} @@ -382,6 +404,7 @@ class Status extends ImmutablePureComponent { sensitive={status.get('sensitive')} onOpenVideo={this.handleOpenVideo} cacheWidth={this.props.cacheMediaWidth} + deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined} visible={this.state.showMedia} onToggleVisibility={this.handleToggleMediaVisibility} /> @@ -396,7 +419,7 @@ class Status extends ImmutablePureComponent { media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} - onOpenMedia={this.props.onOpenMedia} + onOpenMedia={this.handleOpenMedia} cacheWidth={this.props.cacheMediaWidth} defaultWidth={this.props.cachedMediaWidth} visible={this.state.showMedia} @@ -409,7 +432,7 @@ class Status extends ImmutablePureComponent { } else if (status.get('spoiler_text').length === 0 && status.get('card')) { media = ( <Card - onOpenMedia={this.props.onOpenMedia} + onOpenMedia={this.handleOpenMedia} card={status.get('card')} compact cacheWidth={this.props.cacheMediaWidth} @@ -438,14 +461,16 @@ class Status extends ImmutablePureComponent { return ( <HotKeys handlers={handlers}> - <div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), read: unread === false, focusable: !this.props.muted })} tabIndex={this.props.muted ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef}> + <div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef}> {prepend} - <div className={classNames('status', `status-${status.get('visibility')}`, { 'status-reply': !!status.get('in_reply_to_id'), muted: this.props.muted, read: unread === false })} data-id={status.get('id')}> + <div className={classNames('status', `status-${status.get('visibility')}`, { 'status-reply': !!status.get('in_reply_to_id'), muted: this.props.muted })} data-id={status.get('id')}> <div className='status__expand' onClick={this.handleExpandClick} role='presentation' /> <div className='status__info'> - <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a> - <span className='status__visibility-icon'><Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></span> + <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'> + <span className='status__visibility-icon'><Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></span> + <RelativeTimestamp timestamp={status.get('created_at')} /> + </a> <a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'> <div className='status__avatar'> diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index 231c517e9880f621fd087357b4c9f169937827a2..66b5a17ac22c70c77a082ce275278f08f3121452 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -7,6 +7,7 @@ import DropdownMenuContainer from '../containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { me, isStaff } from '../initial_state'; +import classNames from 'classnames'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -20,7 +21,7 @@ const messages = defineMessages({ more: { id: 'status.more', defaultMessage: 'More' }, replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' }, reblog: { id: 'status.reblog', defaultMessage: 'Boost' }, - reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' }, + reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' }, cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' }, cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, @@ -42,16 +43,6 @@ const messages = defineMessages({ unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, }); -const obfuscatedCount = count => { - if (count < 0) { - return 0; - } else if (count <= 1) { - return count; - } else { - return '1+'; - } -}; - const mapStateToProps = (state, { status }) => ({ relationship: state.getIn(['relationships', status.getIn(['account', 'id'])]), }); @@ -328,9 +319,10 @@ class StatusActionBar extends ImmutablePureComponent { return ( <div className='status__action-bar'> - <div className='status__action-bar__counter'><IconButton className='status__action-bar-button' title={replyTitle} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} /><span className='status__action-bar__counter__label' >{obfuscatedCount(status.get('replies_count'))}</span></div> - <IconButton className='status__action-bar-button' disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} pressed={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /> + <IconButton className='status__action-bar-button' title={replyTitle} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} counter={status.get('replies_count')} obfuscateCount /> + <IconButton className={classNames('status__action-bar-button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} pressed={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /> <IconButton className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /> + {shareButton} <div className='status__action-bar-dropdown'> diff --git a/app/javascript/mastodon/components/status_content.js b/app/javascript/mastodon/components/status_content.js index 3200f2d82f6d7f81043b4ae38994fd7d94ecf4f4..185a2a663f9875f2c856016b1be1328decf45a50 100644 --- a/app/javascript/mastodon/components/status_content.js +++ b/app/javascript/mastodon/components/status_content.js @@ -1,7 +1,6 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import { isRtl } from '../rtl'; import { FormattedMessage } from 'react-intl'; import Permalink from './permalink'; import classnames from 'classnames'; @@ -186,17 +185,12 @@ export default class StatusContent extends React.PureComponent { const content = { __html: status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; - const directionStyle = { direction: 'ltr' }; const classNames = classnames('status__content', { 'status__content--with-action': this.props.onClick && this.context.router, 'status__content--with-spoiler': status.get('spoiler_text').length > 0, 'status__content--collapsed': renderReadMore, }); - if (isRtl(status.get('search_index'))) { - directionStyle.direction = 'rtl'; - } - const showThreadButton = ( <button className='status__content__read-more-button' onClick={this.props.onClick}> <FormattedMessage id='status.show_thread' defaultMessage='Show thread' /> @@ -225,7 +219,7 @@ export default class StatusContent extends React.PureComponent { } return ( - <div className={classNames} ref={this.setRef} tabIndex='0' style={directionStyle} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> + <div className={classNames} ref={this.setRef} tabIndex='0' onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }}> <span dangerouslySetInnerHTML={spoilerContent} /> {' '} @@ -234,7 +228,7 @@ export default class StatusContent extends React.PureComponent { {mentionsPlaceholder} - <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} style={directionStyle} dangerouslySetInnerHTML={content} /> + <div tabIndex={!hidden ? 0 : null} className={`status__content__text ${!hidden ? 'status__content__text--visible' : ''}`} dangerouslySetInnerHTML={content} /> {!hidden && !!status.get('poll') && <PollContainer pollId={status.get('poll')} />} @@ -243,8 +237,8 @@ export default class StatusContent extends React.PureComponent { ); } else if (this.props.onClick) { const output = [ - <div className={classNames} ref={this.setRef} tabIndex='0' style={directionStyle} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content'> - <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> + <div className={classNames} ref={this.setRef} tabIndex='0' onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content'> + <div className='status__content__text status__content__text--visible' dangerouslySetInnerHTML={content} /> {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} @@ -259,8 +253,8 @@ export default class StatusContent extends React.PureComponent { return output; } else { return ( - <div className={classNames} ref={this.setRef} tabIndex='0' style={directionStyle}> - <div className='status__content__text status__content__text--visible' style={directionStyle} dangerouslySetInnerHTML={content} /> + <div className={classNames} ref={this.setRef} tabIndex='0'> + <div className='status__content__text status__content__text--visible' dangerouslySetInnerHTML={content} /> {!!status.get('poll') && <PollContainer pollId={status.get('poll')} />} diff --git a/app/javascript/mastodon/containers/media_container.js b/app/javascript/mastodon/containers/media_container.js index ba55ecbc7ba8f42227066f48e74685c1e60915f4..52fdc9294b89c16a16210ee9b390dbba5f6dfb24 100644 --- a/app/javascript/mastodon/containers/media_container.js +++ b/app/javascript/mastodon/containers/media_container.js @@ -2,7 +2,7 @@ import React, { PureComponent, Fragment } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import { IntlProvider, addLocaleData } from 'react-intl'; -import { List as ImmutableList, fromJS } from 'immutable'; +import { fromJS } from 'immutable'; import { getLocale } from 'mastodon/locales'; import { getScrollbarWidth } from 'mastodon/utils/scrollbar'; import MediaGallery from 'mastodon/components/media_gallery'; @@ -30,6 +30,8 @@ export default class MediaContainer extends PureComponent { media: null, index: null, time: null, + backgroundColor: null, + options: null, }; handleOpenMedia = (media, index) => { @@ -39,20 +41,32 @@ export default class MediaContainer extends PureComponent { this.setState({ media, index }); } - handleOpenVideo = (video, time) => { - const media = ImmutableList([video]); + handleOpenVideo = (options) => { + const { components } = this.props; + const { media } = JSON.parse(components[options.componetIndex].getAttribute('data-props')); + const mediaList = fromJS(media); document.body.classList.add('with-modals--active'); document.documentElement.style.marginRight = `${getScrollbarWidth()}px`; - this.setState({ media, time }); + this.setState({ media: mediaList, options }); } handleCloseMedia = () => { document.body.classList.remove('with-modals--active'); document.documentElement.style.marginRight = 0; - this.setState({ media: null, index: null, time: null }); + this.setState({ + media: null, + index: null, + time: null, + backgroundColor: null, + options: null, + }); + } + + setBackgroundColor = color => { + this.setState({ backgroundColor: color }); } render () { @@ -73,6 +87,7 @@ export default class MediaContainer extends PureComponent { ...(hashtag ? { hashtag: fromJS(hashtag) } : {}), ...(componentName === 'Video' ? { + componetIndex: i, onOpenVideo: this.handleOpenVideo, } : { onOpenMedia: this.handleOpenMedia, @@ -85,13 +100,16 @@ export default class MediaContainer extends PureComponent { ); })} - <ModalRoot onClose={this.handleCloseMedia}> + <ModalRoot backgroundColor={this.state.backgroundColor} onClose={this.handleCloseMedia}> {this.state.media && ( <MediaModal media={this.state.media} index={this.state.index || 0} - time={this.state.time} + currentTime={this.state.options?.startTime} + autoPlay={this.state.options?.autoPlay} + volume={this.state.options?.defaultVolume} onClose={this.handleCloseMedia} + onChangeBackgroundColor={this.setBackgroundColor} /> )} </ModalRoot> diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js index decf7279f9a8553e57c574d731f89564fab86165..d6bcb897349a8202ae914fbf404ebe13e2dd9342 100644 --- a/app/javascript/mastodon/containers/status_container.js +++ b/app/javascript/mastodon/containers/status_container.js @@ -1,7 +1,7 @@ import React from 'react'; import { connect } from 'react-redux'; import Status from '../components/status'; -import { makeGetStatus } from '../selectors'; +import { makeGetStatus, makeGetPictureInPicture } from '../selectors'; import { replyCompose, mentionCompose, @@ -37,6 +37,7 @@ import { initMuteModal } from '../actions/mutes'; import { initBlockModal } from '../actions/blocks'; import { initReport } from '../actions/reports'; import { openModal } from '../actions/modal'; +import { deployPictureInPicture } from '../actions/picture_in_picture'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { boostModal, deleteModal } from '../initial_state'; import { showAlertForError } from '../actions/alerts'; @@ -53,9 +54,11 @@ const messages = defineMessages({ const makeMapStateToProps = () => { const getStatus = makeGetStatus(); + const getPictureInPicture = makeGetPictureInPicture(); const mapStateToProps = (state, props) => ({ status: getStatus(state, props), + pictureInPicture: getPictureInPicture(state, props), }); return mapStateToProps; @@ -146,12 +149,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(mentionCompose(account, router)); }, - onOpenMedia (media, index) { - dispatch(openModal('MEDIA', { media, index })); + onOpenMedia (statusId, media, index) { + dispatch(openModal('MEDIA', { statusId, media, index })); }, - onOpenVideo (media, options) { - dispatch(openModal('VIDEO', { media, options })); + onOpenVideo (statusId, media, options) { + dispatch(openModal('VIDEO', { statusId, media, options })); }, onBlock (status) { @@ -207,6 +210,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(unblockDomain(domain)); }, + deployPictureInPicture (status, type, mediaProps) { + dispatch(deployPictureInPicture(status.get('id'), status.getIn(['account', 'id']), type, mediaProps)); + }, + }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status)); diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 9613b0b9edcc46fba73818c684d4d742f1478662..b47ebed62e1327b4f832fcd41b508171ae79c92f 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -7,6 +7,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { autoPlayGif, me, isStaff } from 'mastodon/initial_state'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; +import IconButton from 'mastodon/components/icon_button'; import Avatar from 'mastodon/components/avatar'; import { counterRenderer } from 'mastodon/components/common_counter'; import ShortNumber from 'mastodon/components/short_number'; @@ -35,6 +36,8 @@ const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, + enableNotifications: { id: 'account.enable_notifications', defaultMessage: 'Notify me when @{name} posts' }, + disableNotifications: { id: 'account.disable_notifications', defaultMessage: 'Stop notifying me when @{name} posts' }, pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, @@ -66,6 +69,17 @@ class Header extends ImmutablePureComponent { identity_props: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, + onMention: PropTypes.func.isRequired, + onDirect: PropTypes.func.isRequired, + onReblogToggle: PropTypes.func.isRequired, + onNotifyToggle: PropTypes.func.isRequired, + onReport: PropTypes.func.isRequired, + onMute: PropTypes.func.isRequired, + onBlockDomain: PropTypes.func.isRequired, + onUnblockDomain: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, + onAddToList: PropTypes.func.isRequired, + onEditAccountNote: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, }; @@ -130,8 +144,11 @@ class Header extends ImmutablePureComponent { return null; } + const suspended = account.get('suspended'); + let info = []; let actionBtn = ''; + let bellBtn = ''; let lockedIcon = ''; let menu = []; @@ -147,13 +164,17 @@ class Header extends ImmutablePureComponent { info.push(<span key='domain_blocked' className='relationship-tag'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain blocked' /></span>); } + if (account.getIn(['relationship', 'requested']) || account.getIn(['relationship', 'following'])) { + bellBtn = <IconButton icon='bell-o' size={24} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />; + } + if (me !== account.get('id')) { if (!account.get('relationship')) { // Wait until the relationship is loaded actionBtn = ''; } else if (account.getIn(['relationship', 'requested'])) { - actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />; + actionBtn = <Button className={classNames('logo-button', { 'button--with-bell': bellBtn !== '' })} text={intl.formatMessage(messages.cancel_follow_request)} title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />; } else if (!account.getIn(['relationship', 'blocking'])) { - actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />; + actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']), 'button--with-bell': bellBtn !== '' })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />; } else if (account.getIn(['relationship', 'blocking'])) { actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />; } @@ -258,7 +279,7 @@ class Header extends ImmutablePureComponent { <div className={classNames('account__header', { inactive: !!account.get('moved') })} ref={this.setRef}> <div className='account__header__image'> <div className='account__header__info'> - {info} + {!suspended && info} </div> <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> @@ -272,11 +293,14 @@ class Header extends ImmutablePureComponent { <div className='spacer' /> - <div className='account__header__tabs__buttons'> - {actionBtn} + {!suspended && ( + <div className='account__header__tabs__buttons'> + {actionBtn} + {bellBtn} - <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> - </div> + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> + </div> + )} </div> <div className='account__header__tabs__name'> @@ -288,7 +312,7 @@ class Header extends ImmutablePureComponent { <div className='account__header__extra'> <div className='account__header__bio'> - { (fields.size > 0 || identity_proofs.size > 0) && ( + {(fields.size > 0 || identity_proofs.size > 0) && ( <div className='account__header__fields'> {identity_proofs.map((proof, i) => ( <dl key={i}> @@ -314,33 +338,35 @@ class Header extends ImmutablePureComponent { </div> )} - {account.get('id') !== me && <AccountNoteContainer account={account} />} + {account.get('id') !== me && !suspended && <AccountNoteContainer account={account} />} {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content' dangerouslySetInnerHTML={content} />} </div> - <div className='account__header__extra__links'> - <NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}> - <ShortNumber - value={account.get('statuses_count')} - renderer={counterRenderer('statuses')} - /> - </NavLink> - - <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}> - <ShortNumber - value={account.get('following_count')} - renderer={counterRenderer('following')} - /> - </NavLink> - - <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}> - <ShortNumber - value={account.get('followers_count')} - renderer={counterRenderer('followers')} - /> - </NavLink> - </div> + {!suspended && ( + <div className='account__header__extra__links'> + <NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}> + <ShortNumber + value={account.get('statuses_count')} + renderer={counterRenderer('statuses')} + /> + </NavLink> + + <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}> + <ShortNumber + value={account.get('following_count')} + renderer={counterRenderer('following')} + /> + </NavLink> + + <NavLink exact activeClassName='active' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}> + <ShortNumber + value={account.get('followers_count')} + renderer={counterRenderer('followers')} + /> + </NavLink> + </div> + )} </div> </div> </div> diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.js b/app/javascript/mastodon/features/account_gallery/components/media_item.js index c9a7af7f77929f611dcf4288d4a506c016594a7c..ba7ec46a3307c313658c09e117babe10f8da922f 100644 --- a/app/javascript/mastodon/features/account_gallery/components/media_item.js +++ b/app/javascript/mastodon/features/account_gallery/components/media_item.js @@ -122,7 +122,7 @@ export default class MediaItem extends ImmutablePureComponent { <div className='media-gallery__gifv'> {content} - <span className='media-gallery__gifv__label'>{label}</span> + {label && <span className='media-gallery__gifv__label'>{label}</span>} </div> ); } diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js index fc5aead4868fabbaab9b7176dc39cb1d69c9f16a..015a6a6d7067dc700d35d8928bf9c30f7ad0caad 100644 --- a/app/javascript/mastodon/features/account_gallery/index.js +++ b/app/javascript/mastodon/features/account_gallery/index.js @@ -15,12 +15,15 @@ import { ScrollContainer } from 'react-router-scroll-4'; import LoadMore from 'mastodon/components/load_more'; import MissingIndicator from 'mastodon/components/missing_indicator'; import { openModal } from 'mastodon/actions/modal'; +import { FormattedMessage } from 'react-intl'; const mapStateToProps = (state, props) => ({ isAccount: !!state.getIn(['accounts', props.params.accountId]), attachments: getAccountGallery(state, props.params.accountId), isLoading: state.getIn(['timelines', `account:${props.params.accountId}:media`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${props.params.accountId}:media`, 'hasMore']), + suspended: state.getIn(['accounts', props.params.accountId, 'suspended'], false), + blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false), }); class LoadMoreMedia extends ImmutablePureComponent { @@ -56,6 +59,8 @@ class AccountGallery extends ImmutablePureComponent { isLoading: PropTypes.bool, hasMore: PropTypes.bool, isAccount: PropTypes.bool, + blockedBy: PropTypes.bool, + suspended: PropTypes.bool, multiColumn: PropTypes.bool, }; @@ -100,15 +105,18 @@ class AccountGallery extends ImmutablePureComponent { } handleOpenMedia = attachment => { + const { dispatch } = this.props; + const statusId = attachment.getIn(['status', 'id']); + if (attachment.get('type') === 'video') { - this.props.dispatch(openModal('VIDEO', { media: attachment, status: attachment.get('status'), options: { autoPlay: true } })); + dispatch(openModal('VIDEO', { media: attachment, statusId, options: { autoPlay: true } })); } else if (attachment.get('type') === 'audio') { - this.props.dispatch(openModal('AUDIO', { media: attachment, status: attachment.get('status'), options: { autoPlay: true } })); + dispatch(openModal('AUDIO', { media: attachment, statusId, options: { autoPlay: true } })); } else { const media = attachment.getIn(['status', 'media_attachments']); const index = media.findIndex(x => x.get('id') === attachment.get('id')); - this.props.dispatch(openModal('MEDIA', { media, index, status: attachment.get('status') })); + dispatch(openModal('MEDIA', { media, index, statusId })); } } @@ -119,7 +127,7 @@ class AccountGallery extends ImmutablePureComponent { } render () { - const { attachments, shouldUpdateScroll, isLoading, hasMore, isAccount, multiColumn } = this.props; + const { attachments, shouldUpdateScroll, isLoading, hasMore, isAccount, multiColumn, blockedBy, suspended } = this.props; const { width } = this.state; if (!isAccount) { @@ -144,6 +152,14 @@ class AccountGallery extends ImmutablePureComponent { loadOlder = <LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />; } + let emptyMessage; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (blockedBy) { + emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />; + } + return ( <Column> <ColumnBackButton multiColumn={multiColumn} /> @@ -152,15 +168,21 @@ class AccountGallery extends ImmutablePureComponent { <div className='scrollable scrollable--flex' onScroll={this.handleScroll}> <HeaderContainer accountId={this.props.params.accountId} /> - <div role='feed' className='account-gallery__container' ref={this.handleRef}> - {attachments.map((attachment, index) => attachment === null ? ( - <LoadMoreMedia key={'more:' + attachments.getIn(index + 1, 'id')} maxId={index > 0 ? attachments.getIn(index - 1, 'id') : null} onLoadMore={this.handleLoadMore} /> - ) : ( - <MediaItem key={attachment.get('id')} attachment={attachment} displayWidth={width} onOpenMedia={this.handleOpenMedia} /> - ))} - - {loadOlder} - </div> + {(suspended || blockedBy) ? ( + <div className='empty-column-indicator'> + {emptyMessage} + </div> + ) : ( + <div role='feed' className='account-gallery__container' ref={this.handleRef}> + {attachments.map((attachment, index) => attachment === null ? ( + <LoadMoreMedia key={'more:' + attachments.getIn(index + 1, 'id')} maxId={index > 0 ? attachments.getIn(index - 1, 'id') : null} onLoadMore={this.handleLoadMore} /> + ) : ( + <MediaItem key={attachment.get('id')} attachment={attachment} displayWidth={width} onOpenMedia={this.handleOpenMedia} /> + ))} + + {loadOlder} + </div> + )} {isLoading && attachments.size === 0 && ( <div className='scrollable__append'> diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 4e1b27466b249d5c482b431ac83a3b59b80f885a..6b52defe4a0d2c945fc88567edb0dfa17ed6a987 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -23,7 +23,6 @@ export default class Header extends ImmutablePureComponent { onUnblockDomain: PropTypes.func.isRequired, onEndorseToggle: PropTypes.func.isRequired, onAddToList: PropTypes.func.isRequired, - onEditAccountNote: PropTypes.func.isRequired, hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, }; @@ -56,6 +55,10 @@ export default class Header extends ImmutablePureComponent { this.props.onReblogToggle(this.props.account); } + handleNotifyToggle = () => { + this.props.onNotifyToggle(this.props.account); + } + handleMute = () => { this.props.onMute(this.props.account); } @@ -107,6 +110,7 @@ export default class Header extends ImmutablePureComponent { onMention={this.handleMention} onDirect={this.handleDirect} onReblogToggle={this.handleReblogToggle} + onNotifyToggle={this.handleNotifyToggle} onReport={this.handleReport} onMute={this.handleMute} onBlockDomain={this.handleBlockDomain} diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index 8728b48068a9baa4ddde47f01cbd4ed39fde8798..e12019547ec5ed0a3e2daf09ed4a9a3789e8f427 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -76,9 +76,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onReblogToggle (account) { if (account.getIn(['relationship', 'showing_reblogs'])) { - dispatch(followAccount(account.get('id'), false)); + dispatch(followAccount(account.get('id'), { reblogs: false })); } else { - dispatch(followAccount(account.get('id'), true)); + dispatch(followAccount(account.get('id'), { reblogs: true })); } }, @@ -90,6 +90,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onNotifyToggle (account) { + if (account.getIn(['relationship', 'notifying'])) { + dispatch(followAccount(account.get('id'), { notify: false })); + } else { + dispatch(followAccount(account.get('id'), { notify: true })); + } + }, + onReport (account) { dispatch(initReport(account)); }, diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index 5ea907a1f11fd6c4799c333d4cdc5c594e5695f6..fa4239d6f5f4aad1e899b9b86f71acc7ff8cbeaf 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -15,6 +15,8 @@ import { FormattedMessage } from 'react-intl'; import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; import MissingIndicator from 'mastodon/components/missing_indicator'; import TimelineHint from 'mastodon/components/timeline_hint'; +import { me } from 'mastodon/initial_state'; +import { connectTimeline, disconnectTimeline } from 'mastodon/actions/timelines'; const emptyList = ImmutableList(); @@ -29,6 +31,7 @@ const mapStateToProps = (state, { params: { accountId }, withReplies = false }) featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList), isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), }; }; @@ -55,34 +58,55 @@ class AccountTimeline extends ImmutablePureComponent { withReplies: PropTypes.bool, blockedBy: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, }; componentWillMount () { - const { params: { accountId }, withReplies } = this.props; + const { params: { accountId }, withReplies, dispatch } = this.props; - this.props.dispatch(fetchAccount(accountId)); - this.props.dispatch(fetchAccountIdentityProofs(accountId)); + dispatch(fetchAccount(accountId)); + dispatch(fetchAccountIdentityProofs(accountId)); if (!withReplies) { - this.props.dispatch(expandAccountFeaturedTimeline(accountId)); + dispatch(expandAccountFeaturedTimeline(accountId)); } - this.props.dispatch(expandAccountTimeline(accountId, { withReplies })); + dispatch(expandAccountTimeline(accountId, { withReplies })); + + if (accountId === me) { + dispatch(connectTimeline(`account:${me}`)); + } } componentWillReceiveProps (nextProps) { + const { dispatch } = this.props; + if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { - this.props.dispatch(fetchAccount(nextProps.params.accountId)); - this.props.dispatch(fetchAccountIdentityProofs(nextProps.params.accountId)); + dispatch(fetchAccount(nextProps.params.accountId)); + dispatch(fetchAccountIdentityProofs(nextProps.params.accountId)); if (!nextProps.withReplies) { - this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); + dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); } - this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies })); + dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies })); + } + + if (nextProps.params.accountId === me && this.props.params.accountId !== me) { + dispatch(connectTimeline(`account:${me}`)); + } else if (this.props.params.accountId === me && nextProps.params.accountId !== me) { + dispatch(disconnectTimeline(`account:${me}`)); + } + } + + componentWillUnmount () { + const { dispatch, params: { accountId } } = this.props; + + if (accountId === me) { + dispatch(disconnectTimeline(`account:${me}`)); } } @@ -91,7 +115,7 @@ class AccountTimeline extends ImmutablePureComponent { } render () { - const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, isAccount, multiColumn, remote, remoteUrl } = this.props; + const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, multiColumn, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -112,7 +136,9 @@ class AccountTimeline extends ImmutablePureComponent { let emptyMessage; - if (blockedBy) { + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (blockedBy) { emptyMessage = <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />; } else if (remote && statusIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; @@ -131,7 +157,7 @@ class AccountTimeline extends ImmutablePureComponent { alwaysPrepend append={remoteMessage} scrollKey='account_timeline' - statusIds={blockedBy ? emptyList : statusIds} + statusIds={(suspended || blockedBy) ? emptyList : statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} hasMore={hasMore} diff --git a/app/javascript/mastodon/features/audio/index.js b/app/javascript/mastodon/features/audio/index.js index 1ab1c3117d7cd47c1efdd286be53ee8d7466fb9e..c47f55dd1ea8a42b1cbadec17c3062c585d9a5ce 100644 --- a/app/javascript/mastodon/features/audio/index.js +++ b/app/javascript/mastodon/features/audio/index.js @@ -37,7 +37,11 @@ class Audio extends React.PureComponent { backgroundColor: PropTypes.string, foregroundColor: PropTypes.string, accentColor: PropTypes.string, + currentTime: PropTypes.number, autoPlay: PropTypes.bool, + volume: PropTypes.number, + muted: PropTypes.bool, + deployPictureInPicture: PropTypes.func, }; state = { @@ -64,6 +68,19 @@ class Audio extends React.PureComponent { } } + _pack() { + return { + src: this.props.src, + volume: this.audio.volume, + muted: this.audio.muted, + currentTime: this.audio.currentTime, + poster: this.props.poster, + backgroundColor: this.props.backgroundColor, + foregroundColor: this.props.foregroundColor, + accentColor: this.props.accentColor, + }; + } + _setDimensions () { const width = this.player.offsetWidth; const height = this.props.fullscreen ? this.player.offsetHeight : (width / (16/9)); @@ -112,9 +129,17 @@ class Audio extends React.PureComponent { componentWillUnmount () { window.removeEventListener('scroll', this.handleScroll); window.removeEventListener('resize', this.handleResize); + + if (!this.state.paused && this.audio && this.props.deployPictureInPicture) { + this.props.deployPictureInPicture('audio', this._pack()); + } } togglePlay = () => { + if (!this.audioContext) { + this._initAudioContext(); + } + if (this.state.paused) { this.setState({ paused: false }, () => this.audio.play()); } else { @@ -133,10 +158,6 @@ class Audio extends React.PureComponent { handlePlay = () => { this.setState({ paused: false }); - if (this.canvas && !this.audioContext) { - this._initAudioContext(); - } - if (this.audioContext && this.audioContext.state === 'suspended') { this.audioContext.resume(); } @@ -225,7 +246,7 @@ class Audio extends React.PureComponent { handleTimeUpdate = () => { this.setState({ currentTime: this.audio.currentTime, - duration: Math.floor(this.audio.duration), + duration: this.audio.duration, }); } @@ -248,7 +269,13 @@ class Audio extends React.PureComponent { const inView = (top <= (window.innerHeight || document.documentElement.clientHeight)) && (top + height >= 0); if (!this.state.paused && !inView) { - this.setState({ paused: true }, () => this.audio.pause()); + this.audio.pause(); + + if (this.props.deployPictureInPicture) { + this.props.deployPictureInPicture('audio', this._pack()); + } + + this.setState({ paused: true }); } }, 150, { trailing: true }); @@ -261,16 +288,29 @@ class Audio extends React.PureComponent { } handleLoadedData = () => { - const { autoPlay } = this.props; + const { autoPlay, currentTime, volume, muted } = this.props; + + if (currentTime) { + this.audio.currentTime = currentTime; + } + + if (volume !== undefined) { + this.audio.volume = volume; + } + + if (muted !== undefined) { + this.audio.muted = muted; + } if (autoPlay) { - this.audio.play(); + this.togglePlay(); } } _initAudioContext () { - const context = new AudioContext(); - const source = context.createMediaElementSource(this.audio); + const AudioContext = window.AudioContext || window.webkitAudioContext; + const context = new AudioContext(); + const source = context.createMediaElementSource(this.audio); this.visualizer.setAudioContext(context, source); source.connect(context.destination); @@ -346,13 +386,59 @@ class Audio extends React.PureComponent { return this.props.foregroundColor || '#ffffff'; } + seekBy (time) { + const currentTime = this.audio.currentTime + time; + + if (!isNaN(currentTime)) { + this.setState({ currentTime }, () => { + this.audio.currentTime = currentTime; + }); + } + } + + handleAudioKeyDown = e => { + // On the audio element or the seek bar, we can safely use the space bar + // for playback control because there are no buttons to press + + if (e.key === ' ') { + e.preventDefault(); + e.stopPropagation(); + this.togglePlay(); + } + } + + handleKeyDown = e => { + switch(e.key) { + case 'k': + e.preventDefault(); + e.stopPropagation(); + this.togglePlay(); + break; + case 'm': + e.preventDefault(); + e.stopPropagation(); + this.toggleMute(); + break; + case 'j': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(-10); + break; + case 'l': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(10); + break; + } + } + render () { const { src, intl, alt, editable, autoPlay } = this.props; const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state; - const progress = (currentTime / duration) * 100; + const progress = Math.min((currentTime / duration) * 100, 100); return ( - <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> + <div className={classNames('audio-player', { editable })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), width: '100%', height: this.props.fullscreen ? '100%' : (this.state.height || this.props.height) }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex='0' onKeyDown={this.handleKeyDown}> <audio src={src} ref={this.setAudioRef} @@ -366,12 +452,14 @@ class Audio extends React.PureComponent { <canvas role='button' + tabIndex='0' className='audio-player__canvas' width={this.state.width} height={this.state.height} style={{ width: '100%', position: 'absolute', top: 0, left: 0 }} ref={this.setCanvasRef} onClick={this.togglePlay} + onKeyDown={this.handleAudioKeyDown} title={alt} aria-label={alt} /> @@ -392,20 +480,21 @@ class Audio extends React.PureComponent { className={classNames('video-player__seek__handle', { active: dragging })} tabIndex='0' style={{ left: `${progress}%`, backgroundColor: this._getAccentColor() }} + onKeyDown={this.handleAudioKeyDown} /> </div> <div className='video-player__controls active'> <div className='video-player__buttons-bar'> <div className='video-player__buttons left'> - <button type='button' title={intl.formatMessage(paused ? messages.play : messages.pause)} aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><Icon id={paused ? 'play' : 'pause'} fixedWidth /></button> - <button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button> + <button type='button' title={intl.formatMessage(paused ? messages.play : messages.pause)} aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} className='player-button' onClick={this.togglePlay}><Icon id={paused ? 'play' : 'pause'} fixedWidth /></button> + <button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button> <div className={classNames('video-player__volume', { active: this.state.hovered })} ref={this.setVolumeRef} onMouseDown={this.handleVolumeMouseDown}> <div className='video-player__volume__current' style={{ width: `${volume * 100}%`, backgroundColor: this._getAccentColor() }} /> <span - className={classNames('video-player__volume__handle')} + className='video-player__volume__handle' tabIndex='0' style={{ left: `${volume * 100}%`, backgroundColor: this._getAccentColor() }} /> @@ -414,12 +503,14 @@ class Audio extends React.PureComponent { <span className='video-player__time'> <span className='video-player__time-current'>{formatTime(Math.floor(currentTime))}</span> <span className='video-player__time-sep'>/</span> - <span className='video-player__time-total'>{formatTime(this.state.duration || Math.floor(this.props.duration))}</span> + <span className='video-player__time-total'>{formatTime(Math.floor(this.state.duration || this.props.duration))}</span> </span> </div> <div className='video-player__buttons right'> - <button type='button' title={intl.formatMessage(messages.download)} aria-label={intl.formatMessage(messages.download)} onClick={this.handleDownload}><Icon id='download' fixedWidth /></button> + <a title={intl.formatMessage(messages.download)} aria-label={intl.formatMessage(messages.download)} className='video-player__download__icon player-button' href={this.props.src} download> + <Icon id={'download'} fixedWidth /> + </a> </div> </div> </div> diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 47e189251c9f0d1ab8babe42b69576002db3bfc1..8af806ec437b8d0b748c0ca566e50c38f3a495ff 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -77,6 +77,18 @@ class ComposeForm extends ImmutablePureComponent { } } + getFulltextForCharacterCounting = () => { + return [this.props.spoiler? this.props.spoilerText: '', countableText(this.props.text)].join(''); + } + + canSubmit = () => { + const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; + const fulltext = this.getFulltextForCharacterCounting(); + const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0; + + return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia)); + } + handleSubmit = () => { if (this.props.text !== this.autosuggestTextarea.textarea.value) { // Something changed the text inside the textarea (e.g. browser extensions like Grammarly) @@ -84,11 +96,7 @@ class ComposeForm extends ImmutablePureComponent { this.props.onChange(this.autosuggestTextarea.textarea.value); } - // Submit disabled: - const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; - const fulltext = [this.props.spoilerText, countableText(this.props.text)].join(''); - - if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { + if (!this.canSubmit()) { return; } @@ -178,10 +186,8 @@ class ComposeForm extends ImmutablePureComponent { } render () { - const { intl, onPaste, showSearch, anyMedia } = this.props; + const { intl, onPaste, showSearch } = this.props; const disabled = this.props.isSubmitting; - const text = [this.props.spoilerText, countableText(this.props.text)].join(''); - const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > 500 || (text.length !== 0 && text.trim().length === 0 && !anyMedia); let publishText = ''; if (this.props.privacy === 'private' || this.props.privacy === 'direct') { @@ -243,11 +249,11 @@ class ComposeForm extends ImmutablePureComponent { <PrivacyDropdownContainer /> <SpoilerButtonContainer /> </div> - <div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div> + <div className='character-counter__wrapper'><CharacterCounter max={500} text={this.getFulltextForCharacterCounting()} /></div> </div> <div className='compose-form__publish'> - <div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabledButton} block /></div> + <div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={!this.canSubmit()} block /></div> </div> </div> ); diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js index 360a7af6ab9fcaa5d7d4debfd604d72b192c7f50..dc4f480609e9cc46fa93a3c33d42d8d61bd1b8bc 100644 --- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.js @@ -5,8 +5,9 @@ import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components' import Overlay from 'react-overlays/lib/Overlay'; import classNames from 'classnames'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji'; +import { assetHost } from 'mastodon/utils/config'; const messages = defineMessages({ emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, @@ -25,11 +26,10 @@ const messages = defineMessages({ flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, }); -const assetHost = process.env.CDN_HOST || ''; let EmojiPicker, Emoji; // load asynchronously const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`; -const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false; +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; class ModifierPickerMenu extends React.PureComponent { @@ -315,7 +315,7 @@ class EmojiPickerDropdown extends React.PureComponent { this.setState({ loading: false }); }).catch(() => { - this.setState({ loading: false }); + this.setState({ loading: false, active: false }); }); } diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js index 96028e0421f164fbf399babe2bdcd7daa195d610..309f462903d97a475e933e1c2c08dc3cb96df25d 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js @@ -5,7 +5,7 @@ import IconButton from '../../../components/icon_button'; import Overlay from 'react-overlays/lib/Overlay'; import Motion from '../../ui/util/optional_motion'; import spring from 'react-motion/lib/spring'; -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; @@ -21,7 +21,7 @@ const messages = defineMessages({ change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' }, }); -const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false; +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; class PrivacyDropdownMenu extends React.PureComponent { @@ -179,7 +179,7 @@ class PrivacyDropdown extends React.PureComponent { } else { const { top } = target.getBoundingClientRect(); if (this.state.open && this.activeElement) { - this.activeElement.focus(); + this.activeElement.focus({ preventScroll: true }); } this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); this.setState({ open: !this.state.open }); @@ -220,7 +220,7 @@ class PrivacyDropdown extends React.PureComponent { handleClose = () => { if (this.state.open && this.activeElement) { - this.activeElement.focus(); + this.activeElement.focus({ preventScroll: true }); } this.setState({ open: false }); } diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.js b/app/javascript/mastodon/features/compose/components/reply_indicator.js index 66dc8574216de32ff3c5b3a6061a1f24fff0b513..85638389324e26c4ca2caa8e40edbe31a515a342 100644 --- a/app/javascript/mastodon/features/compose/components/reply_indicator.js +++ b/app/javascript/mastodon/features/compose/components/reply_indicator.js @@ -6,7 +6,6 @@ import IconButton from '../../../components/icon_button'; import DisplayName from '../../../components/display_name'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { isRtl } from '../../../rtl'; import AttachmentList from 'mastodon/components/attachment_list'; const messages = defineMessages({ @@ -45,9 +44,6 @@ class ReplyIndicator extends ImmutablePureComponent { } const content = { __html: status.get('contentHtml') }; - const style = { - direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr', - }; return ( <div className='reply-indicator'> @@ -60,7 +56,7 @@ class ReplyIndicator extends ImmutablePureComponent { </a> </div> - <div className='reply-indicator__content' style={style} dangerouslySetInnerHTML={content} /> + <div className='reply-indicator__content' dangerouslySetInnerHTML={content} /> {status.get('media_attachments').size > 0 && ( <AttachmentList diff --git a/app/javascript/mastodon/features/compose/containers/sensitive_button_container.js b/app/javascript/mastodon/features/compose/containers/sensitive_button_container.js index 7073f76c2e8f81f81189f7003e22edc5f882594e..1bcce57310a86a7422f1bfd7641bd355874ec028 100644 --- a/app/javascript/mastodon/features/compose/containers/sensitive_button_container.js +++ b/app/javascript/mastodon/features/compose/containers/sensitive_button_container.js @@ -6,13 +6,20 @@ import { changeComposeSensitivity } from 'mastodon/actions/compose'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; const messages = defineMessages({ - marked: { id: 'compose_form.sensitive.marked', defaultMessage: 'Media is marked as sensitive' }, - unmarked: { id: 'compose_form.sensitive.unmarked', defaultMessage: 'Media is not marked as sensitive' }, + marked: { + id: 'compose_form.sensitive.marked', + defaultMessage: '{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}', + }, + unmarked: { + id: 'compose_form.sensitive.unmarked', + defaultMessage: '{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}', + }, }); const mapStateToProps = state => ({ active: state.getIn(['compose', 'sensitive']), disabled: state.getIn(['compose', 'spoiler']), + mediaCount: state.getIn(['compose', 'media_attachments']).size, }); const mapDispatchToProps = dispatch => ({ @@ -28,16 +35,17 @@ class SensitiveButton extends React.PureComponent { static propTypes = { active: PropTypes.bool, disabled: PropTypes.bool, + mediaCount: PropTypes.number, onClick: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; render () { - const { active, disabled, onClick, intl } = this.props; + const { active, disabled, mediaCount, onClick, intl } = this.props; return ( <div className='compose-form__sensitive-button'> - <label className={classNames('icon-button', { active })} title={intl.formatMessage(active ? messages.marked : messages.unmarked)}> + <label className={classNames('icon-button', { active })} title={intl.formatMessage(active ? messages.marked : messages.unmarked, { count: mediaCount })}> <input name='mark-sensitive' type='checkbox' @@ -48,7 +56,11 @@ class SensitiveButton extends React.PureComponent { <span className={classNames('checkbox', { active })} /> - <FormattedMessage id='compose_form.sensitive.hide' defaultMessage='Mark media as sensitive' /> + <FormattedMessage + id='compose_form.sensitive.hide' + defaultMessage='{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}' + values={{ count: mediaCount }} + /> </label> </div> ); diff --git a/app/javascript/mastodon/features/compose/containers/warning_container.js b/app/javascript/mastodon/features/compose/containers/warning_container.js index 8200a319f736e64f31cc51beb0a366d5dfa87fc8..bf0660ea9dfeb62c2e2e84ee4e0184bdc1c229dd 100644 --- a/app/javascript/mastodon/features/compose/containers/warning_container.js +++ b/app/javascript/mastodon/features/compose/containers/warning_container.js @@ -5,7 +5,30 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import { me } from '../../../initial_state'; -const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\w*[a-zA-Z·]\w*)/i; +const buildHashtagRE = () => { + try { + const HASHTAG_SEPARATORS = '_\\u00b7\\u200c'; + const ALPHA = '\\p{L}\\p{M}'; + const WORD = '\\p{L}\\p{M}\\p{N}\\p{Pc}'; + return new RegExp( + '(?:^|[^\\/\\)\\w])#((' + + '[' + WORD + '_]' + + '[' + WORD + HASHTAG_SEPARATORS + ']*' + + '[' + ALPHA + HASHTAG_SEPARATORS + ']' + + '[' + WORD + HASHTAG_SEPARATORS +']*' + + '[' + WORD + '_]' + + ')|(' + + '[' + WORD + '_]*' + + '[' + ALPHA + ']' + + '[' + WORD + '_]*' + + '))', 'iu', + ); + } catch { + return /(?:^|[^\/\)\w])#(\w*[a-zA-Z·]\w*)/i; + } +}; + +const APPROX_HASHTAG_RE = buildHashtagRE(); const mapStateToProps = state => ({ needsLockWarning: state.getIn(['compose', 'privacy']) === 'private' && !state.getIn(['accounts', me, 'locked']), diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js index f7d3cfd08ad582ab50ab7624a29ef610380369be..4e37f3a809165de77a039fb082ddc6baaadbf9a3 100644 --- a/app/javascript/mastodon/features/emoji/emoji.js +++ b/app/javascript/mastodon/features/emoji/emoji.js @@ -1,18 +1,17 @@ import { autoPlayGif } from '../../initial_state'; import unicodeMapping from './emoji_unicode_mapping_light'; +import { assetHost } from 'mastodon/utils/config'; import Trie from 'substring-trie'; const trie = new Trie(Object.keys(unicodeMapping)); -const assetHost = process.env.CDN_HOST || ''; - // Convert to file names from emojis. (For different variation selector emojis) const emojiFilenames = (emojis) => { return emojis.map(v => unicodeMapping[v].filename); }; // Emoji requiring extra borders depending on theme -const darkEmoji = emojiFilenames(['🎱', 'ðŸœ', 'âš«', '🖤', '⬛', 'â—¼ï¸', 'â—¾', 'â—¼ï¸', '✒ï¸', 'â–ªï¸', '💣', '🎳', '📷', '📸', '♣ï¸', '🕶ï¸', '✴ï¸', '🔌', '💂â€â™€ï¸', '📽ï¸', 'ðŸ³', 'ðŸ¦', '💂', '🔪', '🕳ï¸', '🕹ï¸', '🕋', '🖊ï¸', '🖋ï¸', '💂â€â™‚ï¸', '🎤', '🎓', '🎥', '🎼', 'â™ ï¸', '🎩', '🦃', '📼', '📹', '🎮', 'ðŸƒ', 'ðŸ´']); +const darkEmoji = emojiFilenames(['🎱', 'ðŸœ', 'âš«', '🖤', '⬛', 'â—¼ï¸', 'â—¾', 'â—¼ï¸', '✒ï¸', 'â–ªï¸', '💣', '🎳', '📷', '📸', '♣ï¸', '🕶ï¸', '✴ï¸', '🔌', '💂â€â™€ï¸', '📽ï¸', 'ðŸ³', 'ðŸ¦', '💂', '🔪', '🕳ï¸', '🕹ï¸', '🕋', '🖊ï¸', '🖋ï¸', '💂â€â™‚ï¸', '🎤', '🎓', '🎥', '🎼', 'â™ ï¸', '🎩', '🦃', '📼', '📹', '🎮', 'ðŸƒ', 'ðŸ´', 'ðŸž', '🕺']); const lightEmoji = emojiFilenames(['👽', 'âš¾', 'ðŸ”', 'â˜ï¸', '💨', '🕊ï¸', '👀', 'ðŸ¥', '👻', 'ðŸ', 'â•', 'â”', '⛸ï¸', '🌩ï¸', '🔊', '🔇', '📃', '🌧ï¸', 'ðŸ', 'ðŸš', 'ðŸ™', 'ðŸ“', 'ðŸ‘', '💀', '☠ï¸', '🌨ï¸', '🔉', '🔈', '💬', 'ðŸ’', 'ðŸ', 'ðŸ³ï¸', '⚪', '⬜', 'â—½', 'â—»ï¸', 'â–«ï¸']); const emojiFilename = (filename) => { diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.js b/app/javascript/mastodon/features/getting_started/components/announcements.js index 1896994daf013bb0efdcb6e1f30d4288dae3dfa4..5bc3abac665129c21081e9bdee4d68ce2ea16d2e 100644 --- a/app/javascript/mastodon/features/getting_started/components/announcements.js +++ b/app/javascript/mastodon/features/getting_started/components/announcements.js @@ -6,7 +6,7 @@ import PropTypes from 'prop-types'; import IconButton from 'mastodon/components/icon_button'; import Icon from 'mastodon/components/icon'; import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl'; -import { autoPlayGif, reduceMotion } from 'mastodon/initial_state'; +import { autoPlayGif, reduceMotion, disableSwiping } from 'mastodon/initial_state'; import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg'; import { mascot } from 'mastodon/initial_state'; import unicodeMapping from 'mastodon/features/emoji/emoji_unicode_mapping_light'; @@ -15,6 +15,7 @@ import EmojiPickerDropdown from 'mastodon/features/compose/containers/emoji_pick import AnimatedNumber from 'mastodon/components/animated_number'; import TransitionMotion from 'react-motion/lib/TransitionMotion'; import spring from 'react-motion/lib/spring'; +import { assetHost } from 'mastodon/utils/config'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -153,8 +154,6 @@ class Content extends ImmutablePureComponent { } -const assetHost = process.env.CDN_HOST || ''; - class Emoji extends React.PureComponent { static propTypes = { @@ -397,7 +396,7 @@ class Announcements extends ImmutablePureComponent { _markAnnouncementAsRead () { const { dismissAnnouncement, announcements } = this.props; const { index } = this.state; - const announcement = announcements.get(index); + const announcement = announcements.get(announcements.size - 1 - index); if (!announcement.get('read')) dismissAnnouncement(announcement.get('id')); } @@ -436,8 +435,9 @@ class Announcements extends ImmutablePureComponent { removeReaction={this.props.removeReaction} intl={intl} selected={index === idx} + disabled={disableSwiping} /> - ))} + )).reverse()} </ReactSwipeableViews> {announcements.size > 1 && ( diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js index d9838e1c7390b178115a952a4e786a2af58dd1ae..1b9994612904498ecae80b3c5136334c138258df 100644 --- a/app/javascript/mastodon/features/getting_started/index.js +++ b/app/javascript/mastodon/features/getting_started/index.js @@ -10,7 +10,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { me, profile_directory, showTrends } from '../../initial_state'; import { fetchFollowRequests } from 'mastodon/actions/accounts'; import { List as ImmutableList } from 'immutable'; -import NavigationBar from '../compose/components/navigation_bar'; +import NavigationContainer from '../compose/containers/navigation_container'; import Icon from 'mastodon/components/icon'; import LinkFooter from 'mastodon/features/ui/components/link_footer'; import TrendsContainer from './containers/trends_container'; @@ -40,6 +40,7 @@ const messages = defineMessages({ const mapStateToProps = state => ({ myAccount: state.getIn(['accounts', me]), + columns: state.getIn(['settings', 'columns']), unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size, }); @@ -89,60 +90,66 @@ class GettingStarted extends ImmutablePureComponent { } render () { - const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props; + const { intl, myAccount, columns, multiColumn, unreadFollowRequests } = this.props; const navItems = []; - let i = 1; let height = (multiColumn) ? 0 : 60; if (multiColumn) { navItems.push( - <ColumnSubheading key={i++} text={intl.formatMessage(messages.discover)} />, - <ColumnLink key={i++} icon='users' text={intl.formatMessage(messages.community_timeline)} to='/timelines/public/local' />, - <ColumnLink key={i++} icon='globe' text={intl.formatMessage(messages.public_timeline)} to='/timelines/public' />, + <ColumnSubheading key='header-discover' text={intl.formatMessage(messages.discover)} />, + <ColumnLink key='community_timeline' icon='users' text={intl.formatMessage(messages.community_timeline)} to='/timelines/public/local' />, + <ColumnLink key='public_timeline' icon='globe' text={intl.formatMessage(messages.public_timeline)} to='/timelines/public' />, ); height += 34 + 48*2; if (profile_directory) { navItems.push( - <ColumnLink key={i++} icon='address-book' text={intl.formatMessage(messages.profile_directory)} to='/directory' />, + <ColumnLink key='directory' icon='address-book' text={intl.formatMessage(messages.profile_directory)} to='/directory' />, ); height += 48; } navItems.push( - <ColumnSubheading key={i++} text={intl.formatMessage(messages.personal)} />, + <ColumnSubheading key='header-personal' text={intl.formatMessage(messages.personal)} />, ); height += 34; } else if (profile_directory) { navItems.push( - <ColumnLink key={i++} icon='address-book' text={intl.formatMessage(messages.profile_directory)} to='/directory' />, + <ColumnLink key='directory' icon='address-book' text={intl.formatMessage(messages.profile_directory)} to='/directory' />, ); height += 48; } + if (multiColumn && !columns.find(item => item.get('id') === 'HOME')) { + navItems.push( + <ColumnLink key='home' icon='home' text={intl.formatMessage(messages.home_timeline)} to='/timelines/home' />, + ); + height += 48; + } + navItems.push( - <ColumnLink key={i++} icon='envelope' text={intl.formatMessage(messages.direct)} to='/timelines/direct' />, - <ColumnLink key={i++} icon='bookmark' text={intl.formatMessage(messages.bookmarks)} to='/bookmarks' />, - <ColumnLink key={i++} icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />, - <ColumnLink key={i++} icon='list-ul' text={intl.formatMessage(messages.lists)} to='/lists' />, + <ColumnLink key='direct' icon='envelope' text={intl.formatMessage(messages.direct)} to='/timelines/direct' />, + <ColumnLink key='bookmark' icon='bookmark' text={intl.formatMessage(messages.bookmarks)} to='/bookmarks' />, + <ColumnLink key='favourites' icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />, + <ColumnLink key='lists' icon='list-ul' text={intl.formatMessage(messages.lists)} to='/lists' />, ); height += 48*4; if (myAccount.get('locked') || unreadFollowRequests > 0) { - navItems.push(<ColumnLink key={i++} icon='user-plus' text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />); + navItems.push(<ColumnLink key='follow_requests' icon='user-plus' text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />); height += 48; } if (!multiColumn) { navItems.push( - <ColumnSubheading key={i++} text={intl.formatMessage(messages.settings_subheading)} />, - <ColumnLink key={i++} icon='gears' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />, + <ColumnSubheading key='header-settings' text={intl.formatMessage(messages.settings_subheading)} />, + <ColumnLink key='preferences' icon='gears' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />, ); height += 34 + 48; @@ -161,7 +168,7 @@ class GettingStarted extends ImmutablePureComponent { <div className='getting-started'> <div className='getting-started__wrapper' style={{ height }}> - {!multiColumn && <NavigationBar account={myAccount} />} + {!multiColumn && <NavigationContainer />} {navItems} </div> diff --git a/app/javascript/mastodon/features/introduction/index.js b/app/javascript/mastodon/features/introduction/index.js index 754477bb992dfc56520a36d01dd4f08b19b4c8f3..5820750a4ee0bd6427719f9fb316eecb42c9e19f 100644 --- a/app/javascript/mastodon/features/introduction/index.js +++ b/app/javascript/mastodon/features/introduction/index.js @@ -9,6 +9,7 @@ import screenHello from '../../../images/screen_hello.svg'; import screenFederation from '../../../images/screen_federation.svg'; import screenInteractions from '../../../images/screen_interactions.svg'; import logoTransparent from '../../../images/logo_transparent.svg'; +import { disableSwiping } from 'mastodon/initial_state'; const FrameWelcome = ({ domain, onNext }) => ( <div className='introduction__frame'> @@ -171,7 +172,7 @@ class Introduction extends React.PureComponent { return ( <div className='introduction'> - <ReactSwipeableViews index={currentIndex} onChangeIndex={this.handleSwipe} className='introduction__pager'> + <ReactSwipeableViews index={currentIndex} onChangeIndex={this.handleSwipe} disabled={disableSwiping} className='introduction__pager'> {pages.map((page, i) => ( <div key={i} className={classNames('introduction__frame-wrapper', { 'active': i === currentIndex })}>{page}</div> ))} diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js index f3205b2bff196466c48c5982dd6bc30367563cc8..02b01824735342dfe9f30f300bf41f0b51a1769c 100644 --- a/app/javascript/mastodon/features/list_timeline/index.js +++ b/app/javascript/mastodon/features/list_timeline/index.js @@ -10,15 +10,19 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { connectListStream } from '../../actions/streaming'; import { expandListTimeline } from '../../actions/timelines'; -import { fetchList, deleteList } from '../../actions/lists'; +import { fetchList, deleteList, updateList } from '../../actions/lists'; import { openModal } from '../../actions/modal'; import MissingIndicator from '../../components/missing_indicator'; import LoadingIndicator from '../../components/loading_indicator'; import Icon from 'mastodon/components/icon'; +import RadioButton from 'mastodon/components/radio_button'; const messages = defineMessages({ deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' }, deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' }, + followed: { id: 'lists.replies_policy.followed', defaultMessage: 'Any followed user' }, + none: { id: 'lists.replies_policy.none', defaultMessage: 'No one' }, + list: { id: 'lists.replies_policy.list', defaultMessage: 'Members of the list' }, }); const mapStateToProps = (state, props) => ({ @@ -131,11 +135,18 @@ class ListTimeline extends React.PureComponent { })); } + handleRepliesPolicyChange = ({ target }) => { + const { dispatch } = this.props; + const { id } = this.props.params; + dispatch(updateList(id, undefined, false, target.value)); + } + render () { - const { shouldUpdateScroll, hasUnread, columnId, multiColumn, list } = this.props; + const { shouldUpdateScroll, hasUnread, columnId, multiColumn, list, intl } = this.props; const { id } = this.props.params; const pinned = !!columnId; const title = list ? list.get('title') : id; + const replies_policy = list ? list.get('replies_policy') : undefined; if (typeof list === 'undefined') { return ( @@ -166,7 +177,7 @@ class ListTimeline extends React.PureComponent { pinned={pinned} multiColumn={multiColumn} > - <div className='column-header__links'> + <div className='column-settings__row column-header__links'> <button className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleEditClick}> <Icon id='pencil' /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' /> </button> @@ -175,6 +186,19 @@ class ListTimeline extends React.PureComponent { <Icon id='trash' /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' /> </button> </div> + + { replies_policy !== undefined && ( + <div role='group' aria-labelledby={`list-${id}-replies-policy`}> + <span id={`list-${id}-replies-policy`} className='column-settings__section'> + <FormattedMessage id='lists.replies_policy.title' defaultMessage='Show replies to:' /> + </span> + <div className='column-settings__row'> + { ['none', 'list', 'followed'].map(policy => ( + <RadioButton name='order' value={policy} label={intl.formatMessage(messages[policy])} checked={replies_policy === policy} onChange={this.handleRepliesPolicyChange} /> + ))} + </div> + </div> + )} </ColumnHeader> <StatusListContainer diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.js b/app/javascript/mastodon/features/notifications/components/column_settings.js index 8bd03fbdab26ef2a05be45d9238106e2824ab849..8339a367ebc72509d49aed36b8c9c38dd504d6b7 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.js +++ b/app/javascript/mastodon/features/notifications/components/column_settings.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage } from 'react-intl'; import ClearColumnButton from './clear_column_button'; +import GrantPermissionButton from './grant_permission_button'; import SettingToggle from './setting_toggle'; export default class ColumnSettings extends React.PureComponent { @@ -12,6 +13,10 @@ export default class ColumnSettings extends React.PureComponent { pushSettings: ImmutablePropTypes.map.isRequired, onChange: PropTypes.func.isRequired, onClear: PropTypes.func.isRequired, + onRequestNotificationPermission: PropTypes.func, + alertsEnabled: PropTypes.bool, + browserSupport: PropTypes.bool, + browserPermission: PropTypes.bool, }; onPushChange = (path, checked) => { @@ -19,7 +24,7 @@ export default class ColumnSettings extends React.PureComponent { } render () { - const { settings, pushSettings, onChange, onClear } = this.props; + const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission } = this.props; const filterShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show' defaultMessage='Show' />; const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />; @@ -32,6 +37,20 @@ export default class ColumnSettings extends React.PureComponent { return ( <div> + {alertsEnabled && browserSupport && browserPermission === 'denied' && ( + <div className='column-settings__row column-settings__row--with-margin'> + <span className='warning-hint'><FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' /></span> + </div> + )} + + {alertsEnabled && browserSupport && browserPermission === 'default' && ( + <div className='column-settings__row column-settings__row--with-margin'> + <span className='warning-hint'> + <FormattedMessage id='notifications.permission_required' defaultMessage='Desktop notifications are unavailable because the required permission has not been granted.' /> <GrantPermissionButton onClick={onRequestNotificationPermission} /> + </span> + </div> + )} + <div className='column-settings__row'> <ClearColumnButton onClick={onClear} /> </div> @@ -40,6 +59,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-filter-bar' className='column-settings__section'> <FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' /> </span> + <div className='column-settings__row'> <SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'show']} onChange={onChange} label={filterShowStr} /> <SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} /> @@ -50,7 +70,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-follow' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} /> @@ -61,7 +81,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-follow-request' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow_request' defaultMessage='New follow requests:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow_request']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow_request']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow_request']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow_request']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow_request']} onChange={onChange} label={soundStr} /> @@ -72,7 +92,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-favourite' className='column-settings__section'><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Favourites:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favourite']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favourite']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favourite']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favourite']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favourite']} onChange={onChange} label={soundStr} /> @@ -83,7 +103,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-mention' className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'mention']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'mention']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'mention']} onChange={onChange} label={soundStr} /> @@ -94,7 +114,7 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-reblog' className='column-settings__section'><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Boosts:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'reblog']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'reblog']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'reblog']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'reblog']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'reblog']} onChange={onChange} label={soundStr} /> @@ -105,12 +125,23 @@ export default class ColumnSettings extends React.PureComponent { <span id='notifications-poll' className='column-settings__section'><FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' /></span> <div className='column-settings__row'> - <SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} /> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} /> {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'poll']} onChange={this.onPushChange} label={pushStr} />} <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'poll']} onChange={onChange} label={showStr} /> <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'poll']} onChange={onChange} label={soundStr} /> </div> </div> + + <div role='group' aria-labelledby='notifications-status'> + <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.status' defaultMessage='New toots:' /></span> + + <div className='column-settings__row'> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'status']} onChange={onChange} label={alertStr} /> + {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'status']} onChange={this.onPushChange} label={pushStr} />} + <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'status']} onChange={onChange} label={showStr} /> + <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'status']} onChange={onChange} label={soundStr} /> + </div> + </div> </div> ); } diff --git a/app/javascript/mastodon/features/notifications/components/filter_bar.js b/app/javascript/mastodon/features/notifications/components/filter_bar.js index 2fd28d832678d3425477b6549904504ae5ae4991..368eb0b7e6c0fa5afcfd730c23dc2757e5ba988e 100644 --- a/app/javascript/mastodon/features/notifications/components/filter_bar.js +++ b/app/javascript/mastodon/features/notifications/components/filter_bar.js @@ -9,6 +9,7 @@ const tooltips = defineMessages({ boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Boosts' }, polls: { id: 'notifications.filter.polls', defaultMessage: 'Poll results' }, follows: { id: 'notifications.filter.follows', defaultMessage: 'Follows' }, + statuses: { id: 'notifications.filter.statuses', defaultMessage: 'Updates from people you follow' }, }); export default @injectIntl @@ -87,6 +88,13 @@ class FilterBar extends React.PureComponent { > <Icon id='tasks' fixedWidth /> </button> + <button + className={selectedFilter === 'status' ? 'active' : ''} + onClick={this.onClick('status')} + title={intl.formatMessage(tooltips.statuses)} + > + <Icon id='home' fixedWidth /> + </button> <button className={selectedFilter === 'follow' ? 'active' : ''} onClick={this.onClick('follow')} diff --git a/app/javascript/mastodon/features/notifications/components/grant_permission_button.js b/app/javascript/mastodon/features/notifications/components/grant_permission_button.js new file mode 100644 index 0000000000000000000000000000000000000000..798e4c7872b24d1eeb9a263bbd39dad4b92d5994 --- /dev/null +++ b/app/javascript/mastodon/features/notifications/components/grant_permission_button.js @@ -0,0 +1,19 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +export default class GrantPermissionButton extends React.PureComponent { + + static propTypes = { + onClick: PropTypes.func.isRequired, + }; + + render () { + return ( + <button className='text-btn column-header__permission-btn' tabIndex='0' onClick={this.props.onClick}> + <FormattedMessage id='notifications.grant_permission' defaultMessage='Grant permission.' /> + </button> + ); + } + +} diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index 74065e5e2686e421f4349934f4c93a4fa8c5e0b3..94fdbd6f4539f23d8cc3712afd8613dae96bc6a0 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -10,6 +10,7 @@ import AccountContainer from 'mastodon/containers/account_container'; import FollowRequestContainer from '../containers/follow_request_container'; import Icon from 'mastodon/components/icon'; import Permalink from 'mastodon/components/permalink'; +import classNames from 'classnames'; const messages = defineMessages({ favourite: { id: 'notification.favourite', defaultMessage: '{name} favourited your status' }, @@ -17,6 +18,7 @@ const messages = defineMessages({ ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' }, poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }, reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' }, + status: { id: 'notification.status', defaultMessage: '{name} just posted' }, }); const notificationForScreenReader = (intl, message, timestamp) => { @@ -49,6 +51,7 @@ class Notification extends ImmutablePureComponent { updateScrollBottom: PropTypes.func, cacheMediaWidth: PropTypes.func, cachedMediaWidth: PropTypes.number, + unread: PropTypes.bool, }; handleMoveUp = () => { @@ -113,11 +116,11 @@ class Notification extends ImmutablePureComponent { } renderFollow (notification, account, link) { - const { intl } = this.props; + const { intl, unread } = this.props; return ( <HotKeys handlers={this.getHandlers()}> - <div className='notification notification-follow focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.follow, { name: account.get('acct') }), notification.get('created_at'))}> + <div className={classNames('notification notification-follow focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.follow, { name: account.get('acct') }), notification.get('created_at'))}> <div className='notification__message'> <div className='notification__favourite-icon-wrapper'> <Icon id='user-plus' fixedWidth /> @@ -135,11 +138,11 @@ class Notification extends ImmutablePureComponent { } renderFollowRequest (notification, account, link) { - const { intl } = this.props; + const { intl, unread } = this.props; return ( <HotKeys handlers={this.getHandlers()}> - <div className='notification notification-follow-request focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow_request', defaultMessage: '{name} has requested to follow you' }, { name: account.get('acct') }), notification.get('created_at'))}> + <div className={classNames('notification notification-follow-request focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage({ id: 'notification.follow_request', defaultMessage: '{name} has requested to follow you' }, { name: account.get('acct') }), notification.get('created_at'))}> <div className='notification__message'> <div className='notification__favourite-icon-wrapper'> <Icon id='user' fixedWidth /> @@ -169,16 +172,17 @@ class Notification extends ImmutablePureComponent { updateScrollBottom={this.props.updateScrollBottom} cachedMediaWidth={this.props.cachedMediaWidth} cacheMediaWidth={this.props.cacheMediaWidth} + unread={this.props.unread} /> ); } renderFavourite (notification, link) { - const { intl } = this.props; + const { intl, unread } = this.props; return ( <HotKeys handlers={this.getHandlers()}> - <div className='notification notification-favourite focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.favourite, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}> + <div className={classNames('notification notification-favourite focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.favourite, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}> <div className='notification__message'> <div className='notification__favourite-icon-wrapper'> <Icon id='star' className='star-icon' fixedWidth /> @@ -206,11 +210,11 @@ class Notification extends ImmutablePureComponent { } renderReblog (notification, link) { - const { intl } = this.props; + const { intl, unread } = this.props; return ( <HotKeys handlers={this.getHandlers()}> - <div className='notification notification-reblog focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.reblog, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}> + <div className={classNames('notification notification-reblog focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.reblog, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}> <div className='notification__message'> <div className='notification__favourite-icon-wrapper'> <Icon id='retweet' fixedWidth /> @@ -237,14 +241,46 @@ class Notification extends ImmutablePureComponent { ); } + renderStatus (notification, link) { + const { intl, unread } = this.props; + + return ( + <HotKeys handlers={this.getHandlers()}> + <div className={classNames('notification notification-status focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.status, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}> + <div className='notification__message'> + <div className='notification__favourite-icon-wrapper'> + <Icon id='home' fixedWidth /> + </div> + + <span title={notification.get('created_at')}> + <FormattedMessage id='notification.status' defaultMessage='{name} just posted' values={{ name: link }} /> + </span> + </div> + + <StatusContainer + id={notification.get('status')} + account={notification.get('account')} + muted + withDismiss + hidden={this.props.hidden} + getScrollPosition={this.props.getScrollPosition} + updateScrollBottom={this.props.updateScrollBottom} + cachedMediaWidth={this.props.cachedMediaWidth} + cacheMediaWidth={this.props.cacheMediaWidth} + /> + </div> + </HotKeys> + ); + } + renderPoll (notification, account) { - const { intl } = this.props; + const { intl, unread } = this.props; const ownPoll = me === account.get('id'); const message = ownPoll ? intl.formatMessage(messages.ownPoll) : intl.formatMessage(messages.poll); return ( <HotKeys handlers={this.getHandlers()}> - <div className='notification notification-poll focusable' tabIndex='0' aria-label={notificationForScreenReader(intl, message, notification.get('created_at'))}> + <div className={classNames('notification notification-poll focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, message, notification.get('created_at'))}> <div className='notification__message'> <div className='notification__favourite-icon-wrapper'> <Icon id='tasks' fixedWidth /> @@ -292,6 +328,8 @@ class Notification extends ImmutablePureComponent { return this.renderFavourite(notification, link); case 'reblog': return this.renderReblog(notification, link); + case 'status': + return this.renderStatus(notification, link); case 'poll': return this.renderPoll(notification, account); } diff --git a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.js b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.js new file mode 100644 index 0000000000000000000000000000000000000000..df9b7fb1b82561e44161d1446f21b80ba42873d4 --- /dev/null +++ b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.js @@ -0,0 +1,48 @@ +import React from 'react'; +import Icon from 'mastodon/components/icon'; +import Button from 'mastodon/components/button'; +import IconButton from 'mastodon/components/icon_button'; +import { requestBrowserPermission } from 'mastodon/actions/notifications'; +import { changeSetting } from 'mastodon/actions/settings'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +export default @connect() +@injectIntl +class NotificationsPermissionBanner extends React.PureComponent { + + static propTypes = { + dispatch: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + handleClick = () => { + this.props.dispatch(requestBrowserPermission()); + } + + handleClose = () => { + this.props.dispatch(changeSetting(['notifications', 'dismissPermissionBanner'], true)); + } + + render () { + const { intl } = this.props; + + return ( + <div className='notifications-permission-banner'> + <div className='notifications-permission-banner__close'> + <IconButton icon='times' onClick={this.handleClose} title={intl.formatMessage(messages.close)} /> + </div> + + <h2><FormattedMessage id='notifications_permission_banner.title' defaultMessage='Never miss a thing' /></h2> + <p><FormattedMessage id='notifications_permission_banner.how_to_control' defaultMessage="To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled." values={{ icon: <Icon id='sliders' /> }} /></p> + <Button onClick={this.handleClick}><FormattedMessage id='notifications_permission_banner.enable' defaultMessage='Enable desktop notifications' /></Button> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/notifications/components/setting_toggle.js b/app/javascript/mastodon/features/notifications/components/setting_toggle.js index e6f593ef89f606375cb88e0ca82f26045ffcb232..c4c8bffbe3240f9ce8f2124e71dcaaf93d3f33d6 100644 --- a/app/javascript/mastodon/features/notifications/components/setting_toggle.js +++ b/app/javascript/mastodon/features/notifications/components/setting_toggle.js @@ -12,6 +12,7 @@ export default class SettingToggle extends React.PureComponent { label: PropTypes.node.isRequired, onChange: PropTypes.func.isRequired, defaultValue: PropTypes.bool, + disabled: PropTypes.bool, } onChange = ({ target }) => { @@ -19,12 +20,12 @@ export default class SettingToggle extends React.PureComponent { } render () { - const { prefix, settings, settingPath, label, defaultValue } = this.props; + const { prefix, settings, settingPath, label, defaultValue, disabled } = this.props; const id = ['setting-toggle', prefix, ...settingPath].filter(Boolean).join('-'); return ( <div className='setting-toggle'> - <Toggle id={id} checked={settings.getIn(settingPath, defaultValue)} onChange={this.onChange} onKeyDown={this.onKeyDown} /> + <Toggle disabled={disabled} id={id} checked={settings.getIn(settingPath, defaultValue)} onChange={this.onChange} onKeyDown={this.onKeyDown} /> <label htmlFor={id} className='setting-toggle__label'>{label}</label> </div> ); diff --git a/app/javascript/mastodon/features/notifications/containers/column_settings_container.js b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js index a67f262953f6a6c2ef6b6b93a1cfee1698825f89..9a70bd4f36136c215e2f7017e0959474b26ef899 100644 --- a/app/javascript/mastodon/features/notifications/containers/column_settings_container.js +++ b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js @@ -3,28 +3,55 @@ import { defineMessages, injectIntl } from 'react-intl'; import ColumnSettings from '../components/column_settings'; import { changeSetting } from '../../../actions/settings'; import { setFilter } from '../../../actions/notifications'; -import { clearNotifications } from '../../../actions/notifications'; +import { clearNotifications, requestBrowserPermission } from '../../../actions/notifications'; import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications'; import { openModal } from '../../../actions/modal'; +import { showAlert } from '../../../actions/alerts'; const messages = defineMessages({ clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' }, clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' }, + permissionDenied: { id: 'notifications.permission_denied_alert', defaultMessage: 'Desktop notifications can\'t be enabled, as browser permission has been denied before' }, }); const mapStateToProps = state => ({ settings: state.getIn(['settings', 'notifications']), pushSettings: state.get('push_notifications'), + alertsEnabled: state.getIn(['settings', 'notifications', 'alerts']).includes(true), + browserSupport: state.getIn(['notifications', 'browserSupport']), + browserPermission: state.getIn(['notifications', 'browserPermission']), }); const mapDispatchToProps = (dispatch, { intl }) => ({ onChange (path, checked) { if (path[0] === 'push') { - dispatch(changePushNotifications(path.slice(1), checked)); + if (checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') { + dispatch(requestBrowserPermission((permission) => { + if (permission === 'granted') { + dispatch(changePushNotifications(path.slice(1), checked)); + } else { + dispatch(showAlert(undefined, messages.permissionDenied)); + } + })); + } else { + dispatch(changePushNotifications(path.slice(1), checked)); + } } else if (path[0] === 'quickFilter') { dispatch(changeSetting(['notifications', ...path], checked)); dispatch(setFilter('all')); + } else if (path[0] === 'alerts' && checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') { + if (checked && typeof window.Notification !== 'undefined' && Notification.permission !== 'granted') { + dispatch(requestBrowserPermission((permission) => { + if (permission === 'granted') { + dispatch(changeSetting(['notifications', ...path], checked)); + } else { + dispatch(showAlert(undefined, messages.permissionDenied)); + } + })); + } else { + dispatch(changeSetting(['notifications', ...path], checked)); + } } else { dispatch(changeSetting(['notifications', ...path], checked)); } @@ -38,6 +65,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ })); }, + onRequestNotificationPermission () { + dispatch(requestBrowserPermission()); + }, + }); export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ColumnSettings)); diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js index d16a0f33a4e1fb984ac649738533d14a43af3090..108470c9a71377face79f9a1ebe97a58c2c27da2 100644 --- a/app/javascript/mastodon/features/notifications/index.js +++ b/app/javascript/mastodon/features/notifications/index.js @@ -4,7 +4,15 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; -import { expandNotifications, scrollTopNotifications, loadPending, mountNotifications, unmountNotifications } from '../../actions/notifications'; +import { + expandNotifications, + scrollTopNotifications, + loadPending, + mountNotifications, + unmountNotifications, + markNotificationsAsRead, +} from '../../actions/notifications'; +import { submitMarkers } from '../../actions/markers'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import NotificationContainer from './containers/notification_container'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; @@ -15,15 +23,25 @@ import { List as ImmutableList } from 'immutable'; import { debounce } from 'lodash'; import ScrollableList from '../../components/scrollable_list'; import LoadGap from '../../components/load_gap'; +import Icon from 'mastodon/components/icon'; +import compareId from 'mastodon/compare_id'; +import NotificationsPermissionBanner from './components/notifications_permission_banner'; const messages = defineMessages({ title: { id: 'column.notifications', defaultMessage: 'Notifications' }, + markAsRead : { id: 'notifications.mark_as_read', defaultMessage: 'Mark every notification as read' }, +}); + +const getExcludedTypes = createSelector([ + state => state.getIn(['settings', 'notifications', 'shows']), +], (shows) => { + return ImmutableList(shows.filter(item => !item).keys()); }); const getNotifications = createSelector([ state => state.getIn(['settings', 'notifications', 'quickFilter', 'show']), state => state.getIn(['settings', 'notifications', 'quickFilter', 'active']), - state => ImmutableList(state.getIn(['settings', 'notifications', 'shows']).filter(item => !item).keys()), + getExcludedTypes, state => state.getIn(['notifications', 'items']), ], (showFilterBar, allowedType, excludedTypes, notifications) => { if (!showFilterBar || allowedType === 'all') { @@ -32,7 +50,7 @@ const getNotifications = createSelector([ // we need to turn it off for FilterBar in order not to block ourselves from seeing a specific category return notifications.filterNot(item => item !== null && excludedTypes.includes(item.get('type'))); } - return notifications.filter(item => item !== null && allowedType === item.get('type')); + return notifications.filter(item => item === null || allowedType === item.get('type')); }); const mapStateToProps = state => ({ @@ -42,6 +60,9 @@ const mapStateToProps = state => ({ isUnread: state.getIn(['notifications', 'unread']) > 0 || state.getIn(['notifications', 'pendingItems']).size > 0, hasMore: state.getIn(['notifications', 'hasMore']), numPending: state.getIn(['notifications', 'pendingItems'], ImmutableList()).size, + lastReadId: state.getIn(['notifications', 'readMarkerId']), + canMarkAsRead: state.getIn(['notifications', 'readMarkerId']) !== '0' && getNotifications(state).some(item => item !== null && compareId(item.get('id'), state.getIn(['notifications', 'readMarkerId'])) > 0), + needsNotificationPermission: state.getIn(['settings', 'notifications', 'alerts']).includes(true) && state.getIn(['notifications', 'browserSupport']) && state.getIn(['notifications', 'browserPermission']) === 'default' && !state.getIn(['settings', 'notifications', 'dismissPermissionBanner']), }); export default @connect(mapStateToProps) @@ -60,6 +81,9 @@ class Notifications extends React.PureComponent { multiColumn: PropTypes.bool, hasMore: PropTypes.bool, numPending: PropTypes.number, + lastReadId: PropTypes.string, + canMarkAsRead: PropTypes.bool, + needsNotificationPermission: PropTypes.bool, }; static defaultProps = { @@ -146,8 +170,13 @@ class Notifications extends React.PureComponent { } } + handleMarkAsRead = () => { + this.props.dispatch(markNotificationsAsRead()); + this.props.dispatch(submitMarkers({ immediate: true })); + }; + render () { - const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar } = this.props; + const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props; const pinned = !!columnId; const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />; @@ -174,6 +203,7 @@ class Notifications extends React.PureComponent { accountId={item.get('account')} onMoveUp={this.handleMoveUp} onMoveDown={this.handleMoveDown} + unread={lastReadId !== '0' && compareId(item.get('id'), lastReadId) > 0} /> )); } else { @@ -190,6 +220,8 @@ class Notifications extends React.PureComponent { showLoading={isLoading && notifications.size === 0} hasMore={hasMore} numPending={numPending} + prepend={needsNotificationPermission && <NotificationsPermissionBanner />} + alwaysPrepend emptyMessage={emptyMessage} onLoadMore={this.handleLoadOlder} onLoadPending={this.handleLoadPending} @@ -202,6 +234,21 @@ class Notifications extends React.PureComponent { </ScrollableList> ); + let extraButton = null; + + if (canMarkAsRead) { + extraButton = ( + <button + aria-label={intl.formatMessage(messages.markAsRead)} + title={intl.formatMessage(messages.markAsRead)} + onClick={this.handleMarkAsRead} + className='column-header__button' + > + <Icon id='check' /> + </button> + ); + } + return ( <Column bindToDocument={!multiColumn} ref={this.setColumnRef} label={intl.formatMessage(messages.title)}> <ColumnHeader @@ -213,6 +260,7 @@ class Notifications extends React.PureComponent { onClick={this.handleHeaderClick} pinned={pinned} multiColumn={multiColumn} + extraButton={extraButton} > <ColumnSettingsContainer /> </ColumnHeader> diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.js b/app/javascript/mastodon/features/picture_in_picture/components/footer.js new file mode 100644 index 0000000000000000000000000000000000000000..1b1ec6d5434b8b5e015745843f9009846ad82aed --- /dev/null +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.js @@ -0,0 +1,159 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; +import IconButton from 'mastodon/components/icon_button'; +import classNames from 'classnames'; +import { me, boostModal } from 'mastodon/initial_state'; +import { defineMessages, injectIntl } from 'react-intl'; +import { replyCompose } from 'mastodon/actions/compose'; +import { reblog, favourite, unreblog, unfavourite } from 'mastodon/actions/interactions'; +import { makeGetStatus } from 'mastodon/selectors'; +import { openModal } from 'mastodon/actions/modal'; + +const messages = defineMessages({ + reply: { id: 'status.reply', defaultMessage: 'Reply' }, + replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' }, + reblog: { id: 'status.reblog', defaultMessage: 'Boost' }, + reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' }, + cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' }, + cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' }, + favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, + replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, + replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, + open: { id: 'status.open', defaultMessage: 'Expand this status' }, +}); + +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); + + const mapStateToProps = (state, { statusId }) => ({ + status: getStatus(state, { id: statusId }), + askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0, + }); + + return mapStateToProps; +}; + +export default @connect(makeMapStateToProps) +@injectIntl +class Footer extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + statusId: PropTypes.string.isRequired, + status: ImmutablePropTypes.map.isRequired, + intl: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + askReplyConfirmation: PropTypes.bool, + withOpenButton: PropTypes.bool, + onClose: PropTypes.func, + }; + + _performReply = () => { + const { dispatch, status, onClose } = this.props; + const { router } = this.context; + + if (onClose) { + onClose(); + } + + dispatch(replyCompose(status, router.history)); + }; + + handleReplyClick = () => { + const { dispatch, askReplyConfirmation, intl } = this.props; + + if (askReplyConfirmation) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: this._performReply, + })); + } else { + this._performReply(); + } + }; + + handleFavouriteClick = () => { + const { dispatch, status } = this.props; + + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + dispatch(favourite(status)); + } + }; + + _performReblog = () => { + const { dispatch, status } = this.props; + dispatch(reblog(status)); + } + + handleReblogClick = e => { + const { dispatch, status } = this.props; + + if (status.get('reblogged')) { + dispatch(unreblog(status)); + } else if ((e && e.shiftKey) || !boostModal) { + this._performReblog(); + } else { + dispatch(openModal('BOOST', { status, onReblog: this._performReblog })); + } + }; + + handleOpenClick = e => { + const { router } = this.context; + + if (e.button !== 0 || !router) { + return; + } + + const { status } = this.props; + + router.history.push(`/statuses/${status.get('id')}`); + } + + render () { + const { status, intl, withOpenButton } = this.props; + + const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); + const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private'; + + let replyIcon, replyTitle; + + if (status.get('in_reply_to_id', null) === null) { + replyIcon = 'reply'; + replyTitle = intl.formatMessage(messages.reply); + } else { + replyIcon = 'reply-all'; + replyTitle = intl.formatMessage(messages.replyAll); + } + + let reblogTitle = ''; + + if (status.get('reblogged')) { + reblogTitle = intl.formatMessage(messages.cancel_reblog_private); + } else if (publicStatus) { + reblogTitle = intl.formatMessage(messages.reblog); + } else if (reblogPrivate) { + reblogTitle = intl.formatMessage(messages.reblog_private); + } else { + reblogTitle = intl.formatMessage(messages.cannot_reblog); + } + + return ( + <div className='picture-in-picture__footer'> + <IconButton className='status__action-bar-button' title={replyTitle} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} counter={status.get('replies_count')} obfuscateCount /> + <IconButton className={classNames('status__action-bar-button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} pressed={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} counter={status.get('reblogs_count')} /> + <IconButton className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} counter={status.get('favourites_count')} /> + {withOpenButton && <IconButton className='status__action-bar-button' title={intl.formatMessage(messages.open)} icon='external-link' onClick={this.handleOpenClick} />} + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.js b/app/javascript/mastodon/features/picture_in_picture/components/header.js new file mode 100644 index 0000000000000000000000000000000000000000..7dd199b75256278129a2076120be8e60f0449620 --- /dev/null +++ b/app/javascript/mastodon/features/picture_in_picture/components/header.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; +import IconButton from 'mastodon/components/icon_button'; +import { Link } from 'react-router-dom'; +import Avatar from 'mastodon/components/avatar'; +import DisplayName from 'mastodon/components/display_name'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +const mapStateToProps = (state, { accountId }) => ({ + account: state.getIn(['accounts', accountId]), +}); + +export default @connect(mapStateToProps) +@injectIntl +class Header extends ImmutablePureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + statusId: PropTypes.string.isRequired, + account: ImmutablePropTypes.map.isRequired, + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + render () { + const { account, statusId, onClose, intl } = this.props; + + return ( + <div className='picture-in-picture__header'> + <Link to={`/statuses/${statusId}`} className='picture-in-picture__header__account'> + <Avatar account={account} size={36} /> + <DisplayName account={account} /> + </Link> + + <IconButton icon='times' onClick={onClose} title={intl.formatMessage(messages.close)} /> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/picture_in_picture/index.js b/app/javascript/mastodon/features/picture_in_picture/index.js new file mode 100644 index 0000000000000000000000000000000000000000..1e59fbcd3376c46589d8ff2421dcd463e0c7313a --- /dev/null +++ b/app/javascript/mastodon/features/picture_in_picture/index.js @@ -0,0 +1,85 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import Video from 'mastodon/features/video'; +import Audio from 'mastodon/features/audio'; +import { removePictureInPicture } from 'mastodon/actions/picture_in_picture'; +import Header from './components/header'; +import Footer from './components/footer'; + +const mapStateToProps = state => ({ + ...state.get('picture_in_picture'), +}); + +export default @connect(mapStateToProps) +class PictureInPicture extends React.Component { + + static propTypes = { + statusId: PropTypes.string, + accountId: PropTypes.string, + type: PropTypes.string, + src: PropTypes.string, + muted: PropTypes.bool, + volume: PropTypes.number, + currentTime: PropTypes.number, + poster: PropTypes.string, + backgroundColor: PropTypes.string, + foregroundColor: PropTypes.string, + accentColor: PropTypes.string, + dispatch: PropTypes.func.isRequired, + }; + + handleClose = () => { + const { dispatch } = this.props; + dispatch(removePictureInPicture()); + } + + render () { + const { type, src, currentTime, accountId, statusId } = this.props; + + if (!currentTime) { + return null; + } + + let player; + + if (type === 'video') { + player = ( + <Video + src={src} + currentTime={this.props.currentTime} + volume={this.props.volume} + muted={this.props.muted} + autoPlay + inline + alwaysVisible + /> + ); + } else if (type === 'audio') { + player = ( + <Audio + src={src} + currentTime={this.props.currentTime} + volume={this.props.volume} + muted={this.props.muted} + poster={this.props.poster} + backgroundColor={this.props.backgroundColor} + foregroundColor={this.props.foregroundColor} + accentColor={this.props.accentColor} + autoPlay + /> + ); + } + + return ( + <div className='picture-in-picture'> + <Header accountId={accountId} statusId={statusId} onClose={this.handleClose} /> + + {player} + + <Footer statusId={statusId} /> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index 1c5d5ca0cae570389df7ae157644ea6962115315..d7d504bc57f8e51794beca7ea58efd6e14d8fa56 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -6,6 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; import { me, isStaff } from '../../../initial_state'; +import classNames from 'classnames'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -14,7 +15,7 @@ const messages = defineMessages({ mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, reply: { id: 'status.reply', defaultMessage: 'Reply' }, reblog: { id: 'status.reblog', defaultMessage: 'Boost' }, - reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' }, + reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' }, cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' }, cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, @@ -273,7 +274,7 @@ class ActionBar extends React.PureComponent { return ( <div className='detailed-status__action-bar'> <div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} /></div> - <div className='detailed-status__button'><IconButton disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div> + <div className='detailed-status__button' ><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div> <div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /></div> {shareButton} <div className='detailed-status__button'><IconButton className='bookmark-icon' active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} /></div> diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js index b1ae0b2cc14afe87ae4d29f655a3bb46907b2126..043a749ede24bec317d69fb2a8874e906f84b49d 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.js @@ -15,6 +15,7 @@ import scheduleIdleTask from '../../ui/util/schedule_idle_task'; import classNames from 'classnames'; import Icon from 'mastodon/components/icon'; import AnimatedNumber from 'mastodon/components/animated_number'; +import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder'; const messages = defineMessages({ public_short: { id: 'privacy.public.short', defaultMessage: 'Public' }, @@ -40,6 +41,10 @@ class DetailedStatus extends ImmutablePureComponent { domain: PropTypes.string.isRequired, compact: PropTypes.bool, showMedia: PropTypes.bool, + pictureInPicture: ImmutablePropTypes.contains({ + inUse: PropTypes.bool, + available: PropTypes.bool, + }), onToggleMediaVisibility: PropTypes.func, }; @@ -56,8 +61,8 @@ class DetailedStatus extends ImmutablePureComponent { e.stopPropagation(); } - handleOpenVideo = (media, options) => { - this.props.onOpenVideo(media, options); + handleOpenVideo = (options) => { + this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), options); } handleExpandedToggle = () => { @@ -100,7 +105,7 @@ class DetailedStatus extends ImmutablePureComponent { render () { const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; const outerStyle = { boxSizing: 'border-box' }; - const { intl, compact } = this.props; + const { intl, compact, pictureInPicture } = this.props; if (!status) { return null; @@ -116,7 +121,9 @@ class DetailedStatus extends ImmutablePureComponent { outerStyle.height = `${this.state.height}px`; } - if (status.get('media_attachments').size > 0) { + if (pictureInPicture.get('inUse')) { + media = <PictureInPicturePlaceholder />; + } else if (status.get('media_attachments').size > 0) { if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); @@ -138,6 +145,7 @@ class DetailedStatus extends ImmutablePureComponent { media = ( <Video preview={attachment.get('preview_url')} + frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])} blurhash={attachment.get('blurhash')} src={attachment.get('url')} alt={attachment.get('description')} diff --git a/app/javascript/mastodon/features/status/containers/detailed_status_container.js b/app/javascript/mastodon/features/status/containers/detailed_status_container.js index 6d5c33240e1a9d668e972de6858406beb5a185c3..0ac4519c89839d6f41140425452bae225d2491bc 100644 --- a/app/javascript/mastodon/features/status/containers/detailed_status_container.js +++ b/app/javascript/mastodon/features/status/containers/detailed_status_container.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import DetailedStatus from '../components/detailed_status'; -import { makeGetStatus } from '../../../selectors'; +import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors'; import { replyCompose, mentionCompose, @@ -40,10 +40,12 @@ const messages = defineMessages({ const makeMapStateToProps = () => { const getStatus = makeGetStatus(); + const getPictureInPicture = makeGetPictureInPicture(); const mapStateToProps = (state, props) => ({ status: getStatus(state, props), domain: state.getIn(['meta', 'domain']), + pictureInPicture: getPictureInPicture(state, props), }); return mapStateToProps; diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 179df53a16de226ed883ea58056b5f459672fe47..09822f372a474c74e4d12705ff20e9f087dfca2d 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -43,7 +43,7 @@ import { import { initMuteModal } from '../../actions/mutes'; import { initBlockModal } from '../../actions/blocks'; import { initReport } from '../../actions/reports'; -import { makeGetStatus } from '../../selectors'; +import { makeGetStatus, makeGetPictureInPicture } from '../../selectors'; import { ScrollContainer } from 'react-router-scroll-4'; import ColumnBackButton from '../../components/column_back_button'; import ColumnHeader from '../../components/column_header'; @@ -72,6 +72,7 @@ const messages = defineMessages({ const makeMapStateToProps = () => { const getStatus = makeGetStatus(); + const getPictureInPicture = makeGetPictureInPicture(); const getAncestorsIds = createSelector([ (_, { id }) => id, @@ -129,11 +130,12 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, props) => { const status = getStatus(state, { id: props.params.statusId }); - let ancestorsIds = Immutable.List(); + + let ancestorsIds = Immutable.List(); let descendantsIds = Immutable.List(); if (status) { - ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') }); + ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') }); descendantsIds = getDescendantsIds(state, { id: status.get('id') }); } @@ -143,6 +145,7 @@ const makeMapStateToProps = () => { descendantsIds, askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0, domain: state.getIn(['meta', 'domain']), + pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }), }; }; @@ -167,6 +170,10 @@ class Status extends ImmutablePureComponent { askReplyConfirmation: PropTypes.bool, multiColumn: PropTypes.bool, domain: PropTypes.string.isRequired, + pictureInPicture: ImmutablePropTypes.contains({ + inUse: PropTypes.bool, + available: PropTypes.bool, + }), }; state = { @@ -274,22 +281,20 @@ class Status extends ImmutablePureComponent { } handleOpenMedia = (media, index) => { - this.props.dispatch(openModal('MEDIA', { media, index })); + this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index })); } handleOpenVideo = (media, options) => { - this.props.dispatch(openModal('VIDEO', { media, options })); + this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, options })); } handleHotkeyOpenMedia = e => { - const status = this._properStatus(); + const { status } = this.props; e.preventDefault(); if (status.get('media_attachments').size > 0) { - if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { - // TODO: toggle play/paused? - } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { + if (status.getIn(['media_attachments', 0, 'type']) === 'video') { this.handleOpenVideo(status.getIn(['media_attachments', 0]), { startTime: 0 }); } else { this.handleOpenMedia(status.get('media_attachments'), 0); @@ -492,7 +497,7 @@ class Status extends ImmutablePureComponent { render () { let ancestors, descendants; - const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl, domain, multiColumn } = this.props; + const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props; const { fullscreen } = this.state; if (status === null) { @@ -550,6 +555,7 @@ class Status extends ImmutablePureComponent { domain={domain} showMedia={this.state.showMedia} onToggleMediaVisibility={this.handleToggleMediaVisibility} + pictureInPicture={pictureInPicture} /> <ActionBar diff --git a/app/javascript/mastodon/features/ui/components/audio_modal.js b/app/javascript/mastodon/features/ui/components/audio_modal.js index a80776b2232bc59c1de824effd4532aeb625117a..0676bd9cf1ce2499a7c59114d86d1579e2978fa5 100644 --- a/app/javascript/mastodon/features/ui/components/audio_modal.js +++ b/app/javascript/mastodon/features/ui/components/audio_modal.js @@ -4,13 +4,11 @@ import PropTypes from 'prop-types'; import Audio from 'mastodon/features/audio'; import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { FormattedMessage } from 'react-intl'; import { previewState } from './video_modal'; -import classNames from 'classnames'; -import Icon from 'mastodon/components/icon'; +import Footer from 'mastodon/features/picture_in_picture/components/footer'; -const mapStateToProps = (state, { status }) => ({ - account: state.getIn(['accounts', status.get('account')]), +const mapStateToProps = (state, { statusId }) => ({ + accountStaticAvatar: state.getIn(['accounts', state.getIn(['statuses', statusId, 'account']), 'avatar_static']), }); export default @connect(mapStateToProps) @@ -18,12 +16,13 @@ class AudioModal extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.map.isRequired, - status: ImmutablePropTypes.map, + statusId: PropTypes.string.isRequired, + accountStaticAvatar: PropTypes.string.isRequired, options: PropTypes.shape({ autoPlay: PropTypes.bool, }), - account: ImmutablePropTypes.map, onClose: PropTypes.func.isRequired, + onChangeBackgroundColor: PropTypes.func.isRequired, }; static contextTypes = { @@ -52,15 +51,8 @@ class AudioModal extends ImmutablePureComponent { } } - handleStatusClick = e => { - if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - this.context.router.history.push(`/statuses/${this.props.status.get('id')}`); - } - } - render () { - const { media, status, account } = this.props; + const { media, accountStaticAvatar, statusId, onClose } = this.props; const options = this.props.options || {}; return ( @@ -71,7 +63,7 @@ class AudioModal extends ImmutablePureComponent { alt={media.get('description')} duration={media.getIn(['meta', 'original', 'duration'], 0)} height={150} - poster={media.get('preview_url') || account.get('avatar_static')} + poster={media.get('preview_url') || accountStaticAvatar} backgroundColor={media.getIn(['meta', 'colors', 'background'])} foregroundColor={media.getIn(['meta', 'colors', 'foreground'])} accentColor={media.getIn(['meta', 'colors', 'accent'])} @@ -79,11 +71,9 @@ class AudioModal extends ImmutablePureComponent { /> </div> - {status && ( - <div className={classNames('media-modal__meta')}> - <a href={status.get('url')} onClick={this.handleStatusClick}><Icon id='comments' /> <FormattedMessage id='lightbox.view_context' defaultMessage='View context' /></a> - </div> - )} + <div className='media-modal__overlay'> + {statusId && <Footer statusId={statusId} withOpenButton onClose={onClose} />} + </div> </div> ); } diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.js b/app/javascript/mastodon/features/ui/components/boost_modal.js index 00c0481f3a598708bb17b25c91e0cedc498e7526..963bb5dc4b5188a5b31af17dc7dfe2708d545bc2 100644 --- a/app/javascript/mastodon/features/ui/components/boost_modal.js +++ b/app/javascript/mastodon/features/ui/components/boost_modal.js @@ -75,9 +75,10 @@ class BoostModal extends ImmutablePureComponent { <div className={classNames('status', `status-${status.get('visibility')}`, 'light')}> <div className='boost-modal__status-header'> <div className='boost-modal__status-time'> - <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'><RelativeTimestamp timestamp={status.get('created_at')} /></a> + <a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener noreferrer'> + <span className='status__visibility-icon'><Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></span> + <RelativeTimestamp timestamp={status.get('created_at')} /></a> </div> - <span className='status__visibility-icon'><Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></span> <a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'> <div className='status__avatar'> diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js index 9b03cf26d274a79388f53a1709c6e50c3696fd79..6837450eb583ecbc6491b3fc46238fcc6f235cff 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.js +++ b/app/javascript/mastodon/features/ui/components/columns_area.js @@ -8,6 +8,8 @@ import ReactSwipeableViews from 'react-swipeable-views'; import TabsBar, { links, getIndex, getLink } from './tabs_bar'; import { Link } from 'react-router-dom'; +import { disableSwiping } from 'mastodon/initial_state'; + import BundleContainer from '../containers/bundle_container'; import ColumnLoading from './column_loading'; import DrawerLoading from './drawer_loading'; @@ -29,7 +31,7 @@ import Icon from 'mastodon/components/icon'; import ComposePanel from './compose_panel'; import NavigationPanel from './navigation_panel'; -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; import { scrollRight } from '../../../scroll'; const componentMap = { @@ -73,12 +75,14 @@ class ColumnsArea extends ImmutablePureComponent { } componentWillReceiveProps() { - this.setState({ shouldAnimate: false }); + if (typeof this.pendingIndex !== 'number' && this.lastIndex !== getIndex(this.context.router.history.location.pathname)) { + this.setState({ shouldAnimate: false }); + } } componentDidMount() { if (!this.props.singleColumn) { - this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); } this.lastIndex = getIndex(this.context.router.history.location.pathname); @@ -95,10 +99,15 @@ class ColumnsArea extends ImmutablePureComponent { componentDidUpdate(prevProps) { if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) { - this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); + } + + const newIndex = getIndex(this.context.router.history.location.pathname); + + if (this.lastIndex !== newIndex) { + this.lastIndex = newIndex; + this.setState({ shouldAnimate: true }); } - this.lastIndex = getIndex(this.context.router.history.location.pathname); - this.setState({ shouldAnimate: true }); } componentWillUnmount () { @@ -185,7 +194,7 @@ class ColumnsArea extends ImmutablePureComponent { const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}><Icon id='pencil' /></Link>; const content = columnIndex !== -1 ? ( - <ReactSwipeableViews key='content' hysteresis={0.2} threshold={15} index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}> + <ReactSwipeableViews key='content' hysteresis={0.2} threshold={15} index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }} disabled={disableSwiping}> {links.map(this.renderView)} </ReactSwipeableViews> ) : ( diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.js b/app/javascript/mastodon/features/ui/components/focal_point_modal.js index 7348d9599a888ade7484f6ea604c6cde7082d1a8..578375a7f4929d9a70a5c36224eaafbe74ba6856 100644 --- a/app/javascript/mastodon/features/ui/components/focal_point_modal.js +++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.js @@ -18,6 +18,11 @@ import { length } from 'stringz'; import { Tesseract as fetchTesseract } from 'mastodon/features/ui/util/async-components'; import GIFV from 'mastodon/components/gifv'; import { me } from 'mastodon/initial_state'; +// eslint-disable-next-line import/no-extraneous-dependencies +import tesseractCorePath from 'tesseract.js-core/tesseract-core.wasm.js'; +// eslint-disable-next-line import/extensions +import tesseractWorkerPath from 'tesseract.js/dist/worker.min.js'; +import { assetHost } from 'mastodon/utils/config'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -48,8 +53,6 @@ const removeExtraLineBreaks = str => str.replace(/\n\n/g, '******') .replace(/\n/g, ' ') .replace(/\*\*\*\*\*\*/g, '\n\n'); -const assetHost = process.env.CDN_HOST || ''; - class ImageLoader extends React.PureComponent { static propTypes = { @@ -104,6 +107,7 @@ class FocalPointModal extends ImmutablePureComponent { dirty: false, progress: 0, loading: true, + ocrStatus: '', }; componentWillMount () { @@ -219,11 +223,18 @@ class FocalPointModal extends ImmutablePureComponent { this.setState({ detecting: true }); - fetchTesseract().then(({ TesseractWorker }) => { - const worker = new TesseractWorker({ - workerPath: `${assetHost}/packs/ocr/worker.min.js`, - corePath: `${assetHost}/packs/ocr/tesseract-core.wasm.js`, - langPath: `${assetHost}/ocr/lang-data`, + fetchTesseract().then(({ createWorker }) => { + const worker = createWorker({ + workerPath: tesseractWorkerPath, + corePath: tesseractCorePath, + langPath: assetHost, + logger: ({ status, progress }) => { + if (status === 'recognizing text') { + this.setState({ ocrStatus: 'detecting', progress }); + } else { + this.setState({ ocrStatus: 'preparing', progress }); + } + }, }); let media_url = media.get('url'); @@ -236,12 +247,18 @@ class FocalPointModal extends ImmutablePureComponent { } } - worker.recognize(media_url) - .progress(({ progress }) => this.setState({ progress })) - .finally(() => worker.terminate()) - .then(({ text }) => this.setState({ description: removeExtraLineBreaks(text), dirty: true, detecting: false })) - .catch(() => this.setState({ detecting: false })); - }).catch(() => this.setState({ detecting: false })); + (async () => { + await worker.load(); + await worker.loadLanguage('eng'); + await worker.initialize('eng'); + const { data: { text } } = await worker.recognize(media_url); + this.setState({ description: removeExtraLineBreaks(text), dirty: true, detecting: false }); + await worker.terminate(); + })(); + }).catch((e) => { + console.error(e); + this.setState({ detecting: false }); + }); } handleThumbnailChange = e => { @@ -261,7 +278,7 @@ class FocalPointModal extends ImmutablePureComponent { render () { const { media, intl, account, onClose, isUploadingThumbnail } = this.props; - const { x, y, dragging, description, dirty, detecting, progress } = this.state; + const { x, y, dragging, description, dirty, detecting, progress, ocrStatus } = this.state; const width = media.getIn(['meta', 'original', 'width']) || null; const height = media.getIn(['meta', 'original', 'height']) || null; @@ -282,6 +299,13 @@ class FocalPointModal extends ImmutablePureComponent { descriptionLabel = <FormattedMessage id='upload_form.description' defaultMessage='Describe for the visually impaired' />; } + let ocrMessage = ''; + if (ocrStatus === 'detecting') { + ocrMessage = <FormattedMessage id='upload_modal.analyzing_picture' defaultMessage='Analyzing picture…' />; + } else { + ocrMessage = <FormattedMessage id='upload_modal.preparing_ocr' defaultMessage='Preparing OCR…' />; + } + return ( <div className='modal-root__modal report-modal' style={{ maxWidth: 960 }}> <div className='report-modal__target'> @@ -333,7 +357,7 @@ class FocalPointModal extends ImmutablePureComponent { /> <div className='setting-text__modifiers'> - <UploadProgress progress={progress * 100} active={detecting} icon='file-text-o' message={<FormattedMessage id='upload_modal.analyzing_picture' defaultMessage='Analyzing picture…' />} /> + <UploadProgress progress={progress * 100} active={detecting} icon='file-text-o' message={ocrMessage} /> </div> </div> @@ -364,6 +388,7 @@ class FocalPointModal extends ImmutablePureComponent { {media.get('type') === 'video' && ( <Video preview={media.get('preview_url')} + frameRate={media.getIn(['meta', 'original', 'frame_rate'])} blurhash={media.get('blurhash')} src={media.get('url')} detailed diff --git a/app/javascript/mastodon/features/ui/components/image_loader.js b/app/javascript/mastodon/features/ui/components/image_loader.js index 5e1cf75af79aad303c4a5be2edcd239c97b77de5..c6f16a79237e44ee6cd205e5e2196045c3bbe222 100644 --- a/app/javascript/mastodon/features/ui/components/image_loader.js +++ b/app/javascript/mastodon/features/ui/components/image_loader.js @@ -13,6 +13,7 @@ export default class ImageLoader extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, onClick: PropTypes.func, + zoomButtonHidden: PropTypes.bool, } static defaultProps = { @@ -151,6 +152,9 @@ export default class ImageLoader extends React.PureComponent { alt={alt} src={src} onClick={onClick} + width={width} + height={height} + zoomButtonHidden={this.props.zoomButtonHidden} /> )} </div> diff --git a/app/javascript/mastodon/features/ui/components/media_modal.js b/app/javascript/mastodon/features/ui/components/media_modal.js index d7f97f210c9e0879965c483df85de601859f1b5c..08da1033042b6458b226e3adbbc9d6f9ed732c08 100644 --- a/app/javascript/mastodon/features/ui/components/media_modal.js +++ b/app/javascript/mastodon/features/ui/components/media_modal.js @@ -4,12 +4,15 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import Video from 'mastodon/features/video'; import classNames from 'classnames'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; import IconButton from 'mastodon/components/icon_button'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ImageLoader from './image_loader'; import Icon from 'mastodon/components/icon'; import GIFV from 'mastodon/components/gifv'; +import { disableSwiping } from 'mastodon/initial_state'; +import Footer from 'mastodon/features/picture_in_picture/components/footer'; +import { getAverageFromBlurhash } from 'mastodon/blurhash'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -24,10 +27,14 @@ class MediaModal extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.list.isRequired, - status: ImmutablePropTypes.map, + statusId: PropTypes.string, index: PropTypes.number.isRequired, onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + onChangeBackgroundColor: PropTypes.func.isRequired, + currentTime: PropTypes.number, + autoPlay: PropTypes.bool, + volume: PropTypes.number, }; static contextTypes = { @@ -37,23 +44,40 @@ class MediaModal extends ImmutablePureComponent { state = { index: null, navigationHidden: false, + zoomButtonHidden: false, }; handleSwipe = (index) => { this.setState({ index: index % this.props.media.size }); } + handleTransitionEnd = () => { + this.setState({ + zoomButtonHidden: false, + }); + } + handleNextClick = () => { - this.setState({ index: (this.getIndex() + 1) % this.props.media.size }); + this.setState({ + index: (this.getIndex() + 1) % this.props.media.size, + zoomButtonHidden: true, + }); } handlePrevClick = () => { - this.setState({ index: (this.props.media.size + this.getIndex() - 1) % this.props.media.size }); + this.setState({ + index: (this.props.media.size + this.getIndex() - 1) % this.props.media.size, + zoomButtonHidden: true, + }); } handleChangeIndex = (e) => { const index = Number(e.currentTarget.getAttribute('data-index')); - this.setState({ index: index % this.props.media.size }); + + this.setState({ + index: index % this.props.media.size, + zoomButtonHidden: true, + }); } handleKeyDown = (e) => { @@ -83,6 +107,25 @@ class MediaModal extends ImmutablePureComponent { this.props.onClose(); }); } + + this._sendBackgroundColor(); + } + + componentDidUpdate (prevProps, prevState) { + if (prevState.index !== this.state.index) { + this._sendBackgroundColor(); + } + } + + _sendBackgroundColor () { + const { media, onChangeBackgroundColor } = this.props; + const index = this.getIndex(); + const blurhash = media.getIn([index, 'blurhash']); + + if (blurhash) { + const backgroundColor = getAverageFromBlurhash(blurhash); + onChangeBackgroundColor(backgroundColor); + } } componentWillUnmount () { @@ -95,6 +138,8 @@ class MediaModal extends ImmutablePureComponent { this.context.router.history.goBack(); } } + + this.props.onChangeBackgroundColor(null); } getIndex () { @@ -110,30 +155,19 @@ class MediaModal extends ImmutablePureComponent { handleStatusClick = e => { if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); - this.context.router.history.push(`/statuses/${this.props.status.get('id')}`); + this.context.router.history.push(`/statuses/${this.props.statusId}`); } } render () { - const { media, status, intl, onClose } = this.props; + const { media, statusId, intl, onClose } = this.props; const { navigationHidden } = this.state; const index = this.getIndex(); - let pagination = []; const leftNav = media.size > 1 && <button tabIndex='0' className='media-modal__nav media-modal__nav--left' onClick={this.handlePrevClick} aria-label={intl.formatMessage(messages.previous)}><Icon id='chevron-left' fixedWidth /></button>; const rightNav = media.size > 1 && <button tabIndex='0' className='media-modal__nav media-modal__nav--right' onClick={this.handleNextClick} aria-label={intl.formatMessage(messages.next)}><Icon id='chevron-right' fixedWidth /></button>; - if (media.size > 1) { - pagination = media.map((item, i) => { - const classes = ['media-modal__button']; - if (i === index) { - classes.push('media-modal__button--active'); - } - return (<li className='media-modal__page-dot' key={i}><button tabIndex='0' className={classes.join(' ')} onClick={this.handleChangeIndex} data-index={i}>{i + 1}</button></li>); - }); - } - const content = media.map((image) => { const width = image.getIn(['meta', 'original', 'width']) || null; const height = image.getIn(['meta', 'original', 'height']) || null; @@ -148,10 +182,11 @@ class MediaModal extends ImmutablePureComponent { alt={image.get('description')} key={image.get('url')} onClick={this.toggleNavigation} + zoomButtonHidden={this.state.zoomButtonHidden} /> ); } else if (image.get('type') === 'video') { - const { time } = this.props; + const { currentTime, autoPlay, volume } = this.props; return ( <Video @@ -160,7 +195,10 @@ class MediaModal extends ImmutablePureComponent { src={image.get('url')} width={image.get('width')} height={image.get('height')} - startTime={time || 0} + frameRate={image.getIn(['meta', 'original', 'frame_rate'])} + currentTime={currentTime || 0} + autoPlay={autoPlay || false} + volume={volume || 1} onCloseVideo={onClose} detailed alt={image.get('description')} @@ -200,18 +238,26 @@ class MediaModal extends ImmutablePureComponent { 'media-modal__navigation--hidden': navigationHidden, }); + let pagination; + + if (media.size > 1) { + pagination = media.map((item, i) => ( + <button key={i} className={classNames('media-modal__page-dot', { active: i === index })} data-index={i} onClick={this.handleChangeIndex}> + {i + 1} + </button> + )); + } + return ( <div className='modal-root__modal media-modal'> - <div - className='media-modal__closer' - role='presentation' - onClick={onClose} - > + <div className='media-modal__closer' role='presentation' onClick={onClose} > <ReactSwipeableViews style={swipeableViewsStyle} containerStyle={containerStyle} onChangeIndex={this.handleSwipe} + onTransitionEnd={this.handleTransitionEnd} index={index} + disabled={disableSwiping} > {content} </ReactSwipeableViews> @@ -223,15 +269,10 @@ class MediaModal extends ImmutablePureComponent { {leftNav} {rightNav} - {status && ( - <div className={classNames('media-modal__meta', { 'media-modal__meta--shifted': media.size > 1 })}> - <a href={status.get('url')} onClick={this.handleStatusClick}><Icon id='comments' /> <FormattedMessage id='lightbox.view_context' defaultMessage='View context' /></a> - </div> - )} - - <ul className='media-modal__pagination'> - {pagination} - </ul> + <div className='media-modal__overlay'> + {pagination && <ul className='media-modal__pagination'>{pagination}</ul>} + {statusId && <Footer statusId={statusId} withOpenButton onClose={onClose} />} + </div> </div> </div> ); diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js index 5cf70a0cc2d7b880e660e1f1c2ea9125960f237b..3403830e41fca2ecd5d9f24cfd0320afe2d07efe 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.js +++ b/app/javascript/mastodon/features/ui/components/modal_root.js @@ -45,6 +45,10 @@ export default class ModalRoot extends React.PureComponent { onClose: PropTypes.func.isRequired, }; + state = { + backgroundColor: null, + }; + getSnapshotBeforeUpdate () { return { visible: !!this.props.type }; } @@ -59,6 +63,10 @@ export default class ModalRoot extends React.PureComponent { } } + setBackgroundColor = color => { + this.setState({ backgroundColor: color }); + } + renderLoading = modalId => () => { return ['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? <ModalLoading /> : null; } @@ -71,13 +79,14 @@ export default class ModalRoot extends React.PureComponent { render () { const { type, props, onClose } = this.props; + const { backgroundColor } = this.state; const visible = !!type; return ( - <Base onClose={onClose}> + <Base backgroundColor={backgroundColor} onClose={onClose}> {visible && ( <BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}> - {(SpecificComponent) => <SpecificComponent {...props} onClose={onClose} />} + {(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={onClose} />} </BundleContainer> )} </Base> diff --git a/app/javascript/mastodon/features/ui/components/mute_modal.js b/app/javascript/mastodon/features/ui/components/mute_modal.js index 852830c3c2c93fd7c87de88e029db557bda9b3e1..d8d8e68c384dbc22233721cd1361581a901f4166 100644 --- a/app/javascript/mastodon/features/ui/components/mute_modal.js +++ b/app/javascript/mastodon/features/ui/components/mute_modal.js @@ -1,25 +1,32 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import { injectIntl, FormattedMessage } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Toggle from 'react-toggle'; import Button from '../../../components/button'; import { closeModal } from '../../../actions/modal'; import { muteAccount } from '../../../actions/accounts'; -import { toggleHideNotifications } from '../../../actions/mutes'; +import { toggleHideNotifications, changeMuteDuration } from '../../../actions/mutes'; +const messages = defineMessages({ + minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' }, + hours: { id: 'intervals.full.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}}' }, + days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' }, + indefinite: { id: 'mute_modal.indefinite', defaultMessage: 'Indefinite' }, +}); const mapStateToProps = state => { return { account: state.getIn(['mutes', 'new', 'account']), notifications: state.getIn(['mutes', 'new', 'notifications']), + muteDuration: state.getIn(['mutes', 'new', 'duration']), }; }; const mapDispatchToProps = dispatch => { return { - onConfirm(account, notifications) { - dispatch(muteAccount(account.get('id'), notifications)); + onConfirm(account, notifications, muteDuration) { + dispatch(muteAccount(account.get('id'), notifications, muteDuration)); }, onClose() { @@ -29,6 +36,10 @@ const mapDispatchToProps = dispatch => { onToggleNotifications() { dispatch(toggleHideNotifications()); }, + + onChangeMuteDuration(e) { + dispatch(changeMuteDuration(e.target.value)); + }, }; }; @@ -43,6 +54,8 @@ class MuteModal extends React.PureComponent { onConfirm: PropTypes.func.isRequired, onToggleNotifications: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, + muteDuration: PropTypes.number.isRequired, + onChangeMuteDuration: PropTypes.func.isRequired, }; componentDidMount() { @@ -51,7 +64,7 @@ class MuteModal extends React.PureComponent { handleClick = () => { this.props.onClose(); - this.props.onConfirm(this.props.account, this.props.notifications); + this.props.onConfirm(this.props.account, this.props.notifications, this.props.muteDuration); } handleCancel = () => { @@ -66,8 +79,12 @@ class MuteModal extends React.PureComponent { this.props.onToggleNotifications(); } + changeMuteDuration = (e) => { + this.props.onChangeMuteDuration(e); + } + render () { - const { account, notifications } = this.props; + const { account, notifications, muteDuration, intl } = this.props; return ( <div className='modal-root__modal mute-modal'> @@ -91,6 +108,21 @@ class MuteModal extends React.PureComponent { <FormattedMessage id='mute_modal.hide_notifications' defaultMessage='Hide notifications from this user?' /> </label> </div> + <div> + <span><FormattedMessage id='mute_modal.duration' defaultMessage='Duration' />: </span> + + {/* eslint-disable-next-line jsx-a11y/no-onchange */} + <select value={muteDuration} onChange={this.changeMuteDuration}> + <option value={0}>{intl.formatMessage(messages.indefinite)}</option> + <option value={300}>{intl.formatMessage(messages.minutes, { number: 5 })}</option> + <option value={1800}>{intl.formatMessage(messages.minutes, { number: 30 })}</option> + <option value={3600}>{intl.formatMessage(messages.hours, { number: 1 })}</option> + <option value={21600}>{intl.formatMessage(messages.hours, { number: 6 })}</option> + <option value={86400}>{intl.formatMessage(messages.days, { number: 1 })}</option> + <option value={259200}>{intl.formatMessage(messages.days, { number: 3 })}</option> + <option value={604800}>{intl.formatMessage(messages.days, { number: 7 })}</option> + </select> + </div> </div> <div className='mute-modal__action-bar'> diff --git a/app/javascript/mastodon/features/ui/components/video_modal.js b/app/javascript/mastodon/features/ui/components/video_modal.js index e28bd5b4915dbb6f246016e66ce9e8ce5a3c513b..2f13a175a1d1c279d719713991fb802568e64cb2 100644 --- a/app/javascript/mastodon/features/ui/components/video_modal.js +++ b/app/javascript/mastodon/features/ui/components/video_modal.js @@ -3,9 +3,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import Video from 'mastodon/features/video'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { FormattedMessage } from 'react-intl'; -import classNames from 'classnames'; -import Icon from 'mastodon/components/icon'; +import Footer from 'mastodon/features/picture_in_picture/components/footer'; +import { getAverageFromBlurhash } from 'mastodon/blurhash'; export const previewState = 'previewVideoModal'; @@ -13,13 +12,14 @@ export default class VideoModal extends ImmutablePureComponent { static propTypes = { media: ImmutablePropTypes.map.isRequired, - status: ImmutablePropTypes.map, + statusId: PropTypes.string, options: PropTypes.shape({ startTime: PropTypes.number, autoPlay: PropTypes.bool, defaultVolume: PropTypes.number, }), onClose: PropTypes.func.isRequired, + onChangeBackgroundColor: PropTypes.func.isRequired, }; static contextTypes = { @@ -27,36 +27,35 @@ export default class VideoModal extends ImmutablePureComponent { }; componentDidMount () { - if (this.context.router) { - const history = this.context.router.history; + const { router } = this.context; + const { media, onChangeBackgroundColor, onClose } = this.props; - history.push(history.location.pathname, previewState); + if (router) { + router.history.push(router.history.location.pathname, previewState); + this.unlistenHistory = router.history.listen(() => onClose()); + } + + const backgroundColor = getAverageFromBlurhash(media.get('blurhash')); - this.unlistenHistory = history.listen(() => { - this.props.onClose(); - }); + if (backgroundColor) { + onChangeBackgroundColor(backgroundColor); } } componentWillUnmount () { - if (this.context.router) { + const { router } = this.context; + + if (router) { this.unlistenHistory(); - if (this.context.router.history.location.state === previewState) { - this.context.router.history.goBack(); + if (router.history.location.state === previewState) { + router.history.goBack(); } } } - handleStatusClick = e => { - if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - this.context.router.history.push(`/statuses/${this.props.status.get('id')}`); - } - } - render () { - const { media, status, onClose } = this.props; + const { media, statusId, onClose } = this.props; const options = this.props.options || {}; return ( @@ -64,22 +63,21 @@ export default class VideoModal extends ImmutablePureComponent { <div className='video-modal__container'> <Video preview={media.get('preview_url')} + frameRate={media.getIn(['meta', 'original', 'frame_rate'])} blurhash={media.get('blurhash')} src={media.get('url')} - startTime={options.startTime} + currentTime={options.startTime} autoPlay={options.autoPlay} - defaultVolume={options.defaultVolume} + volume={options.defaultVolume} onCloseVideo={onClose} detailed alt={media.get('description')} /> </div> - {status && ( - <div className={classNames('media-modal__meta')}> - <a href={status.get('url')} onClick={this.handleStatusClick}><Icon id='comments' /> <FormattedMessage id='lightbox.view_context' defaultMessage='View context' /></a> - </div> - )} + <div className='media-modal__overlay'> + {statusId && <Footer statusId={statusId} withOpenButton onClose={onClose} />} + </div> </div> ); } diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.js b/app/javascript/mastodon/features/ui/components/zoomable_image.js index 3f6562bc991bdeb45f8fcd44f0bd800317f401c3..1cf263cb9003d5b081e141145b7105de1b62108c 100644 --- a/app/javascript/mastodon/features/ui/components/zoomable_image.js +++ b/app/javascript/mastodon/features/ui/components/zoomable_image.js @@ -1,8 +1,16 @@ import React from 'react'; import PropTypes from 'prop-types'; +import IconButton from 'mastodon/components/icon_button'; +import { defineMessages, injectIntl } from 'react-intl'; + +const messages = defineMessages({ + compress: { id: 'lightbox.compress', defaultMessage: 'Compress image view box' }, + expand: { id: 'lightbox.expand', defaultMessage: 'Expand image view box' }, +}); const MIN_SCALE = 1; const MAX_SCALE = 4; +const NAV_BAR_HEIGHT = 66; const getMidpoint = (p1, p2) => ({ x: (p1.clientX + p2.clientX) / 2, @@ -14,7 +22,77 @@ const getDistance = (p1, p2) => const clamp = (min, max, value) => Math.min(max, Math.max(min, value)); -export default class ZoomableImage extends React.PureComponent { +// Normalizing mousewheel speed across browsers +// copy from: https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js +const normalizeWheel = event => { + // Reasonable defaults + const PIXEL_STEP = 10; + const LINE_HEIGHT = 40; + const PAGE_HEIGHT = 800; + + let sX = 0, + sY = 0, // spinX, spinY + pX = 0, + pY = 0; // pixelX, pixelY + + // Legacy + if ('detail' in event) { + sY = event.detail; + } + if ('wheelDelta' in event) { + sY = -event.wheelDelta / 120; + } + if ('wheelDeltaY' in event) { + sY = -event.wheelDeltaY / 120; + } + if ('wheelDeltaX' in event) { + sX = -event.wheelDeltaX / 120; + } + + // side scrolling on FF with DOMMouseScroll + if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) { + sX = sY; + sY = 0; + } + + pX = sX * PIXEL_STEP; + pY = sY * PIXEL_STEP; + + if ('deltaY' in event) { + pY = event.deltaY; + } + if ('deltaX' in event) { + pX = event.deltaX; + } + + if ((pX || pY) && event.deltaMode) { + if (event.deltaMode === 1) { // delta in LINE units + pX *= LINE_HEIGHT; + pY *= LINE_HEIGHT; + } else { // delta in PAGE units + pX *= PAGE_HEIGHT; + pY *= PAGE_HEIGHT; + } + } + + // Fall-back if spin cannot be determined + if (pX && !sX) { + sX = (pX < 1) ? -1 : 1; + } + if (pY && !sY) { + sY = (pY < 1) ? -1 : 1; + } + + return { + spinX: sX, + spinY: sY, + pixelX: pX, + pixelY: pY, + }; +}; + +export default @injectIntl +class ZoomableImage extends React.PureComponent { static propTypes = { alt: PropTypes.string, @@ -22,6 +100,8 @@ export default class ZoomableImage extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, onClick: PropTypes.func, + zoomButtonHidden: PropTypes.bool, + intl: PropTypes.object.isRequired, } static defaultProps = { @@ -32,6 +112,26 @@ export default class ZoomableImage extends React.PureComponent { state = { scale: MIN_SCALE, + zoomMatrix: { + type: null, // 'width' 'height' + fullScreen: null, // bool + rate: null, // full screen scale rate + clientWidth: null, + clientHeight: null, + offsetWidth: null, + offsetHeight: null, + clientHeightFixed: null, + scrollTop: null, + scrollLeft: null, + translateX: null, + translateY: null, + }, + zoomState: 'expand', // 'expand' 'compress' + navigationHidden: false, + dragPosition: { top: 0, left: 0, x: 0, y: 0 }, + dragged: false, + lockScroll: { x: 0, y: 0 }, + lockTranslate: { x: 0, y: 0 }, } removers = []; @@ -49,17 +149,105 @@ export default class ZoomableImage extends React.PureComponent { // https://www.chromestatus.com/features/5093566007214080 this.container.addEventListener('touchmove', handler, { passive: false }); this.removers.push(() => this.container.removeEventListener('touchend', handler)); + + handler = this.mouseDownHandler; + this.container.addEventListener('mousedown', handler); + this.removers.push(() => this.container.removeEventListener('mousedown', handler)); + + handler = this.mouseWheelHandler; + this.container.addEventListener('wheel', handler); + this.removers.push(() => this.container.removeEventListener('wheel', handler)); + // Old Chrome + this.container.addEventListener('mousewheel', handler); + this.removers.push(() => this.container.removeEventListener('mousewheel', handler)); + // Old Firefox + this.container.addEventListener('DOMMouseScroll', handler); + this.removers.push(() => this.container.removeEventListener('DOMMouseScroll', handler)); + + this.initZoomMatrix(); } componentWillUnmount () { this.removeEventListeners(); } + componentDidUpdate () { + this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' }); + + if (this.state.scale === MIN_SCALE) { + this.container.style.removeProperty('cursor'); + } + } + + UNSAFE_componentWillReceiveProps () { + // reset when slide to next image + if (this.props.zoomButtonHidden) { + this.setState({ + scale: MIN_SCALE, + lockTranslate: { x: 0, y: 0 }, + }, () => { + this.container.scrollLeft = 0; + this.container.scrollTop = 0; + }); + } + } + removeEventListeners () { this.removers.forEach(listeners => listeners()); this.removers = []; } + mouseWheelHandler = e => { + e.preventDefault(); + + const event = normalizeWheel(e); + + if (this.state.zoomMatrix.type === 'width') { + // full width, scroll vertical + this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y); + } else { + // full height, scroll horizontal + this.container.scrollLeft = Math.max(this.container.scrollLeft + event.pixelY, this.state.lockScroll.x); + } + + // lock horizontal scroll + this.container.scrollLeft = Math.max(this.container.scrollLeft + event.pixelX, this.state.lockScroll.x); + } + + mouseDownHandler = e => { + this.container.style.cursor = 'grabbing'; + this.container.style.userSelect = 'none'; + + this.setState({ dragPosition: { + left: this.container.scrollLeft, + top: this.container.scrollTop, + // Get the current mouse position + x: e.clientX, + y: e.clientY, + } }); + + this.image.addEventListener('mousemove', this.mouseMoveHandler); + this.image.addEventListener('mouseup', this.mouseUpHandler); + } + + mouseMoveHandler = e => { + const dx = e.clientX - this.state.dragPosition.x; + const dy = e.clientY - this.state.dragPosition.y; + + this.container.scrollLeft = Math.max(this.state.dragPosition.left - dx, this.state.lockScroll.x); + this.container.scrollTop = Math.max(this.state.dragPosition.top - dy, this.state.lockScroll.y); + + this.setState({ dragged: true }); + } + + mouseUpHandler = () => { + this.container.style.cursor = 'grab'; + this.container.style.removeProperty('user-select'); + + this.image.removeEventListener('mousemove', this.mouseMoveHandler); + this.image.removeEventListener('mouseup', this.mouseUpHandler); + } + handleTouchStart = e => { if (e.touches.length !== 2) return; @@ -80,7 +268,8 @@ export default class ZoomableImage extends React.PureComponent { const distance = getDistance(...e.touches); const midpoint = getMidpoint(...e.touches); - const scale = clamp(MIN_SCALE, MAX_SCALE, this.state.scale * distance / this.lastDistance); + const _MAX_SCALE = Math.max(MAX_SCALE, this.state.zoomMatrix.rate); + const scale = clamp(MIN_SCALE, _MAX_SCALE, this.state.scale * distance / this.lastDistance); this.zoom(scale, midpoint); @@ -89,7 +278,7 @@ export default class ZoomableImage extends React.PureComponent { } zoom(nextScale, midpoint) { - const { scale } = this.state; + const { scale, zoomMatrix } = this.state; const { scrollLeft, scrollTop } = this.container; // math memo: @@ -104,14 +293,105 @@ export default class ZoomableImage extends React.PureComponent { this.setState({ scale: nextScale }, () => { this.container.scrollLeft = nextScrollLeft; this.container.scrollTop = nextScrollTop; + // reset the translateX/Y constantly + if (nextScale < zoomMatrix.rate) { + this.setState({ + lockTranslate: { + x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)), + y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)), + }, + }); + } }); } handleClick = e => { // don't propagate event to MediaModal e.stopPropagation(); + const dragged = this.state.dragged; + this.setState({ dragged: false }); + if (dragged) return; const handler = this.props.onClick; if (handler) handler(); + this.setState({ navigationHidden: !this.state.navigationHidden }); + } + + handleMouseDown = e => { + e.preventDefault(); + } + + initZoomMatrix = () => { + const { width, height } = this.props; + const { clientWidth, clientHeight } = this.container; + const { offsetWidth, offsetHeight } = this.image; + const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT; + + const type = width / height < clientWidth / clientHeightFixed ? 'width' : 'height'; + const fullScreen = type === 'width' ? width > clientWidth : height > clientHeightFixed; + const rate = type === 'width' ? Math.min(clientWidth, width) / offsetWidth : Math.min(clientHeightFixed, height) / offsetHeight; + const scrollTop = type === 'width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2; + const scrollLeft = (clientWidth - offsetWidth) / 2; + const translateX = type === 'width' ? (width - offsetWidth) / (2 * rate) : 0; + const translateY = type === 'height' ? (height - offsetHeight) / (2 * rate) : 0; + + this.setState({ + zoomMatrix: { + type: type, + fullScreen: fullScreen, + rate: rate, + clientWidth: clientWidth, + clientHeight: clientHeight, + offsetWidth: offsetWidth, + offsetHeight: offsetHeight, + clientHeightFixed: clientHeightFixed, + scrollTop: scrollTop, + scrollLeft: scrollLeft, + translateX: translateX, + translateY: translateY, + }, + }); + } + + handleZoomClick = e => { + e.preventDefault(); + e.stopPropagation(); + + const { scale, zoomMatrix } = this.state; + + if ( scale >= zoomMatrix.rate ) { + this.setState({ + scale: MIN_SCALE, + lockScroll: { + x: 0, + y: 0, + }, + lockTranslate: { + x: 0, + y: 0, + }, + }, () => { + this.container.scrollLeft = 0; + this.container.scrollTop = 0; + }); + } else { + this.setState({ + scale: zoomMatrix.rate, + lockScroll: { + x: zoomMatrix.scrollLeft, + y: zoomMatrix.scrollTop, + }, + lockTranslate: { + x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX, + y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY, + }, + }, () => { + this.container.scrollLeft = zoomMatrix.scrollLeft; + this.container.scrollTop = zoomMatrix.scrollTop; + }); + } + + this.container.style.cursor = 'grab'; + this.container.style.removeProperty('user-select'); } setContainerRef = c => { @@ -123,29 +403,47 @@ export default class ZoomableImage extends React.PureComponent { } render () { - const { alt, src } = this.props; - const { scale } = this.state; - const overflow = scale === 1 ? 'hidden' : 'scroll'; + const { alt, src, width, height, intl } = this.props; + const { scale, lockTranslate } = this.state; + const overflow = scale === MIN_SCALE ? 'hidden' : 'scroll'; + const zoomButtonShouldHide = this.state.navigationHidden || this.props.zoomButtonHidden || this.state.zoomMatrix.rate <= MIN_SCALE ? 'media-modal__zoom-button--hidden' : ''; + const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand); return ( - <div - className='zoomable-image' - ref={this.setContainerRef} - style={{ overflow }} - > - <img - role='presentation' - ref={this.setImageRef} - alt={alt} - title={alt} - src={src} + <React.Fragment> + <IconButton + className={`media-modal__zoom-button ${zoomButtonShouldHide}`} + title={zoomButtonTitle} + icon={this.state.zoomState} + onClick={this.handleZoomClick} + size={40} style={{ - transform: `scale(${scale})`, - transformOrigin: '0 0', + fontSize: '30px', /* Fontawesome's fa-compress fa-expand is larger than fa-close */ }} - onClick={this.handleClick} /> - </div> + <div + className='zoomable-image' + ref={this.setContainerRef} + style={{ overflow }} + > + <img + role='presentation' + ref={this.setImageRef} + alt={alt} + title={alt} + src={src} + width={width} + height={height} + style={{ + transform: `scale(${scale}) translate(-${lockTranslate.x}px, -${lockTranslate.y}px)`, + transformOrigin: '0 0', + }} + draggable={false} + onClick={this.handleClick} + onMouseDown={this.handleMouseDown} + /> + </div> + </React.Fragment> ); } diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index 553cb33659d573271e5965b5a108768c32063da1..507ac1df1468a239733afd703fa42a0eae77f107 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -8,19 +8,20 @@ import PropTypes from 'prop-types'; import NotificationsContainer from './containers/notifications_container'; import LoadingBarContainer from './containers/loading_bar_container'; import ModalContainer from './containers/modal_container'; -import { isMobile } from '../../is_mobile'; +import { layoutFromWindow } from 'mastodon/is_mobile'; import { debounce } from 'lodash'; import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose'; import { expandHomeTimeline } from '../../actions/timelines'; import { expandNotifications } from '../../actions/notifications'; import { fetchFilters } from '../../actions/filters'; import { clearHeight } from '../../actions/height_cache'; -import { focusApp, unfocusApp } from 'mastodon/actions/app'; -import { synchronouslySubmitMarkers } from 'mastodon/actions/markers'; +import { focusApp, unfocusApp, changeLayout } from 'mastodon/actions/app'; +import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'mastodon/actions/markers'; import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers'; import UploadArea from './components/upload_area'; import ColumnsAreaContainer from './containers/columns_area_container'; import DocumentTitle from './components/document_title'; +import PictureInPicture from 'mastodon/features/picture_in_picture'; import { Compose, Status, @@ -51,7 +52,7 @@ import { Search, Directory, } from './util/async-components'; -import { me, forceSingleColumn } from '../../initial_state'; +import { me } from '../../initial_state'; import { previewState as previewMediaState } from './components/media_modal'; import { previewState as previewVideoState } from './components/video_modal'; @@ -64,6 +65,7 @@ const messages = defineMessages({ }); const mapStateToProps = state => ({ + layout: state.getIn(['meta', 'layout']), isComposing: state.getIn(['compose', 'is_composing']), hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0, hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0, @@ -109,17 +111,11 @@ class SwitchingColumnsArea extends React.PureComponent { static propTypes = { children: PropTypes.node, location: PropTypes.object, - onLayoutChange: PropTypes.func.isRequired, - }; - - state = { - mobile: isMobile(window.innerWidth), + mobile: PropTypes.bool, }; componentWillMount () { - window.addEventListener('resize', this.handleResize, { passive: true }); - - if (this.state.mobile || forceSingleColumn) { + if (this.props.mobile) { document.body.classList.toggle('layout-single-column', true); document.body.classList.toggle('layout-multiple-columns', false); } else { @@ -128,44 +124,21 @@ class SwitchingColumnsArea extends React.PureComponent { } } - componentDidUpdate (prevProps, prevState) { + componentDidUpdate (prevProps) { if (![this.props.location.pathname, '/'].includes(prevProps.location.pathname)) { this.node.handleChildrenContentChange(); } - if (prevState.mobile !== this.state.mobile && !forceSingleColumn) { - document.body.classList.toggle('layout-single-column', this.state.mobile); - document.body.classList.toggle('layout-multiple-columns', !this.state.mobile); + if (prevProps.mobile !== this.props.mobile) { + document.body.classList.toggle('layout-single-column', this.props.mobile); + document.body.classList.toggle('layout-multiple-columns', !this.props.mobile); } } - componentWillUnmount () { - window.removeEventListener('resize', this.handleResize); - } - shouldUpdateScroll (_, { location }) { return location.state !== previewMediaState && location.state !== previewVideoState; } - handleLayoutChange = debounce(() => { - // The cached heights are no longer accurate, invalidate - this.props.onLayoutChange(); - }, 500, { - trailing: true, - }) - - handleResize = () => { - const mobile = isMobile(window.innerWidth); - - if (mobile !== this.state.mobile) { - this.handleLayoutChange.cancel(); - this.props.onLayoutChange(); - this.setState({ mobile }); - } else { - this.handleLayoutChange(); - } - } - setRef = c => { if (c) { this.node = c.getWrappedInstance(); @@ -173,13 +146,11 @@ class SwitchingColumnsArea extends React.PureComponent { } render () { - const { children } = this.props; - const { mobile } = this.state; - const singleColumn = forceSingleColumn || mobile; - const redirect = singleColumn ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />; + const { children, mobile } = this.props; + const redirect = mobile ? <Redirect from='/' to='/timelines/home' exact /> : <Redirect from='/' to='/getting-started' exact />; return ( - <ColumnsAreaContainer ref={this.setRef} singleColumn={singleColumn}> + <ColumnsAreaContainer ref={this.setRef} singleColumn={mobile}> <WrappedSwitch> {redirect} <WrappedRoute path='/getting-started' component={GettingStarted} content={children} /> @@ -243,6 +214,7 @@ class UI extends React.PureComponent { location: PropTypes.object, intl: PropTypes.object.isRequired, dropdownMenuIsOpen: PropTypes.bool, + layout: PropTypes.string.isRequired, }; state = { @@ -265,17 +237,13 @@ class UI extends React.PureComponent { handleWindowFocus = () => { this.props.dispatch(focusApp()); + this.props.dispatch(submitMarkers({ immediate: true })); } handleWindowBlur = () => { this.props.dispatch(unfocusApp()); } - handleLayoutChange = () => { - // The cached heights are no longer accurate, invalidate - this.props.dispatch(clearHeight()); - } - handleDragEnter = (e) => { e.preventDefault(); @@ -349,10 +317,28 @@ class UI extends React.PureComponent { } } - componentWillMount () { + handleLayoutChange = debounce(() => { + this.props.dispatch(clearHeight()); // The cached heights are no longer accurate, invalidate + }, 500, { + trailing: true, + }); + + handleResize = () => { + const layout = layoutFromWindow(); + + if (layout !== this.props.layout) { + this.handleLayoutChange.cancel(); + this.props.dispatch(changeLayout(layout)); + } else { + this.handleLayoutChange(); + } + } + + componentDidMount () { window.addEventListener('focus', this.handleWindowFocus, false); window.addEventListener('blur', this.handleWindowBlur, false); window.addEventListener('beforeunload', this.handleBeforeUnload, false); + window.addEventListener('resize', this.handleResize, { passive: true }); document.addEventListener('dragenter', this.handleDragEnter, false); document.addEventListener('dragover', this.handleDragOver, false); @@ -364,19 +350,14 @@ class UI extends React.PureComponent { navigator.serviceWorker.addEventListener('message', this.handleServiceWorkerPostMessage); } - if (typeof window.Notification !== 'undefined' && Notification.permission === 'default') { - window.setTimeout(() => Notification.requestPermission(), 120 * 1000); - } - + this.props.dispatch(fetchMarkers()); this.props.dispatch(expandHomeTimeline()); this.props.dispatch(expandNotifications()); setTimeout(() => this.props.dispatch(fetchFilters()), 500); - } - componentDidMount () { this.hotkeys.__mousetrap__.stopCallback = (e, element) => { - return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName) && !e.altKey; + return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName); }; } @@ -384,6 +365,7 @@ class UI extends React.PureComponent { window.removeEventListener('focus', this.handleWindowFocus); window.removeEventListener('blur', this.handleWindowBlur); window.removeEventListener('beforeunload', this.handleBeforeUnload); + window.removeEventListener('resize', this.handleResize); document.removeEventListener('dragenter', this.handleDragEnter); document.removeEventListener('dragover', this.handleDragOver); @@ -514,7 +496,7 @@ class UI extends React.PureComponent { render () { const { draggingOver } = this.state; - const { children, isComposing, location, dropdownMenuIsOpen } = this.props; + const { children, isComposing, location, dropdownMenuIsOpen, layout } = this.props; const handlers = { help: this.handleHotkeyToggleHelp, @@ -541,10 +523,11 @@ class UI extends React.PureComponent { return ( <HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused> <div className={classNames('ui', { 'is-composing': isComposing })} ref={this.setRef} style={{ pointerEvents: dropdownMenuIsOpen ? 'none' : null }}> - <SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange}> + <SwitchingColumnsArea location={location} mobile={layout === 'mobile' || layout === 'single-column'}> {children} </SwitchingColumnsArea> + {layout !== 'mobile' && <PictureInPicture />} <NotificationsContainer /> <LoadingBarContainer className='loading-bar' /> <ModalContainer /> diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index 99dcdca2216321aacaaab112226f7b5c4e883c3b..d8a6c4f502b4ed2065945013e464291a59a607d6 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { fromJS, is } from 'immutable'; +import { is } from 'immutable'; import { throttle, debounce } from 'lodash'; import classNames from 'classnames'; import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen'; @@ -99,25 +99,33 @@ class Video extends React.PureComponent { static propTypes = { preview: PropTypes.string, + frameRate: PropTypes.string, src: PropTypes.string.isRequired, alt: PropTypes.string, width: PropTypes.number, height: PropTypes.number, sensitive: PropTypes.bool, - startTime: PropTypes.number, + currentTime: PropTypes.number, onOpenVideo: PropTypes.func, onCloseVideo: PropTypes.func, detailed: PropTypes.bool, inline: PropTypes.bool, editable: PropTypes.bool, + alwaysVisible: PropTypes.bool, cacheWidth: PropTypes.func, visible: PropTypes.bool, onToggleVisibility: PropTypes.func, + deployPictureInPicture: PropTypes.func, intl: PropTypes.object.isRequired, blurhash: PropTypes.string, - link: PropTypes.node, autoPlay: PropTypes.bool, - defaultVolume: PropTypes.number, + volume: PropTypes.number, + muted: PropTypes.bool, + componetIndex: PropTypes.number, + }; + + static defaultProps = { + frameRate: 25, }; state = { @@ -195,7 +203,7 @@ class Video extends React.PureComponent { handleTimeUpdate = () => { this.setState({ currentTime: this.video.currentTime, - duration: Math.floor(this.video.duration), + duration:this.video.duration, }); } @@ -263,6 +271,81 @@ class Video extends React.PureComponent { } }, 15); + seekBy (time) { + const currentTime = this.video.currentTime + time; + + if (!isNaN(currentTime)) { + this.setState({ currentTime }, () => { + this.video.currentTime = currentTime; + }); + } + } + + handleVideoKeyDown = e => { + // On the video element or the seek bar, we can safely use the space bar + // for playback control because there are no buttons to press + + if (e.key === ' ') { + e.preventDefault(); + e.stopPropagation(); + this.togglePlay(); + } + } + + handleKeyDown = e => { + const frameTime = 1 / this.getFrameRate(); + + switch(e.key) { + case 'k': + e.preventDefault(); + e.stopPropagation(); + this.togglePlay(); + break; + case 'm': + e.preventDefault(); + e.stopPropagation(); + this.toggleMute(); + break; + case 'f': + e.preventDefault(); + e.stopPropagation(); + this.toggleFullscreen(); + break; + case 'j': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(-10); + break; + case 'l': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(10); + break; + case ',': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(-frameTime); + break; + case '.': + e.preventDefault(); + e.stopPropagation(); + this.seekBy(frameTime); + break; + } + + // If we are in fullscreen mode, we don't want any hotkeys + // interacting with the UI that's not visible + + if (this.state.fullscreen) { + e.preventDefault(); + e.stopPropagation(); + + if (e.key === 'Escape') { + exitFullscreen(); + } + } + } + togglePlay = () => { if (this.state.paused) { this.setState({ paused: false }, () => this.video.play()); @@ -297,6 +380,15 @@ class Video extends React.PureComponent { document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true); document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true); document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true); + + if (!this.state.paused && this.video && this.props.deployPictureInPicture) { + this.props.deployPictureInPicture('video', { + src: this.props.src, + currentTime: this.video.currentTime, + muted: this.video.muted, + volume: this.video.volume, + }); + } } componentWillReceiveProps (nextProps) { @@ -328,7 +420,18 @@ class Video extends React.PureComponent { const inView = (top <= (window.innerHeight || document.documentElement.clientHeight)) && (top + height >= 0); if (!this.state.paused && !inView) { - this.setState({ paused: true }, () => this.video.pause()); + this.video.pause(); + + if (this.props.deployPictureInPicture) { + this.props.deployPictureInPicture('video', { + src: this.props.src, + currentTime: this.video.currentTime, + muted: this.video.muted, + volume: this.video.volume, + }); + } + + this.setState({ paused: true }); } }, 150, { trailing: true }) @@ -361,15 +464,21 @@ class Video extends React.PureComponent { } handleLoadedData = () => { - if (this.props.startTime) { - this.video.currentTime = this.props.startTime; + const { currentTime, volume, muted, autoPlay } = this.props; + + if (currentTime) { + this.video.currentTime = currentTime; + } + + if (volume !== undefined) { + this.video.volume = volume; } - if (this.props.defaultVolume !== undefined) { - this.video.volume = this.props.defaultVolume; + if (muted !== undefined) { + this.video.muted = muted; } - if (this.props.autoPlay) { + if (autoPlay) { this.video.play(); } } @@ -387,25 +496,14 @@ class Video extends React.PureComponent { } handleOpenVideo = () => { - const { src, preview, width, height, alt } = this.props; - - const media = fromJS({ - type: 'video', - url: src, - preview_url: preview, - description: alt, - width, - height, - }); + this.video.pause(); - const options = { + this.props.onOpenVideo({ startTime: this.video.currentTime, autoPlay: !this.state.paused, defaultVolume: this.state.volume, - }; - - this.video.pause(); - this.props.onOpenVideo(media, options); + componetIndex: this.props.componetIndex, + }); } handleCloseVideo = () => { @@ -413,10 +511,21 @@ class Video extends React.PureComponent { this.props.onCloseVideo(); } + getFrameRate () { + if (this.props.frameRate && isNaN(this.props.frameRate)) { + // The frame rate is returned as a fraction string so we + // need to convert it to a number + + return this.props.frameRate.split('/').reduce((p, c) => p / c); + } + + return this.props.frameRate; + } + render () { - const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, editable, blurhash } = this.props; + const { preview, src, inline, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, editable, blurhash } = this.props; const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; - const progress = (currentTime / duration) * 100; + const progress = Math.min((currentTime / duration) * 100, 100); const playerStyle = {}; let { width, height } = this.props; @@ -430,7 +539,7 @@ class Video extends React.PureComponent { let preload; - if (startTime || fullscreen || dragging) { + if (this.props.currentTime || fullscreen || dragging) { preload = 'auto'; } else if (detailed) { preload = 'metadata'; @@ -455,6 +564,7 @@ class Video extends React.PureComponent { onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClickRoot} + onKeyDown={this.handleKeyDown} tabIndex={0} > <Blurhash @@ -478,6 +588,7 @@ class Video extends React.PureComponent { height={height} volume={volume} onClick={this.togglePlay} + onKeyDown={this.handleVideoKeyDown} onPlay={this.handlePlay} onPause={this.handlePause} onLoadedData={this.handleLoadedData} @@ -500,13 +611,14 @@ class Video extends React.PureComponent { className={classNames('video-player__seek__handle', { active: dragging })} tabIndex='0' style={{ left: `${progress}%` }} + onKeyDown={this.handleVideoKeyDown} /> </div> <div className='video-player__buttons-bar'> <div className='video-player__buttons left'> - <button type='button' title={intl.formatMessage(paused ? messages.play : messages.pause)} aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay} autoFocus={detailed}><Icon id={paused ? 'play' : 'pause'} fixedWidth /></button> - <button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button> + <button type='button' title={intl.formatMessage(paused ? messages.play : messages.pause)} aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} className='player-button' onClick={this.togglePlay} autoFocus={detailed}><Icon id={paused ? 'play' : 'pause'} fixedWidth /></button> + <button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button> <div className={classNames('video-player__volume', { active: this.state.hovered })} onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}> <div className='video-player__volume__current' style={{ width: `${volume * 100}%` }} /> @@ -522,18 +634,16 @@ class Video extends React.PureComponent { <span className='video-player__time'> <span className='video-player__time-current'>{formatTime(Math.floor(currentTime))}</span> <span className='video-player__time-sep'>/</span> - <span className='video-player__time-total'>{formatTime(duration)}</span> + <span className='video-player__time-total'>{formatTime(Math.floor(duration))}</span> </span> )} - - {link && <span className='video-player__link'>{link}</span>} </div> <div className='video-player__buttons right'> - {(!onCloseVideo && !editable && !fullscreen) && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>} - {(!fullscreen && onOpenVideo) && <button type='button' title={intl.formatMessage(messages.expand)} aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>} - {onCloseVideo && <button type='button' title={intl.formatMessage(messages.close)} aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>} - <button type='button' title={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button> + {(!onCloseVideo && !editable && !fullscreen && !this.props.alwaysVisible) && <button type='button' title={intl.formatMessage(messages.hide)} aria-label={intl.formatMessage(messages.hide)} className='player-button' onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>} + {(!fullscreen && onOpenVideo) && <button type='button' title={intl.formatMessage(messages.expand)} aria-label={intl.formatMessage(messages.expand)} className='player-button' onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>} + {onCloseVideo && <button type='button' title={intl.formatMessage(messages.close)} aria-label={intl.formatMessage(messages.close)} className='player-button' onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>} + <button type='button' title={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} className='player-button' onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button> </div> </div> </div> diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 1134c55db42c4080f5e87dd406bf7d5bfaeb9b75..80d43907d30b82388295e180b074a83d22c93c01 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -25,5 +25,6 @@ export const usePendingItems = getMeta('use_pending_items'); export const showTrends = getMeta('trends'); export const title = getMeta('title'); export const cropImages = getMeta('crop_images'); +export const disableSwiping = getMeta('disable_swiping'); export default initialState; diff --git a/app/javascript/mastodon/is_mobile.js b/app/javascript/mastodon/is_mobile.js index f96df1ebbc6705956b19413fa11ca9437e02e9f4..2926eb4b1717be68b93b80bf45c519c7617c63b8 100644 --- a/app/javascript/mastodon/is_mobile.js +++ b/app/javascript/mastodon/is_mobile.js @@ -1,27 +1,32 @@ -import detectPassiveEvents from 'detect-passive-events'; +import { supportsPassiveEvents } from 'detect-passive-events'; +import { forceSingleColumn } from 'mastodon/initial_state'; const LAYOUT_BREAKPOINT = 630; -export function isMobile(width) { - return width <= LAYOUT_BREAKPOINT; +export const isMobile = width => width <= LAYOUT_BREAKPOINT; + +export const layoutFromWindow = () => { + if (isMobile(window.innerWidth)) { + return 'mobile'; + } else if (forceSingleColumn) { + return 'single-column'; + } else { + return 'multi-column'; + } }; const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; let userTouching = false; -let listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false; +let listenerOptions = supportsPassiveEvents ? { passive: true } : false; -function touchListener() { +const touchListener = () => { userTouching = true; window.removeEventListener('touchstart', touchListener, listenerOptions); -} +}; window.addEventListener('touchstart', touchListener, listenerOptions); -export function isUserTouching() { - return userTouching; -} +export const isUserTouching = () => userTouching; -export function isIOS() { - return iOS; -}; +export const isIOS = () => iOS; diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 548471edfd88b8108db61bd30498328b1d8b98ae..4d43a2720e110ab2f7d41ec0d478483a5ba87f29 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "ØªØµÙØ المزيد على المل٠التعريÙÙŠ الأصلي", "account.cancel_follow_request": "إلغاء طلب المتابَعة", "account.direct": "رسالة خاصة إلى @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "النطاق مخÙÙŠ", "account.edit_profile": "تعديل المل٠الشخصي", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "أوص٠به على ØµÙØØªÙƒ", "account.follow": "ØªØ§Ø¨ÙØ¹", "account.followers": "Ù…ÙØªØ§Ø¨Ùعون", @@ -147,6 +149,7 @@ "emoji_button.search_results": "نتائج Ø§Ù„Ø¨ØØ«", "emoji_button.symbols": "رموز", "emoji_button.travel": "الأماكن ÙˆØ§Ù„Ø³ÙØ±", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "ليس هناك تبويقات!", "empty_column.account_unavailable": "المل٠التعريÙÙŠ غير Ù…ØªÙˆÙØ±", "empty_column.blocks": "لم تقم Ø¨ØØ¸Ø± أي مستخدÙÙ… بعد.", @@ -166,7 +169,9 @@ "empty_column.notifications": "لم تتلق أي إشعار بعدÙ. ØªÙØ§Ø¹Ù„ مع المستخدمين الآخرين لإنشاء Ù…ØØ§Ø¯Ø«Ø©.", "empty_column.public": "لا يوجد أي شيء هنا! قم بنشر شيء ما للعامة، أو اتبع المستخدمين الآخرين المتواجدين على الخوادم الأخرى لملء خيط Ø§Ù„Ù…ØØ§Ø¯Ø«Ø§Øª", "error.unexpected_crash.explanation": "نظرا لوجود خطأ ÙÙŠ التعليمات البرمجية أو مشكلة تواÙÙ‚ مع المتصÙÙ‘ØØŒ تعذر عرض هذه Ø§Ù„ØµÙØØ© بشكل صØÙŠØ.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "ØØ§ÙˆÙ„ إعادة إنعاش Ø§Ù„ØµÙØØ©. إن لم ØªÙØÙ„Ù‘ المشكلة ØŒ يمكنك دائمًا استخدام ماستدون عبر متصÙÙ‘Ø Ø¢Ø®Ø± أو تطبيق أصلي.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "انسخ تتبع الارتباطات إلى Ø§Ù„ØØ§Ùظة", "errors.unexpected_crash.report_issue": "الإبلاغ عن خلل", "follow_request.authorize": "ترخيص", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "لإلغاء التركيز على ØÙ‚Ù„ النص أو Ù†Ø§ÙØ°Ø© Ø§Ù„Ø¨ØØ«", "keyboard_shortcuts.up": "للانتقال إلى أعلى القائمة", "lightbox.close": "إغلاق", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "التالي", "lightbox.previous": "العودة", - "lightbox.view_context": "اعرض السياق", "lists.account.add": "أض٠إلى القائمة", "lists.account.remove": "Ø§ØØ°Ù من القائمة", "lists.delete": "Ø§ØØ°Ù القائمة", @@ -260,6 +266,10 @@ "lists.edit.submit": "تعديل العنوان", "lists.new.create": "إنشاء قائمة", "lists.new.title_placeholder": "عنوان القائمة الجديدة", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Ø¥Ø¨ØØ« ÙÙŠ قائمة Ø§Ù„ØØ³Ø§Ø¨Ø§Øª التي ØªÙØªØ§Ø¨Ùعها", "lists.subheading": "قوائمك", "load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "عرض / Ø¥Ø®ÙØ§Ø¡", "missing_indicator.label": "غير موجود", "missing_indicator.sublabel": "تعذر العثور على هذا المورد", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "هل تود Ø¥Ø®ÙØ§Ø¡ الإخطارات القادمة من هذا المستخدم ØŸ", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "تطبيقات الأجهزة المØÙ…ولة", "navigation_bar.blocks": "Ø§Ù„ØØ³Ø§Ø¨Ø§Øª Ø§Ù„Ù…ØØ¬ÙˆØ¨Ø©", "navigation_bar.bookmarks": "الÙواصل المرجعية", @@ -298,6 +310,7 @@ "notification.own_poll": "انتهى استطلاعك للرأي", "notification.poll": "لقد إنتها تصويت شاركت Ùيه", "notification.reblog": "{name} قام بترقية تبويقك", + "notification.status": "{name} just posted", "notifications.clear": "Ø§Ù…Ø³Ø Ø§Ù„Ø¥Ø®Ø·Ø§Ø±Ø§Øª", "notifications.clear_confirmation": "أمتأكد من أنك تود Ù…Ø³Ø Ø¬Ù„ الإخطارات الخاصة بك Ùˆ المتلقاة إلى ØØ¯ الآن ØŸ", "notifications.column_settings.alert": "إشعارات Ø³Ø·Ø Ø§Ù„Ù…ÙƒØªØ¨", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "الترقيّات:", "notifications.column_settings.show": "Ø§Ø¹Ø±ÙØ¶Ù‡Ø§ ÙÙŠ عمود", "notifications.column_settings.sound": "أصدر صوتا", + "notifications.column_settings.status": "تبويقات جديدة:", "notifications.filter.all": "الكل", "notifications.filter.boosts": "الترقيات", "notifications.filter.favourites": "Ø§Ù„Ù…ÙØ¶Ù„Ø©", "notifications.filter.follows": "ÙŠØªØ§Ø¨ÙØ¹", "notifications.filter.mentions": "الإشارات", "notifications.filter.polls": "نتائج استطلاع الرأي", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} إشعارات", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "انتهى", "poll.refresh": "ØªØØ¯ÙŠØ«", "poll.total_people": "{count, plural, one {# شخص} two {# شخصين} few {# أشخاص} many {# أشخاص} other {# أشخاص}}", @@ -430,7 +454,7 @@ "units.short.million": "{count} مليون", "units.short.thousand": "{count} ألÙ", "upload_area.title": "Ø§Ø³ØØ¨ ثم Ø£Ùلت Ù„Ù„Ø±ÙØ¹", - "upload_button.label": "Ø¥Ø¶Ø§ÙØ© وسائط ({formats})", + "upload_button.label": "Ø¥Ø¶Ø§ÙØ© وسائط", "upload_error.limit": "لقد تم بلوغ Ø§Ù„ØØ¯ الأقصى Ø§Ù„Ù…Ø³Ù…ÙˆØ Ø¨Ù‡ لإرسال Ø§Ù„Ù…Ù„ÙØ§Øª.", "upload_error.poll": "لا يمكن إدراج Ù…Ù„ÙØ§Øª ÙÙŠ استطلاعات الرأي.", "upload_form.audio_description": "وص٠للأشخاص ذي Ù‚ÙØµØ± السمع", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "اكتش٠النص Ù…ÙÙ† الصورة", "upload_modal.edit_media": "تعديل الوسائط", "upload_modal.hint": "اضغط أو Ø§Ø³ØØ¨ الدائرة على خانة المعاينة لاختيار نقطة التركيز التي Ø³ØªÙØ¹Ø±ÙŽØ¶ دائمًا على كل المصغرات.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "معاينة ({ratio})", "upload_progress.label": "ÙŠØ±ÙØ¹...", "video.close": "إغلاق الÙيديو", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 6c6232262effd0d5bef91e9e0a317e7be1451ff0..4f5fec8b1fe2331f3f0ee92988cae126ff14ec7e 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Encaboxar la solicitú de siguimientu", "account.direct": "Unviar un mensaxe direutu a @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Dominiu anubrÃu", "account.edit_profile": "Editar el perfil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Destacar nel perfil", "account.follow": "Siguir", "account.followers": "Siguidores", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Barritar", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "El testu nun va anubrise darrera d'una alvertencia", "compose_form.spoiler.unmarked": "El testu nun va anubrise", "compose_form.spoiler_placeholder": "Escribi equà l'alvertencia", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viaxes y llugares", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "¡Equà nun hai barritos!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "Entá nun bloquiesti a nunengún usuariu.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Entá nun tienes nunengún avisu. Interactúa con otros p'aniciar la conversación.", "empty_column.public": "¡Equà nun hai nada! Escribi daqué público o sigui a usuarios d'otros sirvidores pa rellenar esto", "error.unexpected_crash.explanation": "Pola mor d'un fallu nel códigu o un problema de compatibilidá del restolador, esta páxina nun pudo amosase correutamente.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Autorizar", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "pa desenfocar l'área de composición/gueta", "keyboard_shortcuts.up": "pa xubir na llista", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Siguiente", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Amestar a la llista", "lists.account.remove": "Desaniciar de la llista", "lists.delete": "Desaniciar la llista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "TÃtulu nuevu de la llista", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Guetar ente la xente que sigues", "lists.subheading": "Les tos llistes", "load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Alternar la visibilidá", "missing_indicator.label": "Nun s'alcontró", "missing_indicator.sublabel": "Esti recursu nun pudo alcontrase", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "¿Anubrir los avisos d'esti usuariu?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Aplicaciones pa móviles", "navigation_bar.blocks": "Usuarios bloquiaos", "navigation_bar.bookmarks": "Marcadores", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "Finó una encuesta na que votesti", "notification.reblog": "{name} compartió'l to estáu", + "notification.status": "{name} just posted", "notifications.clear": "Llimpiar avisos", "notifications.clear_confirmation": "¿De xuru que quies llimpiar dafechu tolos avisos?", "notifications.column_settings.alert": "Avisos d'escritoriu", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Barritos compartÃos:", "notifications.column_settings.show": "Amosar en columna", "notifications.column_settings.sound": "Reproducir un sonÃu", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Too", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Menciones", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} avisos", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Acabó", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# persona} other {# persones}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Deteutar el testu de la semeya", "upload_modal.edit_media": "Edición", "upload_modal.hint": "Calca o arrastra'l cÃrculu de la previsualización pa escoyer el puntu d'enfoque que va amosase siempres en toles miniatures.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Previsualización ({ratio})", "upload_progress.label": "Xubiendo…", "video.close": "Zarrar el videu", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 16520dbad5281e86a265472334eb917e481910f2..4778d66182807a5f900bdd060203ab49a2e8fd3d 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Откажи иÑкането за Ñледване", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Скрит домейн", "account.edit_profile": "Редактирай профила Ñи", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "ХарактериÑтика на профила", "account.follow": "ПоÑледвай", "account.followers": "ПоÑледователи", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Раздумай", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Content warning", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Затвори", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} Ñподели твоÑта публикациÑ", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "ДеÑктоп извеÑтиÑ", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "СподелÑниÑ:", "notifications.column_settings.show": "Покажи в колона", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "СподелÑне", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} Ñподели", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/bn.json b/app/javascript/mastodon/locales/bn.json index 7de1a10221b2470daabdfb69b116a5fac84d298b..9b73c35971a933177dc0552597c1b25b537b869a 100644 --- a/app/javascript/mastodon/locales/bn.json +++ b/app/javascript/mastodon/locales/bn.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "নোট", "account.add_or_remove_from_list": "তালিকাতে যà§à¦•à§à¦¤ বা অপসারণ করà§à¦¨", "account.badges.bot": "বট", - "account.badges.group": "Group", + "account.badges.group": "গà§à¦°à§à¦ª", "account.block": "@{name} কে বà§à¦²à¦• করà§à¦¨", "account.block_domain": "{domain} থেকে সব আড়াল করà§à¦¨", "account.blocked": "অবরà§à¦¦à§à¦§", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "মূল পà§à¦°à§‹à¦«à¦¾à¦‡à¦²à¦Ÿà¦¿à¦¤à§‡ আরও বà§à¦°à¦¾à¦‰à¦œ করà§à¦¨", "account.cancel_follow_request": "অনà§à¦¸à¦°à¦£ অনà§à¦°à§‹à¦§ বাতিল করà§à¦¨", "account.direct": "@{name} কে সরাসরি বারà§à¦¤à¦¾", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "ডোমেন গোপন করà§à¦¨", "account.edit_profile": "পà§à¦°à§‹à¦«à¦¾à¦‡à¦² পরিবরà§à¦¤à¦¨ করà§à¦¨", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "নিজের পাতায় দেখান", "account.follow": "অনà§à¦¸à¦°à¦£ করà§à¦¨", "account.followers": "অনà§à¦¸à¦°à¦£à¦•ারী", "account.followers.empty": "à¦à¦‡ সদসà§à¦¯à¦•ে à¦à¦–নো কেউ অনà§à¦¸à¦°à¦£ করে না।.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural,one {{counter} জন অনà§à¦¸à¦°à¦£à¦•ারী } other {{counter} জন অনà§à¦¸à¦°à¦£à¦•ারী}}", + "account.following_counter": "{count, plural,one {{counter} জনকে অনà§à¦¸à¦°à¦£} other {{counter} জনকে অনà§à¦¸à¦°à¦£}}", "account.follows.empty": "à¦à¦‡ সদসà§à¦¯ কাওকে à¦à¦–নো অনà§à¦¸à¦°à¦£ করেন না.", "account.follows_you": "আপনাকে অনà§à¦¸à¦°à¦£ করে", "account.hide_reblogs": "@{name}'র সমরà§à¦¥à¦¨à¦—à§à¦²à¦¿ লà§à¦•িয়ে ফেলà§à¦¨", @@ -36,19 +38,19 @@ "account.requested": "অনà§à¦®à¦¤à¦¿à¦° অপেকà§à¦·à¦¾à¥¤ অনà§à¦¸à¦°à¦£ করার অনà§à¦°à§‹à¦§ বাতিল করতে à¦à¦–ানে কà§à¦²à¦¿à¦• করà§à¦¨", "account.share": "@{name} র পà§à¦°à§‹à¦«à¦¾à¦‡à¦² অনà§à¦¯à¦¦à§‡à¦° দেখান", "account.show_reblogs": "@{name} র সমরà§à¦¥à¦¨à¦—à§à¦²à§‹ দেখান", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural,one {{counter} টà§à¦Ÿ} other {{counter} টà§à¦Ÿ}}", "account.unblock": "@{name} র কারà§à¦¯à¦•লাপ দেখà§à¦¨", "account.unblock_domain": "{domain} কে আবার দেখà§à¦¨", "account.unendorse": "আপনার নিজের পাতায় à¦à¦Ÿà¦¾ দেখবেন না", "account.unfollow": "অনà§à¦¸à¦°à¦£ না করতে", "account.unmute": "@{name} র কারà§à¦¯à¦•লাপ আবার দেখà§à¦¨", "account.unmute_notifications": "@{name} র পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨ দেখà§à¦¨", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "নোট যোগ করতে কà§à¦²à¦¿à¦• করà§à¦¨", "alert.rate_limited.message": "{retry_time, time, medium} -à¦à¦° পরে আবার পà§à¦°à¦šà§‡à¦·à§à¦Ÿà¦¾ করà§à¦¨à¥¤", "alert.rate_limited.title": "হার সীমিত", "alert.unexpected.message": "সমসà§à¦¯à¦¾ অপà§à¦°à¦¤à§à¦¯à¦¾à¦¶à¦¿à¦¤.", "alert.unexpected.title": "ওহো!", - "announcement.announcement": "Announcement", + "announcement.announcement": "ঘোষণা", "autosuggest_hashtag.per_week": "পà§à¦°à¦¤à¦¿ সপà§à¦¤à¦¾à¦¹à§‡ {count}", "boost_modal.combo": "পরেরবার আপনি {combo} টিপলে à¦à¦Ÿà¦¿ আর আসবে না", "bundle_column_error.body": "à¦à¦‡ অংশটি দেখতে যেয়ে কোনো সমসà§à¦¯à¦¾ হয়েছে।.", @@ -58,7 +60,7 @@ "bundle_modal_error.message": "à¦à¦‡ অংশটি দেখাতে যেয়ে কোনো সমসà§à¦¯à¦¾ হয়েছে।.", "bundle_modal_error.retry": "আবার চেষà§à¦Ÿà¦¾ করà§à¦¨", "column.blocks": "যাদের বà§à¦²à¦• করা হয়েছে", - "column.bookmarks": "Bookmarks", + "column.bookmarks": "বà§à¦•মারà§à¦•", "column.community": "সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼ সময়সারি", "column.direct": "সরাসরি লেখা", "column.directory": "পà§à¦°à§‹à¦«à¦¾à¦‡à¦² বà§à¦°à¦¾à¦‰à¦œ করà§à¦¨", @@ -79,9 +81,9 @@ "column_header.show_settings": "সেটিং দেখান", "column_header.unpin": "পিন খà§à¦²à§à¦¨", "column_subheading.settings": "সেটিং", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° সà§à¦¥à¦¾à¦¨à§€à§Ÿ", "community.column_settings.media_only": "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° ছবি বা à¦à¦¿à¦¡à¦¿à¦“", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° দূরবরà§à¦¤à§€", "compose_form.direct_message_warning": "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° যাদেরকে উলà§à¦²à§‡à¦– করা হয়েছে তাদেরকেই à¦à¦‡ টà§à¦Ÿà¦Ÿà¦¿ পাঠানো হবে ।", "compose_form.direct_message_warning_learn_more": "আরো জানà§à¦¨", "compose_form.hashtag_warning": "কোনো হà§à¦¯à¦¾à¦¶à¦Ÿà§à¦¯à¦¾à¦—ের à¦à§‡à¦¤à¦°à§‡ à¦à¦‡ টà§à¦Ÿà¦Ÿà¦¿ থাকবেনা কারণ à¦à¦Ÿà¦¿ তালিকাবহিরà§à¦à§‚ত। শà§à¦§à§à¦®à¦¾à¦¤à§à¦° পà§à¦°à¦•াশà§à¦¯ ঠোটগà§à¦²à§‹ হà§à¦¯à¦¾à¦¶à¦Ÿà§à¦¯à¦¾à¦—ের à¦à§‡à¦¤à¦°à§‡ খà§à¦à¦œà§‡ পাওয়া যাবে।", @@ -92,8 +94,8 @@ "compose_form.poll.duration": "à¦à§‹à¦Ÿà¦—à§à¦°à¦¹à¦¨à§‡à¦° সময়", "compose_form.poll.option_placeholder": "বিকলà§à¦ª {number}", "compose_form.poll.remove_option": "à¦à¦‡ বিকলà§à¦ªà¦Ÿà¦¿ মà§à¦›à§‡ ফেলà§à¦¨", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.poll.switch_to_multiple": "à¦à¦•াধিক পছনà§à¦¦ অনà§à¦®à¦¤à¦¿ দেওয়ার জনà§à¦¯ পোল পরিবরà§à¦¤à¦¨ করà§à¦¨", + "compose_form.poll.switch_to_single": "à¦à¦•টি à¦à¦•ক পছনà§à¦¦à§‡à¦° অনà§à¦®à¦¤à¦¿ দেওয়ার জনà§à¦¯ পোল পরিবরà§à¦¤à¦¨ করà§à¦¨", "compose_form.publish": "টà§à¦Ÿ", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.hide": "à¦à¦‡ ছবি বা à¦à¦¿à¦¡à¦¿à¦“টি সংবেদনশীল হিসেবে চিহà§à¦¨à¦¿à¦¤ করতে", @@ -147,10 +149,11 @@ "emoji_button.search_results": "খোà¦à¦œà¦¾à¦° ফলাফল", "emoji_button.symbols": "পà§à¦°à¦¤à§€à¦•", "emoji_button.travel": "à¦à§à¦°à¦®à¦£ à¦à¦¬à¦‚ সà§à¦¥à¦¾à¦¨", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "à¦à¦–ানে কোনো টà§à¦Ÿ নেই!", "empty_column.account_unavailable": "নিজসà§à¦¬ পাতা নেই", "empty_column.blocks": "আপনি কোনো বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের বà§à¦²à¦• করেন নি।", - "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", + "empty_column.bookmarked_statuses": "আপনার কাছে à¦à¦–নও কোনও বà§à¦•মারà§à¦•ড টà§à¦Ÿ নেই। আপনি যখন à¦à¦•টি বà§à¦•মারà§à¦• করেন, à¦à¦Ÿà¦¿ à¦à¦–ানে পà§à¦°à¦¦à¦°à§à¦¶à¦¿à¦¤ হবে।", "empty_column.community": "সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼ সময়রেখাতে কিছৠনেই। পà§à¦°à¦•াশà§à¦¯à¦à¦¾à¦¬à§‡ কিছৠলিখে লেখালেখির উদà§à¦¬à§‹à¦§à¦¨ করে ফেলà§à¦¨!", "empty_column.direct": "আপনার কাছে সরাসরি পাঠানো কোনো লেখা নেই। যদি কেও পাঠায়, সেটা à¦à¦–ানে দেখা যাবে।", "empty_column.domain_blocks": "à¦à¦–নও কোনও লà§à¦•ানো ডোমেন নেই।", @@ -166,13 +169,15 @@ "empty_column.notifications": "আপনার à¦à¦–নো কোনো পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨ নেই। কথোপকথন শà§à¦°à§ করতে, অনà§à¦¯à¦¦à§‡à¦° সাথে মেলামেশা করতে পারেন।", "empty_column.public": "à¦à¦–ানে à¦à¦–নো কিছৠনেই! পà§à¦°à¦•াশà§à¦¯ à¦à¦¾à¦¬à§‡ কিছৠলিখà§à¦¨ বা অনà§à¦¯ সারà§à¦à¦¾à¦° থেকে কাওকে অনà§à¦¸à¦°à¦£ করে à¦à¦‡ জায়গা à¦à¦°à§‡ ফেলà§à¦¨", "error.unexpected_crash.explanation": "আমাদের কোড বা বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° সামঞà§à¦œà¦¸à§à¦¯ ইসà§à¦¯à§à¦¤à§‡ à¦à¦•টি বাগের কারণে à¦à¦‡ পৃষà§à¦ াটি সঠিকà¦à¦¾à¦¬à§‡ পà§à¦°à¦¦à¦°à§à¦¶à¦¿à¦¤ করা যায় নি।", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "পাতাটি রিফà§à¦°à§‡à¦¶ করে চেষà§à¦Ÿà¦¾ করà§à¦¨à¥¤ তবà§à¦“ যদি না হয়, তবে আপনি অনà§à¦¯ à¦à¦•টি বà§à¦°à¦¾à¦‰à¦œà¦¾à¦° অথবা আপনার ডিà¦à¦¾à¦‡à¦¸à§‡à¦° জনà§à¦¯à§‡ à¦à¦ªà§‡à¦° মাধà§à¦¯à¦®à§‡ মাসà§à¦Ÿà¦¡à¦¨ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦° করতে পারবেন।.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "সà§à¦Ÿà§‡à¦•টà§à¦°à§‡à¦¸ কà§à¦²à¦¿à¦ªà¦¬à§‹à¦°à§à¦¡à§‡ কপি করà§à¦¨", "errors.unexpected_crash.report_issue": "সমসà§à¦¯à¦¾à¦° পà§à¦°à¦¤à¦¿à¦¬à§‡à¦¦à¦¨ করà§à¦¨", "follow_request.authorize": "অনà§à¦®à¦¤à¦¿ দিন", "follow_request.reject": "পà§à¦°à¦¤à§à¦¯à¦¾à¦–à§à¦¯à¦¾à¦¨ করà§à¦¨", - "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "আপনার অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦Ÿà¦¿ লক না থাকলেও, {domain} করà§à¦®à§€à¦°à¦¾ à¦à§‡à¦¬à§‡à¦›à¦¿à¦²à§‡à¦¨ যে আপনি à¦à¦‡ অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦—à§à¦²à¦¿ থেকে মà§à¦¯à¦¾à¦¨à§à¦¯à¦¼à¦¾à¦²à¦¿ অনà§à¦¸à¦°à¦£à§‡à¦° অনà§à¦°à§‹à¦§à¦—à§à¦²à¦¿ পরà§à¦¯à¦¾à¦²à§‹à¦šà¦¨à¦¾ করতে চাইতে পারেন।", + "generic.saved": "সংরকà§à¦·à¦£ হয়েছে", "getting_started.developers": "তৈরিকারকদের জনà§à¦¯", "getting_started.directory": "নিজসà§à¦¬-পাতাগà§à¦²à¦¿à¦° তালিকা", "getting_started.documentation": "নথিপতà§à¦°", @@ -193,8 +198,8 @@ "home.column_settings.basic": "সাধারণ", "home.column_settings.show_reblogs": "সমরà§à¦¥à¦¨à¦—à§à¦²à§‹ দেখান", "home.column_settings.show_replies": "মতামত দেখান", - "home.hide_announcements": "Hide announcements", - "home.show_announcements": "Show announcements", + "home.hide_announcements": "ঘোষণা লà§à¦•ান", + "home.show_announcements": "ঘোষণা দেখান", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# ঘটা} other {# ঘটা}}", "intervals.full.minutes": "{number, plural, one {# মিনিট} other {# মিনিট}}", @@ -236,13 +241,13 @@ "keyboard_shortcuts.muted": "বনà§à¦§ করা বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের তালিকা খà§à¦²à¦¤à§‡", "keyboard_shortcuts.my_profile": "আপনার নিজের পাতা দেখতে", "keyboard_shortcuts.notifications": "পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à§‡à¦° কলাম খà§à¦²à¦¤à§‡", - "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.open_media": "মিডিয়া খলার জনà§à¦¯", "keyboard_shortcuts.pinned": "পিন দেওয়া টà§à¦Ÿà§‡à¦° তালিকা খà§à¦²à¦¤à§‡", "keyboard_shortcuts.profile": "লেখকের পাতা দেখতে", "keyboard_shortcuts.reply": "মতামত দিতে", "keyboard_shortcuts.requests": "অনà§à¦¸à¦°à¦£ অনà§à¦°à§‹à¦§à§‡à¦° তালিকা দেখতে", "keyboard_shortcuts.search": "খোà¦à¦œà¦¾à¦° অংশে ফোকাস করতে", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "CW কà§à¦·à§‡à¦¤à§à¦° দেখাবার/লà§à¦•বার জনà§à¦¯", "keyboard_shortcuts.start": "\"পà§à¦°à¦¥à¦® শà§à¦°à§à¦°\" কলাম বের করতে", "keyboard_shortcuts.toggle_hidden": "CW লেখা দেখতে বা লà§à¦•াতে", "keyboard_shortcuts.toggle_sensitivity": "à¦à¦¿à¦¡à¦¿à¦“/ছবি দেখতে বা বনà§à¦§ করতে", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "লেখা বা খোà¦à¦œà¦¾à¦° জায়গায় ফোকাস না করতে", "keyboard_shortcuts.up": "তালিকার উপরের দিকে যেতে", "lightbox.close": "বনà§à¦§", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "পরবরà§à¦¤à§€", "lightbox.previous": "পূরà§à¦¬à¦¬à¦°à§à¦¤à§€", - "lightbox.view_context": "পà§à¦°à¦¸à¦™à§à¦—টি দেখতে", "lists.account.add": "তালিকাতে যà§à¦•à§à¦¤ করতে", "lists.account.remove": "তালিকা থেকে বাদ দিতে", "lists.delete": "তালিকা মà§à¦›à§‡ ফেলতে", @@ -260,6 +266,10 @@ "lists.edit.submit": "শিরোনাম সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করতে", "lists.new.create": "তালিকাতে যà§à¦•à§à¦¤ করতে", "lists.new.title_placeholder": "তালিকার নতà§à¦¨ শিরোনাম দিতে", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "যাদের অনà§à¦¸à¦°à¦£ করেন তাদের à¦à§‡à¦¤à¦°à§‡ খà§à¦à¦œà§à¦¨", "lists.subheading": "আপনার তালিকা", "load_pending": "{count, plural, one {# নতà§à¦¨ জিনিস} other {# নতà§à¦¨ জিনিস}}", @@ -267,10 +277,12 @@ "media_gallery.toggle_visible": "দৃশà§à¦¯à¦¤à¦¾à¦° অবসà§à¦¥à¦¾ বদলান", "missing_indicator.label": "খà§à¦à¦œà§‡ পাওয়া যায়নি", "missing_indicator.sublabel": "জিনিসটা খà§à¦à¦œà§‡ পাওয়া যায়নি", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "à¦à¦‡ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨ বনà§à¦§ করবেন ?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "মোবাইলের আপà§à¦ª", "navigation_bar.blocks": "বনà§à¦§ করা বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী", - "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.bookmarks": "বà§à¦•মারà§à¦•", "navigation_bar.community_timeline": "সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼ সময়রেখা", "navigation_bar.compose": "নতà§à¦¨ টà§à¦Ÿ লিখà§à¦¨", "navigation_bar.direct": "সরাসরি লেখাগà§à¦²à¦¿", @@ -293,11 +305,12 @@ "navigation_bar.security": "নিরাপতà§à¦¤à¦¾", "notification.favourite": "{name} আপনার কারà§à¦¯à¦•à§à¦°à¦® পছনà§à¦¦ করেছেন", "notification.follow": "{name} আপনাকে অনà§à¦¸à¦°à¦£ করেছেন", - "notification.follow_request": "{name} has requested to follow you", + "notification.follow_request": "{name} আপনাকে অনà§à¦¸à¦°à¦£ করার জনà§à¦¯ অনà§à¦°à¦§ করেছে", "notification.mention": "{name} আপনাকে উলà§à¦²à§‡à¦– করেছেন", "notification.own_poll": "আপনার পোল শেষ হয়েছে", "notification.poll": "আপনি à¦à§‹à¦Ÿ দিয়েছিলেন à¦à¦®à¦¨ à¦à¦• নিরà§à¦¬à¦¾à¦šà¦¨à§‡à¦° à¦à§‹à¦Ÿà§‡à¦° সময় শেষ হয়েছে", "notification.reblog": "{name} আপনার কারà§à¦¯à¦•à§à¦°à¦®à§‡ সমরà§à¦¥à¦¨ দেখিয়েছেন", + "notification.status": "{name} just posted", "notifications.clear": "পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à¦—à§à¦²à§‹ মà§à¦›à§‡ ফেলতে", "notifications.clear_confirmation": "আপনি কি নিরà§à¦šà¦¿à¦¤ পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à¦—à§à¦²à§‹ মà§à¦›à§‡ ফেলতে চান ?", "notifications.column_settings.alert": "কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à¦°à§‡ পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à¦—à§à¦²à¦¿", @@ -306,20 +319,31 @@ "notifications.column_settings.filter_bar.category": "সংকà§à¦·à¦¿à¦ªà§à¦¤ ছাà¦à¦•নি অংশ", "notifications.column_settings.filter_bar.show": "দেখানো", "notifications.column_settings.follow": "নতà§à¦¨ অনà§à¦¸à¦°à¦£à¦•ারীরা:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.follow_request": "অনà§à¦¸à¦°à¦£à§‡à¦° অনà§à¦°à§‹à¦§à¦—à§à¦²à¦¿:", "notifications.column_settings.mention": "পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à¦—à§à¦²à§‹:", "notifications.column_settings.poll": "নিরà§à¦¬à¦¾à¦šà¦¨à§‡à¦° ফলাফল:", "notifications.column_settings.push": "পà§à¦¶ পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨à¦—à§à¦²à¦¿", "notifications.column_settings.reblog": "সমরà§à¦¥à¦¨à¦—à§à¦²à§‹:", "notifications.column_settings.show": "কলামে দেখানো", "notifications.column_settings.sound": "শবà§à¦¦ বাজানো", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "সব", "notifications.filter.boosts": "সমরà§à¦¥à¦¨à¦—à§à¦²à§‹", "notifications.filter.favourites": "পছনà§à¦¦à§‡à¦° গà§à¦²à§‹", "notifications.filter.follows": "অনà§à¦¸à¦°à¦£à§‡à¦°", "notifications.filter.mentions": "উলà§à¦²à§‡à¦–িত", "notifications.filter.polls": "নিরà§à¦¬à¦¾à¦šà¦¨à§‡à¦° ফলাফল", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} পà§à¦°à¦œà§à¦žà¦¾à¦ªà¦¨", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "বনà§à¦§", "poll.refresh": "বদলেছে কিনা দেখতে", "poll.total_people": "{count, plural, one {# বà§à¦¯à¦•à§à¦¤à¦¿} other {# বà§à¦¯à¦•à§à¦¤à¦¿}}", @@ -345,7 +369,7 @@ "relative_time.just_now": "à¦à¦–ন", "relative_time.minutes": "{number}মিঃ", "relative_time.seconds": "{number} সেকেনà§à¦¡", - "relative_time.today": "today", + "relative_time.today": "আজ", "reply_indicator.cancel": "বাতিল করতে", "report.forward": "à¦à¦Ÿà¦¾ আরো পাঠান {target} তে", "report.forward_hint": "à¦à¦‡ নিবনà§à¦§à¦¨à¦Ÿà¦¿ অনà§à¦¯ à¦à¦•টি সারà§à¦à¦¾à¦°à§‡à¥¤ অপà§à¦°à¦•াশিতনামাà¦à¦¾à¦¬à§‡ রিপোরà§à¦Ÿà§‡à¦° কপি সেখানেও কি পাঠাতে চান ?", @@ -368,7 +392,7 @@ "status.admin_account": "@{name} র জনà§à¦¯ পরিচালনার ইনà§à¦Ÿà¦¾à¦°à¦«à§‡à¦¸à§‡ ঢà§à¦•à§à¦¨", "status.admin_status": "যায় লেখাটি পরিচালনার ইনà§à¦Ÿà¦¾à¦°à¦«à§‡à¦¸à§‡ খà§à¦²à§à¦¨", "status.block": "@{name} কে বà§à¦²à¦• করà§à¦¨", - "status.bookmark": "Bookmark", + "status.bookmark": "বà§à¦•মারà§à¦•", "status.cancel_reblog_private": "সমরà§à¦¥à¦¨ বাতিল করতে", "status.cannot_reblog": "à¦à¦Ÿà¦¿à¦¤à§‡ সমরà§à¦¥à¦¨ দেওয়া যাবেনা", "status.copy": "লেখাটির লিংক কপি করতে", @@ -393,7 +417,7 @@ "status.reblogged_by": "{name} সমরà§à¦¥à¦¨ দিয়েছে", "status.reblogs.empty": "à¦à¦–নো কেও à¦à¦Ÿà¦¾à¦¤à§‡ সমরà§à¦¥à¦¨ দেয়নি। যখন কেও দেয়, সেটা তখন à¦à¦–ানে দেখা যাবে।", "status.redraft": "মà§à¦›à§‡ আবার নতà§à¦¨ করে লিখতে", - "status.remove_bookmark": "Remove bookmark", + "status.remove_bookmark": "বà§à¦•মারà§à¦• সরান", "status.reply": "মতামত জানাতে", "status.replyAll": "লেখাযà§à¦•à§à¦¤ সবার কাছে মতামত জানাতে", "status.report": "@{name} কে রিপোরà§à¦Ÿ করতে", @@ -419,33 +443,34 @@ "time_remaining.minutes": "{number, plural, one {# মিনিট} other {# মিনিট}} বাকি আছে", "time_remaining.moments": "সময় বাকি আছে", "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} বাকি আছে", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "অনà§à¦¯ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿ থেকে {resource} দেখাচà§à¦›à§‡ না। ", + "timeline_hint.resources.followers": "অনà§à¦¸à¦°à¦•ারীরা", + "timeline_hint.resources.follows": "অনà§à¦¸à¦°à¦£ করে", + "timeline_hint.resources.statuses": "পà§à¦°à¦¨à§‹ টà§à¦Ÿà¦—à§à¦²à¦¿", + "trends.counter_by_accounts": "{count, plural,one {{counter} জন বà§à¦¯à¦•à§à¦¤à¦¿} other {{counter} জন লোক}} কথা বলছে", "trends.trending_now": "বরà§à¦¤à¦®à¦¾à¦¨à§‡ জনপà§à¦°à¦¿à§Ÿ", "ui.beforeunload": "যে পরà§à¦¯à¦¨à§à¦¤ à¦à¦Ÿà¦¾ লেখা হয়েছে, মাসà§à¦Ÿà¦¾à¦¡à¦¨ থেকে চলে গেলে à¦à¦Ÿà¦¾ মà§à¦›à§‡ যাবে।", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count}বিলিয়ন", + "units.short.million": "{count}মিলিওন", + "units.short.thousand": "{count}হাজার", "upload_area.title": "টেনে à¦à¦–ানে ছেড়ে দিলে à¦à¦–ানে যà§à¦•à§à¦¤ করা যাবে", "upload_button.label": "ছবি বা à¦à¦¿à¦¡à¦¿à¦“ যà§à¦•à§à¦¤ করতে (à¦à¦¸à¦¬ ধরণের: JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "যা যà§à¦•à§à¦¤ করতে চাচà§à¦›à§‡à¦¨ সেটি বেশি বড়, à¦à¦–ানকার সরà§à¦¬à¦¾à¦§à¦¿à¦•ের মেমোরির উপরে চলে গেছে।", "upload_error.poll": "নিরà§à¦¬à¦¾à¦šà¦¨à¦•à§à¦·à§‡à¦¤à§à¦°à§‡ কোনো ফাইল যà§à¦•à§à¦¤ করা যাবেনা।", - "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.audio_description": "শà§à¦°à¦¬à¦£à¦¶à¦•à§à¦¤à¦¿ লোকদের জনà§à¦¯ বরà§à¦£à¦¨à¦¾ করà§à¦¨", "upload_form.description": "যারা দেখতে পায়না তাদের জনà§à¦¯ à¦à¦Ÿà¦¾ বরà§à¦£à¦¨à¦¾ করতে", "upload_form.edit": "সমà§à¦ªà¦¾à¦¦à¦¨", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "থামà§à¦¬à¦¨à§‡à¦² পরিবরà§à¦¤à¦¨ করà§à¦¨", "upload_form.undo": "মà§à¦›à§‡ ফেলতে", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_form.video_description": "শà§à¦°à¦¬à¦£à¦¶à¦•à§à¦¤à¦¿ হà§à¦°à¦¾à¦¸ বা চাকà§à¦·à§à¦· পà§à¦°à¦¤à¦¿à¦¬à¦¨à§à¦§à§€ বà§à¦¯à¦•à§à¦¤à¦¿à¦¦à§‡à¦° জনà§à¦¯ বরà§à¦£à¦¨à¦¾ করà§à¦¨", "upload_modal.analyzing_picture": "চিতà§à¦° বিশà§à¦²à§‡à¦·à¦£ করা হচà§à¦›à§‡â€¦", "upload_modal.apply": "পà§à¦°à§Ÿà§‹à¦— করà§à¦¨", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "ছবি নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨", "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", "upload_modal.detect_text": "ছবি থেকে পাঠà§à¦¯ সনাকà§à¦¤ করà§à¦¨", "upload_modal.edit_media": "মিডিয়া সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করà§à¦¨", "upload_modal.hint": "à¦à¦•টি দৃশà§à¦¯à¦®à¦¾à¦¨ পয়েনà§à¦Ÿ নিরà§à¦¬à¦¾à¦šà¦¨ করà§à¦¨ কà§à¦²à¦¿à¦• অথবা টানার মাধà§à¦¯à¦®à§‡ যেটি সবময় সব থামà§à¦¬à¦¨à§‡à¦²à§‡ দেখা যাবে।", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "পূরà§à¦¬à¦°à§‚প({ratio})", "upload_progress.label": "যà§à¦•à§à¦¤ করতে পাঠানো হচà§à¦›à§‡...", "video.close": "à¦à¦¿à¦¡à¦¿à¦“টি বনà§à¦§ করতে", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index e0be9d1a2c34f298a33c7bd5570aa0227e9c10b4..84c5f452399141233e4ac597216546bc861bfd7e 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Nullañ ar bedadenn heuliañ", "account.direct": "Kas ur gemennadenn da @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domani berzet", "account.edit_profile": "Aozañ ar profil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Lakaat war-wel war ar profil", "account.follow": "Heuliañ", "account.followers": "Heulier·ezed·ien", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Disoc'hoù an enklask", "emoji_button.symbols": "Arouezioù", "emoji_button.travel": "Lec'hioù ha Beajoù", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Toud ebet amañ!", "empty_column.account_unavailable": "Profil dihegerz", "empty_column.blocks": "N'eus ket bet berzet implijer·ez ganeoc'h c'hoazh.", @@ -166,7 +169,9 @@ "empty_column.notifications": "N'ho peus kemenn ebet c'hoazh. Grit gant implijer·ezed·ien all evit loc'hañ ar gomz.", "empty_column.public": "N'eus netra amañ! Skrivit un dra bennak foran pe heuilhit implijer·ien·ezed eus dafariadoù all evit leuniañ", "error.unexpected_crash.explanation": "Abalamour d'ur beug en hor c'hod pe d'ur gudenn geverlec'hded n'hallomp ket skrammañ ar bajenn-mañ en un doare dereat.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Klaskit azbevaat ar bajenn. Ma n'a ket en-dro e c'hallit klask ober gant Mastodon dre ur merdeer disheñvel pe dre an arload genidik.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Eilañ ar roudoù diveugañ er golver", "errors.unexpected_crash.report_issue": "Danevellañ ur fazi", "follow_request.authorize": "Aotren", @@ -245,14 +250,15 @@ "keyboard_shortcuts.spoilers": "to show/hide CW field", "keyboard_shortcuts.start": "to open \"get started\" column", "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", + "keyboard_shortcuts.toggle_sensitivity": "da guzhat/ziguzhat ur media", "keyboard_shortcuts.toot": "da gregiñ gant un toud nevez-flamm", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Serriñ", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Da-heul", "lightbox.previous": "A-raok", - "lightbox.view_context": "Diskouez ar c'hemperzh", "lists.account.add": "Ouzhpennañ d'al listenn", "lists.account.remove": "Lemel kuit eus al listenn", "lists.delete": "Dilemel al listenn", @@ -260,6 +266,10 @@ "lists.edit.submit": "Cheñch an titl", "lists.new.create": "Ouzhpennañ ul listenn", "lists.new.title_placeholder": "Titl nevez al listenn", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Ho listennoù", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Toggle visibility", "missing_indicator.label": "Digavet", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Arloadoù pellgomz", "navigation_bar.blocks": "Implijer·ezed·ien berzet", "navigation_bar.bookmarks": "Sinedoù", @@ -292,12 +304,13 @@ "navigation_bar.public_timeline": "Red-amzer kevreet", "navigation_bar.security": "Diogelroez", "notification.favourite": "{name} favourited your status", - "notification.follow": "{name} followed you", + "notification.follow": "heuliañ a ra {name} ac'hanoc'h", "notification.follow_request": "{name} has requested to follow you", "notification.mention": "{name} mentioned you", "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Skarzhañ ar c'hemennoù", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Kemennoù war ar burev", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Skignadennoù:", "notifications.column_settings.show": "Diskouez er bann", "notifications.column_settings.sound": "Seniñ", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Pep tra", "notifications.filter.boosts": "Skignadennoù", "notifications.filter.favourites": "Muiañ-karet", "notifications.filter.follows": "Heuliañ", "notifications.filter.mentions": "Menegoù", "notifications.filter.polls": "Disoc'hoù ar sontadegoù", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} a gemennoù", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Serret", "poll.refresh": "Azbevaat", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Toud spilhennet", "status.read_more": "Lenn muioc'h", "status.reblog": "Skignañ", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Drag & drop to upload", - "upload_button.label": "Ouzhpennañ ur media ({formats})", + "upload_button.label": "Ouzhpennañ ur media", "upload_error.limit": "File upload limit exceeded.", "upload_error.poll": "File upload not allowed with polls.", "upload_form.audio_description": "Describe for people with hearing loss", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Dinoiñ testenn diouzh ar skeudenn", "upload_modal.edit_media": "Embann ar media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Rakwel ({ratio})", "upload_progress.label": "O pellgargañ...", "video.close": "Serriñ ar video", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 04a37fc0308b5fefd422c792153d87e03b7ceab0..13e9e885b76d96386e87edbabec715c49214ffc3 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "La teva nota per a @{name}", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Afegir o Treure de les llistes", "account.badges.bot": "Bot", "account.badges.group": "Grup", @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Navega més en el perfil original", "account.cancel_follow_request": "Anul·la la sol·licitud de seguiment", "account.direct": "Missatge directe @{name}", + "account.disable_notifications": "Deixa de notificar-me els tuts de @{name}", "account.domain_blocked": "Domini ocult", "account.edit_profile": "Edita el perfil", + "account.enable_notifications": "Notifica’m els tuts de @{name}", "account.endorse": "Recomana en el teu perfil", "account.follow": "Segueix", "account.followers": "Seguidors", "account.followers.empty": "Encara ningú no segueix aquest usuari.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidors}}", - "account.following_counter": "{count, plural, one {} other {{counter} Seguint}}", + "account.following_counter": "{count, plural, other {{counter} Seguint}}", "account.follows.empty": "Aquest usuari encara no segueix a ningú.", "account.follows_you": "Et segueix", "account.hide_reblogs": "Amaga els impulsos de @{name}", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultats de la cerca", "emoji_button.symbols": "SÃmbols", "emoji_button.travel": "Viatges i Llocs", + "empty_column.account_suspended": "Compte suspès", "empty_column.account_timeline": "No hi ha tuts aquÃ!", "empty_column.account_unavailable": "Perfil no disponible", "empty_column.blocks": "Encara no has bloquejat cap usuari.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Encara no tens notificacions. Interactua amb altres per iniciar la conversa.", "empty_column.public": "No hi ha res aquÃ! Escriu públicament alguna cosa o manualment segueix usuaris d'altres servidors per omplir-ho", "error.unexpected_crash.explanation": "A causa d'un bug en el nostre codi o un problema de compatibilitat del navegador, aquesta pà gina podria no ser mostrada correctament.", - "error.unexpected_crash.next_steps": "Prova recarregant la pà gina. Si això no ajuda, encara podries ser capaç d'utilitzar Mastodon a través d'un navegador diferent o amb una app nativa.", + "error.unexpected_crash.explanation_addons": "Aquesta pà gina podria no mostrar-se correctament. Aquest error és possiblement causat per una extensió del navegador o per eienes automà tiques de traducció.", + "error.unexpected_crash.next_steps": "Prova recarregant la pà gina. Si això no ajuda, encara podries ser capaç d'utilitzar Mastodon a través d'un navegador diferent o amb una aplicació nativa.", + "error.unexpected_crash.next_steps_addons": "Prova de desactivar-les i refrescant la pà gina. Si això no ajuda, encara pots ser capaç d’utilitzar Mastodon amb un altre navegador o aplicació nativa.", "errors.unexpected_crash.copy_stacktrace": "Còpia stacktrace al porta-retalls", "errors.unexpected_crash.report_issue": "Informa d'un problema", "follow_request.authorize": "Autoritzar", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "descentrar l'à rea de composició de text/cerca", "keyboard_shortcuts.up": "moure amunt en la llista", "lightbox.close": "Tancar", + "lightbox.compress": "Quadre de visualització d’imatge comprimida", + "lightbox.expand": "Amplia el quadre de visualització de l’imatge", "lightbox.next": "Següent", "lightbox.previous": "Anterior", - "lightbox.view_context": "Veure el context", "lists.account.add": "Afegir a la llista", "lists.account.remove": "Treure de la llista", "lists.delete": "Esborrar llista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Canvi de tÃtol", "lists.new.create": "Afegir llista", "lists.new.title_placeholder": "Nova llista", + "lists.replies_policy.followed": "Qualsevol usuari seguit", + "lists.replies_policy.list": "Membres de la llista", + "lists.replies_policy.none": "Ningú", + "lists.replies_policy.title": "Mostra respostes a:", "lists.search": "Cercar entre les persones que segueixes", "lists.subheading": "Les teves llistes", "load_pending": "{count, plural, one {# element nou} other {# elements nous}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Alternar visibilitat", "missing_indicator.label": "No trobat", "missing_indicator.sublabel": "Aquest recurs no pot ser trobat", + "mute_modal.duration": "Durada", "mute_modal.hide_notifications": "Amagar notificacions d'aquest usuari?", + "mute_modal.indefinite": "Indefinit", "navigation_bar.apps": "Apps mòbils", "navigation_bar.blocks": "Usuaris bloquejats", "navigation_bar.bookmarks": "Marcadors", @@ -298,6 +310,7 @@ "notification.own_poll": "La teva enquesta ha finalitzat", "notification.poll": "Ha finalitzat una enquesta en la que has votat", "notification.reblog": "{name} ha impulsat el teu estat", + "notification.status": "ha publicat {name}", "notifications.clear": "Netejar notificacions", "notifications.clear_confirmation": "Està s segur que vols esborrar permanentment totes les teves notificacions?", "notifications.column_settings.alert": "Notificacions d'escriptori", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Impulsos:", "notifications.column_settings.show": "Mostra en la columna", "notifications.column_settings.sound": "Reproduir so", + "notifications.column_settings.status": "Nous tuts:", "notifications.filter.all": "Tots", "notifications.filter.boosts": "Impulsos", "notifications.filter.favourites": "Favorits", "notifications.filter.follows": "Seguiments", "notifications.filter.mentions": "Mencions", "notifications.filter.polls": "Resultats de l'enquesta", + "notifications.filter.statuses": "Actualitzacions de gent que segueixes", + "notifications.grant_permission": "Concedir permÃs.", "notifications.group": "{count} notificacions", + "notifications.mark_as_read": "Marca cada notificació com a llegida", + "notifications.permission_denied": "No s’ha pogut activar les notificacions d’escriptori perquè s’ha denegat el permÃs.", + "notifications.permission_denied_alert": "No es poden activar les notificacions del escriptori perquè el permÃs del navegador ha estat denegat abans", + "notifications.permission_required": "Les notificacions d'escriptori no estan disponibles perquè el permÃs requerit no ha estat concedit.", + "notifications_permission_banner.enable": "Activar les notificacions d’escriptori", + "notifications_permission_banner.how_to_control": "Per a rebre notificacions quan Mastodon no està obert cal activar les notificacions d’escriptori. Pots controlar amb precisió quins tipus d’interaccions generen notificacions d’escriptori després d’activar el botó {icon} de dalt.", + "notifications_permission_banner.title": "Mai et perdis res", + "picture_in_picture.restore": "Retorna’l", "poll.closed": "Finalitzada", "poll.refresh": "Actualitza", "poll.total_people": "{count, plural, one {# persona} other {# persones}}", @@ -442,10 +466,11 @@ "upload_modal.analyzing_picture": "Analitzant imatge…", "upload_modal.apply": "Aplica", "upload_modal.choose_image": "Tria imatge", - "upload_modal.description_placeholder": "Uns salts rà pids de guineu marró sobre el gos gandul", + "upload_modal.description_placeholder": "Jove xef, porti whisky amb quinze glaçons d’hidrogen, coi!", "upload_modal.detect_text": "Detecta el text de l'imatge", "upload_modal.edit_media": "Editar multimèdia", "upload_modal.hint": "Fes clic o arrossega el cercle en la previsualització per escollir el punt focal que sempre serà visible de totes les miniatures.", + "upload_modal.preparing_ocr": "Preparant OCR…", "upload_modal.preview_label": "Previsualitza ({ratio})", "upload_progress.label": "Pujant...", "video.close": "Tancar el vÃdeo", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 1bd9cda0b5a8093f1bdedb417a8decfc5961ef06..43e1f6c104a3e6e0798f0c7b8569361c3b1c657e 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "A vostra nota per @{name}", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Aghjunghje o toglie da e liste", "account.badges.bot": "Bot", "account.badges.group": "Gruppu", @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Vede di più nant'à u prufile uriginale", "account.cancel_follow_request": "Annullà a dumanda d'abbunamentu", "account.direct": "Missaghju direttu @{name}", + "account.disable_notifications": "Ùn mi nutificate più quandu @{name} pubblica qualcosa", "account.domain_blocked": "Duminiu piattatu", "account.edit_profile": "Mudificà u prufile", + "account.enable_notifications": "Nutificate mi quandu @{name} pubblica qualcosa", "account.endorse": "Fà figurà nant'à u prufilu", "account.follow": "Siguità ", "account.followers": "Abbunati", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Cambià u scandagliu per ùn accittà ch'una scelta", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Indicà u media cum'è sensibile", - "compose_form.sensitive.marked": "Media indicatu cum'è sensibile", - "compose_form.sensitive.unmarked": "Media micca indicatu cum'è sensibile", + "compose_form.sensitive.hide": "{count, plural, one {Indicà u media cum'è sensibile} other {Indicà i media cum'è sensibili}}", + "compose_form.sensitive.marked": "{count, plural, one {Media indicatu cum'è sensibile} other {Media indicati cum'è sensibili}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media micca indicatu cum'è sensibile} other {Media micca indicati cum'è sensibili}}", "compose_form.spoiler.marked": "Testu piattatu daret'à un'avertimentu", "compose_form.spoiler.unmarked": "Testu micca piattatu", "compose_form.spoiler_placeholder": "Scrive u vostr'avertimentu quì", @@ -132,7 +134,7 @@ "directory.new_arrivals": "Ultimi arrivi", "directory.recently_active": "Attività ricente", "embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.", - "embed.preview": "Assumiglierà à qualcosa cusì:", + "embed.preview": "Hà da parè à quessa:", "emoji_button.activity": "Attività ", "emoji_button.custom": "Persunalizati", "emoji_button.flags": "Bandere", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Risultati di a cerca", "emoji_button.symbols": "Simbuli", "emoji_button.travel": "Lochi è Viaghju", + "empty_column.account_suspended": "Contu suspesu", "empty_column.account_timeline": "Nisun statutu quì!", "empty_column.account_unavailable": "Prufile micca dispunibule", "empty_column.blocks": "Per avà ùn avete bluccatu manc'un utilizatore.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Ùn avete ancu nisuna nutificazione. Interact with others to start the conversation.", "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altri servori per empie a linea pubblica", "error.unexpected_crash.explanation": "In ragione d'un bug indè u nostru codice o un prublemu di cumpatibilità cù quessu navigatore, sta pagina ùn hè micca pussuta esse affissata currettamente.", + "error.unexpected_crash.explanation_addons": "Sta pagina ùn hè micca pussuta esse affissata currettamente, prubabilmente per via d'un'estenzione di navigatore o d'un lugiziale di traduzione.", "error.unexpected_crash.next_steps": "Pruvate d'attualizà sta pagina. S'ellu persiste u prublemu, pudete forse sempre accede à Mastodon dapoi un'alltru navigatore o applicazione.", + "error.unexpected_crash.next_steps_addons": "Pruvate di disattivà quelli è poi attualizà sta pagina. S'ellu persiste u prublemu, pudete forse sempre accede à Mastodon dapoi un'alltru navigatore o applicazione.", "errors.unexpected_crash.copy_stacktrace": "Cupià stacktrace nant'à u fermacarta", "errors.unexpected_crash.report_issue": "Palisà prublemu", "follow_request.authorize": "Auturizà ", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "ùn fucalizà più l'area di testu", "keyboard_shortcuts.up": "cullà indè a lista", "lightbox.close": "Chjudà ", + "lightbox.compress": "Cumprime a finestra d'affissera di i ritratti", + "lightbox.expand": "Ingrandà a finestra d'affissera di i ritratti", "lightbox.next": "Siguente", "lightbox.previous": "Pricidente", - "lightbox.view_context": "Vede u cuntestu", "lists.account.add": "Aghjunghje à a lista", "lists.account.remove": "Toglie di a lista", "lists.delete": "Toglie a lista", @@ -260,14 +266,20 @@ "lists.edit.submit": "Cambià u titulu", "lists.new.create": "Aghjunghje", "lists.new.title_placeholder": "Titulu di a lista", + "lists.replies_policy.followed": "Tutti i vostri abbunamenti", + "lists.replies_policy.list": "Membri di a lista", + "lists.replies_policy.none": "Nimu", + "lists.replies_policy.title": "Vede e risposte à :", "lists.search": "Circà indè i vostr'abbunamenti", "lists.subheading": "E vo liste", "load_pending": "{count, plural, one {# entrata nova} other {# entrate nove}}", "loading_indicator.label": "Caricamentu...", - "media_gallery.toggle_visible": "Cambià a visibilità ", + "media_gallery.toggle_visible": "Piattà {number, plural, one {ritrattu} other {ritratti}}", "missing_indicator.label": "Micca trovu", "missing_indicator.sublabel": "Ùn era micca pussivule di truvà sta risorsa", + "mute_modal.duration": "Durata", "mute_modal.hide_notifications": "Piattà nutificazione da st'utilizatore?", + "mute_modal.indefinite": "Indifinita", "navigation_bar.apps": "Applicazione per u telefuninu", "navigation_bar.blocks": "Utilizatori bluccati", "navigation_bar.bookmarks": "Segnalibri", @@ -298,6 +310,7 @@ "notification.own_poll": "U vostru scandagliu hè compiu", "notification.poll": "Un scandagliu induve avete vutatu hè finitu", "notification.reblog": "{name} hà spartutu u vostru statutu", + "notification.status": "{name} hà appena pubblicatu", "notifications.clear": "Purgà e nutificazione", "notifications.clear_confirmation": "Site sicuru·a che vulete toglie tutte ste nutificazione?", "notifications.column_settings.alert": "Nutificazione nant'à l'urdinatore", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Spartere:", "notifications.column_settings.show": "Mustrà indè a colonna", "notifications.column_settings.sound": "Sunà ", + "notifications.column_settings.status": "Statuti novi:", "notifications.filter.all": "Tuttu", "notifications.filter.boosts": "Spartere", "notifications.filter.favourites": "Favuriti", "notifications.filter.follows": "Abbunamenti", "notifications.filter.mentions": "Minzione", "notifications.filter.polls": "Risultati di u scandagliu", + "notifications.filter.statuses": "Messe à ghjornu di e persone chì siguitate", + "notifications.grant_permission": "Auturizà .", "notifications.group": "{count} nutificazione", + "notifications.mark_as_read": "Marcà tutte e nutificazione cum'è lette", + "notifications.permission_denied": "Ùn si po micca attivà e nutificazione desktop perchè l'auturizazione hè stata ricusata", + "notifications.permission_denied_alert": "Ùn pudete micca attivà e nutificazione nant'à l'urdinatore, perchè avete digià ricusatu a dumanda d'auturizazione di u navigatore", + "notifications.permission_required": "Ùn si po micca attivà e nutificazione desktop perchè a l'auturizazione richiesta ùn hè micca stata data.", + "notifications_permission_banner.enable": "Attivà e nutificazione nant'à l'urdinatore", + "notifications_permission_banner.how_to_control": "Per riceve nutificazione quandu Mastodon ùn hè micca aperta, attivate e nutificazione nant'à l'urdinatore. Pudete decide quali tippi d'interazione anu da mandà ste nutificazione cù u buttone {icon} quì sopra quandu saranu attivate.", + "notifications_permission_banner.title": "Ùn mancate mai nunda", + "picture_in_picture.restore": "Rimette in piazza", "poll.closed": "Chjosu", "poll.refresh": "Attualizà ", "poll.total_people": "{count, plural, one {# persona} other {# persone}}", @@ -352,7 +376,7 @@ "report.hint": "U signalamentu sarà mandatu à i muderatori di u servore. Pudete spiegà perchè avete palisatu stu contu quì sottu:", "report.placeholder": "Altri cummenti", "report.submit": "Mandà ", - "report.target": "Signalamentu", + "report.target": "Signalamentu di {target}", "search.placeholder": "Circà ", "search_popout.search_format": "Ricerca avanzata", "search_popout.tips.full_text": "I testi simplici rimandanu i statuti ch'avete scritti, aghjunti à i vostri favuriti, spartuti o induve quelli site mintuvatu·a, è ancu i cugnomi, nomi pubblichi è hashtag chì currispondenu.", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Drag & drop per caricà un fugliale", - "upload_button.label": "Aghjunghje un media ({formats})", + "upload_button.label": "Aghjunghje un media", "upload_error.limit": "Limita di caricamentu di fugliali trapassata.", "upload_error.poll": "Ùn si pò micca caricà fugliali cù i scandagli.", "upload_form.audio_description": "Discrizzione per i ciochi", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Ditettà testu da u ritrattu", "upload_modal.edit_media": "Cambià media", "upload_modal.hint": "Cliccate o sguillate u chjerchju nant'à a vista per sceglie u puntu fucale chì sarà sempre in vista indè tutte e miniature.", + "upload_modal.preparing_ocr": "Priparazione di l'OCR…", "upload_modal.preview_label": "Vista ({ratio})", "upload_progress.label": "Caricamentu...", "video.close": "Chjudà a video", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 0ddd18de898a72c1f54a05f11abf394397cb09d8..76df857d833d45e605433c0deed754f4c9adf94f 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Poznámka", "account.add_or_remove_from_list": "PÅ™idat nebo odstranit ze seznamů", "account.badges.bot": "Robot", "account.badges.group": "Skupina", @@ -9,13 +9,15 @@ "account.browse_more_on_origin_server": "VÃce na původnÃm profilu", "account.cancel_follow_request": "ZruÅ¡it žádost o sledovánÃ", "account.direct": "Poslat uživateli @{name} pÅ™Ãmou zprávu", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Doména skryta", "account.edit_profile": "Upravit profil", + "account.enable_notifications": "Oznámit mÄ› na pÅ™ÃspÄ›vky @{name}", "account.endorse": "Zvýraznit na profilu", "account.follow": "Sledovat", "account.followers": "SledujÃcÃ", "account.followers.empty": "Tohoto uživatele jeÅ¡tÄ› nikdo nesleduje.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.followers_counter": "{count, plural, one {{counter} sledujÃcÃ} few {{counter} sledujÃcÃ} many {{counter} sledujÃcÃch} other {{counter} sledujÃcÃch}}", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Tento uživatel jeÅ¡tÄ› nikoho nesleduje.", "account.follows_you": "Sleduje vás", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Výsledky hledánÃ", "emoji_button.symbols": "Symboly", "emoji_button.travel": "Cestovánà a mÃsta", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Nejsou tu žádné tooty!", "empty_column.account_unavailable": "Profil nedostupný", "empty_column.blocks": "JeÅ¡tÄ› jste nezablokovali žádného uživatele.", @@ -166,13 +169,15 @@ "empty_column.notifications": "JeÅ¡tÄ› nemáte žádná oznámenÃ. ZaÄnÄ›te s nÄ›kým konverzaci.", "empty_column.public": "Tady nic nenÃ! NapiÅ¡te nÄ›co veÅ™ejnÄ›, nebo zaÄnÄ›te ruÄnÄ› sledovat uživatele z jiných serverů, aby tu nÄ›co pÅ™ibylo", "error.unexpected_crash.explanation": "Kvůli chybÄ› v naÅ¡em kódu nebo problému s kompatibilitou prohlÞeÄe nemohla být tato stránka naÄtena správnÄ›.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Zkuste stránku naÄÃst znovu. Pokud to nepomůže, zkuste Mastodon použÃvat pomocà jiného prohlÞeÄe nebo nativnà aplikace.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "ZkopÃrovat stacktrace do schránky", "errors.unexpected_crash.report_issue": "Nahlásit problém", "follow_request.authorize": "Autorizovat", "follow_request.reject": "OdmÃtnout", "follow_requests.unlocked_explanation": "PÅ™estože váš úÄet nenà uzamÄen, {domain} si myslÃ, že budete chtÃt následujÃcà požadavky na sledovánà zkontrolovat ruÄnÄ›.", - "generic.saved": "Saved", + "generic.saved": "Uloženo", "getting_started.developers": "Vývojáři", "getting_started.directory": "Adresář profilů", "getting_started.documentation": "Dokumentace", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "zruÅ¡enà zaměřenà na psacà prostor/hledánÃ", "keyboard_shortcuts.up": "posunutà nahoru v seznamu", "lightbox.close": "ZavÅ™Ãt", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "DalÅ¡Ã", "lightbox.previous": "PÅ™edchozÃ", - "lightbox.view_context": "Zobrazit kontext", "lists.account.add": "PÅ™idat do seznamu", "lists.account.remove": "Odebrat ze seznamu", "lists.delete": "Smazat seznam", @@ -260,6 +266,10 @@ "lists.edit.submit": "ZmÄ›nit název", "lists.new.create": "PÅ™idat seznam", "lists.new.title_placeholder": "Název nového seznamu", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Hledejte mezi lidmi, které sledujete", "lists.subheading": "VaÅ¡e seznamy", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "PÅ™epnout viditelnost", "missing_indicator.label": "Nenalezeno", "missing_indicator.sublabel": "Tento zdroj se nepodaÅ™ilo najÃt", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Skrýt oznámenà od tohoto uživatele?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobilnà aplikace", "navigation_bar.blocks": "Blokovanà uživatelé", "navigation_bar.bookmarks": "Záložky", @@ -298,6 +310,7 @@ "notification.own_poll": "VaÅ¡e anketa skonÄila", "notification.poll": "Anketa, ve které jste hlasovali, skonÄila", "notification.reblog": "Uživatel {name} boostnul váš toot", + "notification.status": "{name} just posted", "notifications.clear": "Smazat oznámenÃ", "notifications.clear_confirmation": "Opravdu chcete trvale smazat vÅ¡echna vaÅ¡e oznámenÃ?", "notifications.column_settings.alert": "Oznámenà na poÄÃtaÄi", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosty:", "notifications.column_settings.show": "Zobrazit ve sloupci", "notifications.column_settings.sound": "PÅ™ehrát zvuk", + "notifications.column_settings.status": "Nové tooty:", "notifications.filter.all": "VÅ¡e", "notifications.filter.boosts": "Boosty", "notifications.filter.favourites": "OblÃbenÃ", "notifications.filter.follows": "SledovánÃ", "notifications.filter.mentions": "ZmÃnky", "notifications.filter.polls": "Výsledky anket", + "notifications.filter.statuses": "Aktuality od lidÃ, které sledujete", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} oznámenÃ", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "UzavÅ™eno", "poll.refresh": "Obnovit", "poll.total_people": "{count, plural, one {# ÄlovÄ›k} few {# lidé} many {# lidÃ} other {# lidÃ}}", @@ -430,13 +454,13 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Nahrajte pÅ™etaženÃm", - "upload_button.label": "PÅ™idat média ({formats})", + "upload_button.label": "PÅ™idat média", "upload_error.limit": "Byl pÅ™ekroÄen limit nahraných souborů.", "upload_error.poll": "U anket nenà nahrávánà souborů povoleno.", "upload_form.audio_description": "Popis pro sluchovÄ› postižené", "upload_form.description": "Popis pro zrakovÄ› postižené", "upload_form.edit": "Upravit", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "ZmÄ›nit miniaturu", "upload_form.undo": "Smazat", "upload_form.video_description": "Popis pro sluchovÄ› Äi zrakovÄ› postižené", "upload_modal.analyzing_picture": "Analyzuji obrázek…", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detekovat text z obrázku", "upload_modal.edit_media": "Upravit média", "upload_modal.hint": "KliknutÃm na nebo pÅ™etáhnutÃm kruhu na náhledu vyberte oblast, která bude na vÅ¡ech náhledech vždy zobrazen.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Náhled ({ratio})", "upload_progress.label": "NahrávánÃ…", "video.close": "ZavÅ™Ãt video", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 312a0f97a270662f787ac5eec26a32b0ea2bf9c6..b3c1947b40925991c60c478144f1c2e092bf9eb7 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Nodyn", "account.add_or_remove_from_list": "Ychwanegu neu Dileu o'r rhestrau", "account.badges.bot": "Bot", "account.badges.group": "Grŵp", "account.block": "Blocio @{name}", "account.block_domain": "Cuddio popeth rhag {domain}", "account.blocked": "Blociwyd", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Pori mwy ar y proffil gwreiddiol", "account.cancel_follow_request": "Canslo cais dilyn", "account.direct": "Neges breifat @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Parth wedi ei guddio", "account.edit_profile": "Golygu proffil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Arddangos ar fy mhroffil", "account.follow": "Dilyn", "account.followers": "Dilynwyr", "account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Ddilynwr} other {{counter} o Ddilynwyr}}", + "account.following_counter": "{count, plural, one {{counter} yn Dilyn} other {{counter} yn Dilyn}}", "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.follows_you": "Yn eich dilyn chi", "account.hide_reblogs": "Cuddio bwstiau o @{name}", @@ -36,14 +38,14 @@ "account.requested": "Aros am gymeradwyaeth. Cliciwch er mwyn canslo cais dilyn", "account.share": "Rhannwch broffil @{name}", "account.show_reblogs": "Dangos bwstiau o @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} Dŵt} other {{counter} o Dŵtiau}}", "account.unblock": "Dadflocio @{name}", "account.unblock_domain": "Dadguddio {domain}", "account.unendorse": "Peidio a'i arddangos ar fy mhroffil", "account.unfollow": "Dad-ddilyn", "account.unmute": "Dad-dawelu @{name}", "account.unmute_notifications": "Dad-dawelu hysbysiadau o @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Clicio i ychwanegu nodyn", "alert.rate_limited.message": "Ceisiwch eto ar ôl {retry_time, time, medium}.", "alert.rate_limited.title": "Cyfradd gyfyngedig", "alert.unexpected.message": "Digwyddodd gwall annisgwyl.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Canlyniadau chwilio", "emoji_button.symbols": "Symbolau", "emoji_button.travel": "Teithio & Llefydd", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Dim tŵtiau fama!", "empty_column.account_unavailable": "Proffil ddim ar gael", "empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Nid oes gennych unrhyw hysbysiadau eto. Rhyngweithiwch ac eraill i ddechrau'r sgwrs.", "empty_column.public": "Does dim byd yma! Ysgrifennwch rhywbeth yn gyhoeddus, neu dilynwch ddefnyddwyr o achosion eraill i'w lenwi", "error.unexpected_crash.explanation": "Oherwydd gwall yn ein cod neu oherwydd problem cysondeb porwr, nid oedd y dudalen hon gallu cael ei dangos yn gywir.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Ceisiwch ail-lwytho y dudalen. Os nad yw hyn yn eich helpu, efallai gallech defnyddio Mastodon trwy borwr neu ap brodorol gwahanol.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copïo'r olrhain stac i'r clipfwrdd", "errors.unexpected_crash.report_issue": "Rhoi gwybod am broblem", "follow_request.authorize": "Caniatau", "follow_request.reject": "Gwrthod", "follow_requests.unlocked_explanation": "Er nid yw eich cyfrif wedi'i gloi, oedd y staff {domain} yn meddwl efallai hoffech adolygu ceisiadau dilyn o'r cyfrifau rhain wrth law.", - "generic.saved": "Saved", + "generic.saved": "Wedi'i Gadw", "getting_started.developers": "Datblygwyr", "getting_started.directory": "Cyfeiriadur proffil", "getting_started.documentation": "Dogfennaeth", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "i ateb", "keyboard_shortcuts.requests": "i agor rhestr ceisiadau dilyn", "keyboard_shortcuts.search": "i ffocysu chwilio", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "i ddangos/cuddio'r maes CW", "keyboard_shortcuts.start": "i agor colofn \"dechrau arni\"", "keyboard_shortcuts.toggle_hidden": "i ddangos/cuddio testun tu ôl i CW", "keyboard_shortcuts.toggle_sensitivity": "i ddangos/gyddio cyfryngau", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "i ddad-ffocysu ardal cyfansoddi testun/chwilio", "keyboard_shortcuts.up": "i symud yn uwch yn y rhestr", "lightbox.close": "Cau", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Nesaf", "lightbox.previous": "Blaenorol", - "lightbox.view_context": "Gweld cyd-destyn", "lists.account.add": "Ychwanegwch at restr", "lists.account.remove": "Dileu o'r rhestr", "lists.delete": "Dileu rhestr", @@ -260,6 +266,10 @@ "lists.edit.submit": "Newid teitl", "lists.new.create": "Ychwanegu rhestr", "lists.new.title_placeholder": "Teitl rhestr newydd", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Chwilio ymysg pobl yr ydych yn ei ddilyn", "lists.subheading": "Eich rhestrau", "load_pending": "{count, plural, one {# eitem newydd} other {# eitemau newydd}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Toglo gwelededd", "missing_indicator.label": "Heb ei ganfod", "missing_indicator.sublabel": "Ni ellid canfod yr adnodd hwn", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Cuddio hysbysiadau rhag y defnyddiwr hwn?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Apiau symudol", "navigation_bar.blocks": "Defnyddwyr wedi eu blocio", "navigation_bar.bookmarks": "Tudalnodau", @@ -298,6 +310,7 @@ "notification.own_poll": "Mae eich pôl wedi diweddu", "notification.poll": "Mae pleidlais rydych wedi pleidleisio ynddi wedi dod i ben", "notification.reblog": "Hysbysebodd {name} eich tŵt", + "notification.status": "{name} just posted", "notifications.clear": "Clirio hysbysiadau", "notifications.clear_confirmation": "Ydych chi'n sicr eich bod am glirio'ch holl hysbysiadau am byth?", "notifications.column_settings.alert": "Hysbysiadau bwrdd gwaith", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Hybiadau:", "notifications.column_settings.show": "Dangos yn y golofn", "notifications.column_settings.sound": "Chwarae sain", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Pob", "notifications.filter.boosts": "Hybiadau", "notifications.filter.favourites": "Ffefrynnau", "notifications.filter.follows": "Yn dilyn", "notifications.filter.mentions": "Crybwylliadau", "notifications.filter.polls": "Canlyniadau pleidlais", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} o hysbysiadau", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Ar gau", "poll.refresh": "Adnewyddu", "poll.total_people": "{count, plural, one {# berson} other {# o bobl}}", @@ -419,16 +443,16 @@ "time_remaining.minutes": "{number, plural, one {# funud} other {# o funudau}} ar ôl", "time_remaining.moments": "Munudau ar ôl", "time_remaining.seconds": "{number, plural, one {# eiliad} other {# o eiliadau}} ar ôl", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "ni chaiff {resource} o gweinyddion eraill ei ddangos.", + "timeline_hint.resources.followers": "Dilynwyr", + "timeline_hint.resources.follows": "Yn dilyn", + "timeline_hint.resources.statuses": "Tŵtiau henach", + "trends.counter_by_accounts": "{count, plural, one {{counter} berson} other {{counter} o bobl}}", "trends.trending_now": "Yn tueddu nawr", "ui.beforeunload": "Mi fyddwch yn colli eich drafft os gadewch Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count}biliwn", + "units.short.million": "{count}miliwn", + "units.short.thousand": "{count}mil", "upload_area.title": "Llusgwch & gollwing i uwchlwytho", "upload_button.label": "Ychwanegwch gyfryngau (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Wedi mynd heibio'r uchafswm terfyn uwchlwytho.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Disgrifio ar gyfer pobl sydd â cholled clyw", "upload_form.description": "Disgrifio i'r rheini a nam ar ei golwg", "upload_form.edit": "Golygu", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Newid mân-lun", "upload_form.undo": "Dileu", "upload_form.video_description": "Disgrifio ar gyfer pobl sydd â cholled clyw neu amhariad golwg", "upload_modal.analyzing_picture": "Dadansoddi llun…", "upload_modal.apply": "Gweithredu", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Dewis delwedd", "upload_modal.description_placeholder": "Mae ei phen bach llawn jocs, 'run peth a fy nghot golff, rhai dyddiau", "upload_modal.detect_text": "Canfod testun o'r llun", "upload_modal.edit_media": "Golygu cyfryngau", "upload_modal.hint": "Cliciwch neu llusgwch y cylch ar y rhagolwg i ddewis y canolbwynt a fydd bob amser i'w weld ar bob mân-lunau.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Rhagolwg ({ratio})", "upload_progress.label": "Uwchlwytho...", "video.close": "Cau fideo", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index a0fb354e6692f3900cb1425eaab94688fd43d395..7c4b3e4ef350bafa9bcb82aa68e1c28919a318d7 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -6,16 +6,18 @@ "account.block": "Bloker @{name}", "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blokeret", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Gennemse mere pÃ¥ den oprindelige profil", "account.cancel_follow_request": "Annullér følgeranmodning", "account.direct": "Send en direkte besked til @{name}", + "account.disable_notifications": "Stop med at give mig besked nÃ¥r @{name} lægger noget op", "account.domain_blocked": "Domænet er blevet skjult", "account.edit_profile": "Rediger profil", + "account.enable_notifications": "Giv mig besked nÃ¥r @{name} lægger noget op", "account.endorse": "Fremhæv pÃ¥ profil", "account.follow": "Følg", "account.followers": "Følgere", "account.followers.empty": "Der er endnu ingen der følger denne bruger.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.followers_counter": "{count, plural, one {{counter} Følger} other {{counter} Følgere}}", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", "account.follows.empty": "Denne bruger følger endnu ikke nogen.", "account.follows_you": "Følger dig", @@ -48,7 +50,7 @@ "alert.rate_limited.title": "Gradsbegrænset", "alert.unexpected.message": "Der opstod en uventet fejl.", "alert.unexpected.title": "Ups!", - "announcement.announcement": "Announcement", + "announcement.announcement": "Bekendtgørelse", "autosuggest_hashtag.per_week": "{count} per uge", "boost_modal.combo": "Du kan trykke {combo} for at springe dette over næste gang", "bundle_column_error.body": "Noget gik galt under indlæsningen af dette komponent.", @@ -79,9 +81,9 @@ "column_header.show_settings": "Vis indstillinger", "column_header.unpin": "Fastgør ikke længere", "column_subheading.settings": "Indstillinger", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "Kun lokalt", "community.column_settings.media_only": "Kun medie", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "Kun fjernt", "compose_form.direct_message_warning": "Dette trut vil kun blive sendt til de nævnte brugere.", "compose_form.direct_message_warning_learn_more": "Lær mere", "compose_form.hashtag_warning": "Dette trut vil ikke blive vist under noget hashtag da det ikke er listet. Kun offentlige trut kan blive vist under søgninger med hashtags.", @@ -92,8 +94,8 @@ "compose_form.poll.duration": "Afstemningens varighed", "compose_form.poll.option_placeholder": "Valgmulighed {number}", "compose_form.poll.remove_option": "Fjern denne valgmulighed", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.poll.switch_to_multiple": "Ændre afstemning for at tillade flere valg", + "compose_form.poll.switch_to_single": "Ændre afstemning for at tillade et enkelt valg", "compose_form.publish": "Trut", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.hide": "Markér medie som følsomt", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Søgeresultater", "emoji_button.symbols": "Symboler", "emoji_button.travel": "Rejser & steder", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ingen bidrag her!", "empty_column.account_unavailable": "Profil utilgængelig", "empty_column.blocks": "Du har ikke blokeret nogen endnu.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Du har endnu ingen notifikationer. Tag ud og bland dig med folkemængden for at starte samtalen.", "empty_column.public": "Der er ikke noget at se her! Skriv noget offentligt eller start ud med manuelt at følge brugere fra andre server for at udfylde tomrummet", "error.unexpected_crash.explanation": "PÃ¥ grund af en fejl i vores kode, eller en browser kompatibilitetsfejl, sÃ¥ kunne siden ikke vises korrekt.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Prøv at genindlæs siden. Hvis dette ikke hjælper, sÃ¥ forsøg venligst, at tilgÃ¥ Mastodon via en anden browser eller app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopiér stack trace til udklipsholderen", "errors.unexpected_crash.report_issue": "Rapportér problem", "follow_request.authorize": "Godkend", "follow_request.reject": "Afvis", - "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "Selvom din konto ikke er lÃ¥st, troede {domain} -personalet, at du mÃ¥ske vil gennemgÃ¥ dine anmodninger manuelt.", + "generic.saved": "Gemt", "getting_started.developers": "Udviklere", "getting_started.directory": "Profilliste", "getting_started.documentation": "Dokumentation", @@ -193,8 +198,8 @@ "home.column_settings.basic": "Grundlæggende", "home.column_settings.show_reblogs": "Vis fremhævelser", "home.column_settings.show_replies": "Vis svar", - "home.hide_announcements": "Hide announcements", - "home.show_announcements": "Show announcements", + "home.hide_announcements": "Skjul bekendtgørelser", + "home.show_announcements": "Vis bekendtgørelser", "intervals.full.days": "{number, plural, one {# dag} other {# dage}}", "intervals.full.hours": "{number, plural, one {# time} other {# timer}}", "intervals.full.minutes": "{number, plural, one {# minut} other {# minutter}}", @@ -236,13 +241,13 @@ "keyboard_shortcuts.muted": "for at Ã¥bne listen over dæmpede brugere", "keyboard_shortcuts.my_profile": "for at Ã¥bne din profil", "keyboard_shortcuts.notifications": "for at Ã¥bne notifikations kolonnen", - "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.open_media": "for at Ã¥bne medier", "keyboard_shortcuts.pinned": "for at Ã¥bne listen over fastgjorte trut", "keyboard_shortcuts.profile": "til profil af Ã¥ben forfatter", "keyboard_shortcuts.reply": "for at svare", "keyboard_shortcuts.requests": "for at Ã¥bne listen over følgeranmodninger", "keyboard_shortcuts.search": "for at fokusere søgningen", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "for at vise/skjule CW-felt", "keyboard_shortcuts.start": "for at Ã¥bne \"kom igen\" kolonnen", "keyboard_shortcuts.toggle_hidden": "for at vise/skjule tekst bag CW", "keyboard_shortcuts.toggle_sensitivity": "for at vise/skjule medier", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "for at fjerne fokus fra skriveomrÃ¥de/søgning", "keyboard_shortcuts.up": "for at bevæge dig op ad listen", "lightbox.close": "Luk", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Næste", "lightbox.previous": "Forrige", - "lightbox.view_context": "Vis kontekst", "lists.account.add": "Tilføj til liste", "lists.account.remove": "Fjern fra liste", "lists.delete": "Slet liste", @@ -260,6 +266,10 @@ "lists.edit.submit": "Skift titel", "lists.new.create": "Tilføj liste", "lists.new.title_placeholder": "Ny liste titel", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Vis svar til:", "lists.search": "Søg iblandt folk du følger", "lists.subheading": "Dine lister", "load_pending": "{count, plural, one {# nyt punkt} other {# nye punkter}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Ændre synlighed", "missing_indicator.label": "Ikke fundet", "missing_indicator.sublabel": "Denne ressource kunne ikke blive fundet", + "mute_modal.duration": "Varighed", "mute_modal.hide_notifications": "Skjul notifikationer fra denne bruger?", + "mute_modal.indefinite": "Uendeligt", "navigation_bar.apps": "Mobil apps", "navigation_bar.blocks": "Blokerede brugere", "navigation_bar.bookmarks": "Bogmærker", @@ -293,11 +305,12 @@ "navigation_bar.security": "Sikkerhed", "notification.favourite": "{name} favoriserede din status", "notification.follow": "{name} fulgte dig", - "notification.follow_request": "{name} has requested to follow you", + "notification.follow_request": "{name} har anmodet om at følge dig", "notification.mention": "{name} nævnte dig", "notification.own_poll": "Din afstemning er afsluttet", "notification.poll": "En afstemning, du stemte i, er slut", "notification.reblog": "{name} boostede din status", + "notification.status": "{name} har lige lagt noget op", "notifications.clear": "Ryd notifikationer", "notifications.clear_confirmation": "Er du sikker pÃ¥, du vil rydde alle dine notifikationer permanent?", "notifications.column_settings.alert": "Skrivebordsnotifikationer", @@ -306,20 +319,31 @@ "notifications.column_settings.filter_bar.category": "Hurtigfilter", "notifications.column_settings.filter_bar.show": "Vis", "notifications.column_settings.follow": "Nye følgere:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.follow_request": "Nye følgeranmodninger:", "notifications.column_settings.mention": "Statusser der nævner dig:", "notifications.column_settings.poll": "Afstemningsresultat:", "notifications.column_settings.push": "Pushnotifikationer", "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Vis i kolonne", "notifications.column_settings.sound": "Afspil lyd", + "notifications.column_settings.status": "Nye toots:", "notifications.filter.all": "Alle", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favoritter", "notifications.filter.follows": "Følger", "notifications.filter.mentions": "Statusser der nævner dig", "notifications.filter.polls": "Afstemningsresultat", + "notifications.filter.statuses": "Opdateringer fra personer, du følger", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifikationer", + "notifications.mark_as_read": "Markér alle notifikationer som læst", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Aktivér skrivebordsmeddelelser", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "GÃ¥ aldrig glip af noget", + "picture_in_picture.restore": "Sæt den tilbage", "poll.closed": "Lukket", "poll.refresh": "Opdatér", "poll.total_people": "{count, plural, one {# person} other {# personer}}", @@ -419,10 +443,10 @@ "time_remaining.minutes": "{number, plural, one {# minut} other {# minutter}} tilbage", "time_remaining.moments": "FÃ¥ øjeblikke tilbage", "time_remaining.seconds": "{number, plural, one {# sekund} other {# sekunder}} tilbage", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", + "timeline_hint.remote_resource_not_displayed": "{resource} fra andre servere vises ikke.", + "timeline_hint.resources.followers": "Følgere", + "timeline_hint.resources.follows": "Følger", + "timeline_hint.resources.statuses": "Ældre toots", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", "trends.trending_now": "Hot lige nu", "ui.beforeunload": "Din kladde vil gÃ¥ tabt hvis du forlader Mastodon.", @@ -433,19 +457,20 @@ "upload_button.label": "Tilføj medie (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Uploadgrænse overskredet.", "upload_error.poll": "Filupload ikke tilladt sammen med afstemninger.", - "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.audio_description": "Beskriv for personer med høretab", "upload_form.description": "Beskriv for svagtseende", "upload_form.edit": "Redigér", "upload_form.thumbnail": "Change thumbnail", "upload_form.undo": "Slet", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_form.video_description": "Beskriv for personer med høretab eller nedsat syn", "upload_modal.analyzing_picture": "Analyserer billede…", "upload_modal.apply": "Anvend", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Vælg billede", "upload_modal.description_placeholder": "En hurtig brun ræv hopper over den dovne hund", "upload_modal.detect_text": "Find tekst i billede pÃ¥ automatisk vis", "upload_modal.edit_media": "Redigér medie", "upload_modal.hint": "Klik eller træk cirklen pÃ¥ billedet for at vælge et fokuspunkt.", + "upload_modal.preparing_ocr": "Forbereder OCR…", "upload_modal.preview_label": "ForhÃ¥ndsvisning ({ratio})", "upload_progress.label": "Uploader...", "video.close": "Luk video", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index d0274b077ddb6a4dd866c180616b1e2fe8c161ce..1c177302985a0918796fa3d904519d44180e6d8e 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -1,16 +1,18 @@ { - "account.account_note_header": "Deine Notiz für @{name}", + "account.account_note_header": "Notiz", "account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen", "account.badges.bot": "Bot", "account.badges.group": "Gruppe", "account.block": "@{name} blockieren", - "account.block_domain": "Alles von {domain} blockieren", + "account.block_domain": "Alles von {domain} verstecken", "account.blocked": "Blockiert", "account.browse_more_on_origin_server": "Mehr auf dem Originalprofil durchsuchen", "account.cancel_follow_request": "Folgeanfrage abbrechen", "account.direct": "Direktnachricht an @{name}", + "account.disable_notifications": "Höre auf mich zu benachrichtigen wenn @{name} etwas postet", "account.domain_blocked": "Domain versteckt", "account.edit_profile": "Profil bearbeiten", + "account.enable_notifications": "Benachrichtige mich wenn @{name} etwas postet", "account.endorse": "Auf Profil hervorheben", "account.follow": "Folgen", "account.followers": "Folgende", @@ -38,12 +40,12 @@ "account.show_reblogs": "Von @{name} geteilte Beiträge anzeigen", "account.statuses_counter": "{count, plural, one {{counter} Beitrag} other {{counter} Beiträge}}", "account.unblock": "@{name} entblocken", - "account.unblock_domain": "Blockieren von {domain} beenden", + "account.unblock_domain": "{domain} wieder anzeigen", "account.unendorse": "Nicht auf Profil hervorheben", "account.unfollow": "Entfolgen", "account.unmute": "@{name} nicht mehr stummschalten", "account.unmute_notifications": "Benachrichtigungen von @{name} einschalten", - "account_note.placeholder": "Kein Kommentar angegeben", + "account_note.placeholder": "Notiz durch Klicken hinzufügen", "alert.rate_limited.message": "Bitte versuche es nach {retry_time, time, medium}.", "alert.rate_limited.title": "Anfragelimit überschritten", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", @@ -62,7 +64,7 @@ "column.community": "Lokale Zeitleiste", "column.direct": "Direktnachrichten", "column.directory": "Profile durchsuchen", - "column.domain_blocks": "Versteckte Domains", + "column.domain_blocks": "Blockierte Domains", "column.favourites": "Favoriten", "column.follow_requests": "Folgeanfragen", "column.home": "Startseite", @@ -94,11 +96,11 @@ "compose_form.poll.remove_option": "Wahl entfernen", "compose_form.poll.switch_to_multiple": "Umfrage ändern, um mehrere Optionen zu erlauben", "compose_form.poll.switch_to_single": "Umfrage ändern, um eine einzige Wahl zu erlauben", - "compose_form.publish": "Beitrag", + "compose_form.publish": "Tröt", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Medien als heikel markieren", - "compose_form.sensitive.marked": "Medien sind als heikel markiert", - "compose_form.sensitive.unmarked": "Medien sind nicht als heikel markiert", + "compose_form.sensitive.hide": "Medien als NSFW markieren", + "compose_form.sensitive.marked": "Medien sind als NSFW markiert", + "compose_form.sensitive.unmarked": "Medien sind nicht als NSFW markiert", "compose_form.spoiler.marked": "Text ist hinter einer Warnung versteckt", "compose_form.spoiler.unmarked": "Text ist nicht versteckt", "compose_form.spoiler_placeholder": "Inhaltswarnung", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Suchergebnisse", "emoji_button.symbols": "Symbole", "emoji_button.travel": "Reisen und Orte", + "empty_column.account_suspended": "Konto gesperrt", "empty_column.account_timeline": "Keine Beiträge!", "empty_column.account_unavailable": "Konto nicht verfügbar", "empty_column.blocks": "Du hast keine Profile blockiert.", @@ -165,8 +168,10 @@ "empty_column.mutes": "Du hast keine Profile stummgeschaltet.", "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.", "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Zeitleiste aufzufüllen", - "error.unexpected_crash.explanation": "Aufgrund eines Fehlers in unserem Code oder einer Browser-Inkompatibilität konnte diese Seite nicht korrekt angezeigt werden.", + "error.unexpected_crash.explanation": "Aufgrund eines Fehlers in unserem Code oder einer Browsereinkompatibilität konnte diese Seite nicht korrekt angezeigt werden.", + "error.unexpected_crash.explanation_addons": "Diese Seite konnte nicht korrekt angezeigt werden. Dieser Fehler wird wahrscheinlich durch ein Browser-Add-on oder automatische Übersetzungswerkzeuge verursacht.", "error.unexpected_crash.next_steps": "Versuche die Seite zu aktualisieren. Wenn das nicht hilft, kannst du Mastodon über einen anderen Browser oder eine native App verwenden.", + "error.unexpected_crash.next_steps_addons": "Versuche sie zu deaktivieren und lade dann die Seite neu. Wenn das Problem weiterhin besteht, solltest du Mastodon über einen anderen Browser oder eine native App nutzen.", "errors.unexpected_crash.copy_stacktrace": "Fehlerlog in die Zwischenablage kopieren", "errors.unexpected_crash.report_issue": "Problem melden", "follow_request.authorize": "Erlauben", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "Textfeld/die Suche nicht mehr fokussieren", "keyboard_shortcuts.up": "sich in der Liste hinauf bewegen", "lightbox.close": "Schließen", + "lightbox.compress": "Bildansicht komprimieren", + "lightbox.expand": "Bildansicht erweitern", "lightbox.next": "Weiter", "lightbox.previous": "Zurück", - "lightbox.view_context": "Beitrag sehen", "lists.account.add": "Zur Liste hinzufügen", "lists.account.remove": "Von der Liste entfernen", "lists.delete": "Liste löschen", @@ -260,6 +266,10 @@ "lists.edit.submit": "Titel ändern", "lists.new.create": "Liste hinzufügen", "lists.new.title_placeholder": "Neuer Titel der Liste", + "lists.replies_policy.followed": "Jeder gefolgte Benutzer", + "lists.replies_policy.list": "Mitglieder der Liste", + "lists.replies_policy.none": "Niemand", + "lists.replies_policy.title": "Antworten anzeigen für:", "lists.search": "Suche nach Leuten denen du folgst", "lists.subheading": "Deine Listen", "load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Sichtbarkeit umschalten", "missing_indicator.label": "Nicht gefunden", "missing_indicator.sublabel": "Die Ressource konnte nicht gefunden werden", + "mute_modal.duration": "Dauer", "mute_modal.hide_notifications": "Benachrichtigungen von diesem Account verbergen?", + "mute_modal.indefinite": "Unbestimmt", "navigation_bar.apps": "Mobile Apps", "navigation_bar.blocks": "Blockierte Profile", "navigation_bar.bookmarks": "Lesezeichen", @@ -298,6 +310,7 @@ "notification.own_poll": "Deine Umfrage ist beendet", "notification.poll": "Eine Umfrage in der du abgestimmt hast ist vorbei", "notification.reblog": "{name} hat deinen Beitrag geteilt", + "notification.status": "{name} hat gerade etwas gepostet", "notifications.clear": "Mitteilungen löschen", "notifications.clear_confirmation": "Bist du dir sicher, dass du alle Mitteilungen löschen möchtest?", "notifications.column_settings.alert": "Desktop-Benachrichtigungen", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Geteilte Beiträge:", "notifications.column_settings.show": "In der Spalte anzeigen", "notifications.column_settings.sound": "Ton abspielen", + "notifications.column_settings.status": "Neue Beiträge:", "notifications.filter.all": "Alle", "notifications.filter.boosts": "Geteilte Beiträge", "notifications.filter.favourites": "Favorisierungen", "notifications.filter.follows": "Folgt", "notifications.filter.mentions": "Erwähnungen", "notifications.filter.polls": "Ergebnisse der Umfrage", + "notifications.filter.statuses": "Updates von Personen, denen du folgst", + "notifications.grant_permission": "Zugriff gewährt.", "notifications.group": "{count} Benachrichtigungen", + "notifications.mark_as_read": "Alle Benachrichtigungen als gelesen markieren", + "notifications.permission_denied": "Desktop-Benachrichtigungen können nicht aktiviert werden, da die Berechtigung verweigert wurde.", + "notifications.permission_denied_alert": "Desktop-Benachrichtigungen können nicht aktiviert werden, da die Browser-Berechtigung zuvor verweigert wurde", + "notifications.permission_required": "Desktop-Benachrichtigungen sind nicht verfügbar, da die erforderliche Berechtigung nicht erteilt wurde.", + "notifications_permission_banner.enable": "Aktiviere Desktop-Benachrichtigungen", + "notifications_permission_banner.how_to_control": "Um Benachrichtigungen zu erhalten, wenn Mastodon nicht geöffnet ist, aktiviere die Desktop-Benachrichtigungen. Du kannst genau bestimmen, welche Arten von Interaktionen Desktop-Benachrichtigungen über die {icon} -Taste erzeugen, sobald diese aktiviert sind.", + "notifications_permission_banner.title": "Verpasse nie etwas", + "picture_in_picture.restore": "Zurücksetzen", "poll.closed": "Geschlossen", "poll.refresh": "Aktualisieren", "poll.total_people": "{count, plural, one {# Person} other {# Personen}}", @@ -357,7 +381,7 @@ "search_popout.search_format": "Fortgeschrittenes Suchformat", "search_popout.tips.full_text": "Einfache Texteingabe gibt Beiträge, die du geschrieben, favorisiert und geteilt hast zurück. Außerdem auch Beiträge in denen du erwähnt wurdest, aber auch passende Nutzernamen, Anzeigenamen oder Hashtags.", "search_popout.tips.hashtag": "Hashtag", - "search_popout.tips.status": "Beitrag", + "search_popout.tips.status": "Tröt", "search_popout.tips.text": "Einfache Texteingabe gibt Anzeigenamen, Benutzernamen und Hashtags zurück", "search_popout.tips.user": "Nutzer", "search_results.accounts": "Personen", @@ -397,7 +421,7 @@ "status.reply": "Antworten", "status.replyAll": "Allen antworten", "status.report": "@{name} melden", - "status.sensitive_warning": "Heikle Inhalte", + "status.sensitive_warning": "NSFW", "status.share": "Teilen", "status.show_less": "Weniger anzeigen", "status.show_less_all": "Alle Inhaltswarnungen zuklappen", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Zum Hochladen hereinziehen", - "upload_button.label": "Mediendatei hinzufügen ({formats})", + "upload_button.label": "Mediendatei hinzufügen", "upload_error.limit": "Dateiupload-Limit erreicht.", "upload_error.poll": "Dateiuploads sind in Kombination mit Umfragen nicht erlaubt.", "upload_form.audio_description": "Beschreibe die Audiodatei für Menschen mit Hörschädigungen", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Text aus Bild erkennen", "upload_modal.edit_media": "Medien bearbeiten", "upload_modal.hint": "Klicke oder ziehe den Kreis auf die Vorschau, um den Brennpunkt auszuwählen, der immer auf allen Vorschaubilder angezeigt wird.", + "upload_modal.preparing_ocr": "Vorbereitung von OCR…", "upload_modal.preview_label": "Vorschau ({ratio})", "upload_progress.label": "Wird hochgeladen …", "video.close": "Video schließen", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index bd9ebbc0de960103a878c6da02eacc409f2ce5b4..d9ebf0a4c5c4f28ed829294b5cdf99a0ee3f212e 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -167,10 +167,18 @@ }, { "descriptors": [ + { + "defaultMessage": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", + "id": "error.unexpected_crash.explanation_addons" + }, { "defaultMessage": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", "id": "error.unexpected_crash.explanation" }, + { + "defaultMessage": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "id": "error.unexpected_crash.next_steps_addons" + }, { "defaultMessage": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "id": "error.unexpected_crash.next_steps" @@ -265,6 +273,15 @@ ], "path": "app/javascript/mastodon/components/missing_indicator.json" }, + { + "descriptors": [ + { + "defaultMessage": "Put it back", + "id": "picture_in_picture.restore" + } + ], + "path": "app/javascript/mastodon/components/picture_in_picture_placeholder.json" + }, { "descriptors": [ { @@ -421,7 +438,7 @@ "id": "status.reblog" }, { - "defaultMessage": "Boost to original audience", + "defaultMessage": "Boost with original visibility", "id": "status.reblog_private" }, { @@ -633,6 +650,19 @@ ], "path": "app/javascript/mastodon/containers/status_container.json" }, + { + "descriptors": [ + { + "defaultMessage": "Account suspended", + "id": "empty_column.account_suspended" + }, + { + "defaultMessage": "Profile unavailable", + "id": "empty_column.account_unavailable" + } + ], + "path": "app/javascript/mastodon/features/account_gallery/index.json" + }, { "descriptors": [ { @@ -686,6 +716,10 @@ "defaultMessage": "Older toots", "id": "timeline_hint.resources.statuses" }, + { + "defaultMessage": "Account suspended", + "id": "empty_column.account_suspended" + }, { "defaultMessage": "Profile unavailable", "id": "empty_column.account_unavailable" @@ -796,6 +830,14 @@ "defaultMessage": "Show boosts from @{name}", "id": "account.show_reblogs" }, + { + "defaultMessage": "Notify me when @{name} posts", + "id": "account.enable_notifications" + }, + { + "defaultMessage": "Stop notifying me when @{name} posts", + "id": "account.disable_notifications" + }, { "defaultMessage": "Pinned toots", "id": "navigation_bar.pins" @@ -1305,15 +1347,15 @@ { "descriptors": [ { - "defaultMessage": "Media is marked as sensitive", + "defaultMessage": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", "id": "compose_form.sensitive.marked" }, { - "defaultMessage": "Media is not marked as sensitive", + "defaultMessage": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "id": "compose_form.sensitive.unmarked" }, { - "defaultMessage": "Mark media as sensitive", + "defaultMessage": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", "id": "compose_form.sensitive.hide" } ], @@ -2125,6 +2167,18 @@ "defaultMessage": "Delete", "id": "confirmations.delete_list.confirm" }, + { + "defaultMessage": "Any followed user", + "id": "lists.replies_policy.followed" + }, + { + "defaultMessage": "No one", + "id": "lists.replies_policy.none" + }, + { + "defaultMessage": "Members of the list", + "id": "lists.replies_policy.list" + }, { "defaultMessage": "Edit list", "id": "lists.edit" @@ -2133,6 +2187,10 @@ "defaultMessage": "Delete list", "id": "lists.delete" }, + { + "defaultMessage": "Show replies to:", + "id": "lists.replies_policy.title" + }, { "defaultMessage": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", "id": "empty_column.list" @@ -2218,6 +2276,14 @@ "defaultMessage": "Push notifications", "id": "notifications.column_settings.push" }, + { + "defaultMessage": "Desktop notifications are unavailable due to previously denied browser permissions request", + "id": "notifications.permission_denied" + }, + { + "defaultMessage": "Desktop notifications are unavailable because the required permission has not been granted.", + "id": "notifications.permission_required" + }, { "defaultMessage": "Quick filter bar", "id": "notifications.column_settings.filter_bar.category" @@ -2245,6 +2311,10 @@ { "defaultMessage": "Poll results:", "id": "notifications.column_settings.poll" + }, + { + "defaultMessage": "New toots:", + "id": "notifications.column_settings.status" } ], "path": "app/javascript/mastodon/features/notifications/components/column_settings.json" @@ -2271,6 +2341,10 @@ "defaultMessage": "Follows", "id": "notifications.filter.follows" }, + { + "defaultMessage": "Updates from people you follow", + "id": "notifications.filter.statuses" + }, { "defaultMessage": "All", "id": "notifications.filter.all" @@ -2291,6 +2365,15 @@ ], "path": "app/javascript/mastodon/features/notifications/components/follow_request.json" }, + { + "descriptors": [ + { + "defaultMessage": "Grant permission.", + "id": "notifications.grant_permission" + } + ], + "path": "app/javascript/mastodon/features/notifications/components/grant_permission_button.json" + }, { "descriptors": [ { @@ -2313,6 +2396,10 @@ "defaultMessage": "{name} boosted your status", "id": "notification.reblog" }, + { + "defaultMessage": "{name} just posted", + "id": "notification.status" + }, { "defaultMessage": "{name} has requested to follow you", "id": "notification.follow_request" @@ -2320,6 +2407,27 @@ ], "path": "app/javascript/mastodon/features/notifications/components/notification.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "Never miss a thing", + "id": "notifications_permission_banner.title" + }, + { + "defaultMessage": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "id": "notifications_permission_banner.how_to_control" + }, + { + "defaultMessage": "Enable desktop notifications", + "id": "notifications_permission_banner.enable" + } + ], + "path": "app/javascript/mastodon/features/notifications/components/notifications_permission_banner.json" + }, { "descriptors": [ { @@ -2329,6 +2437,10 @@ { "defaultMessage": "Clear notifications", "id": "notifications.clear" + }, + { + "defaultMessage": "Desktop notifications can't be enabled, as browser permission has been denied before", + "id": "notifications.permission_denied_alert" } ], "path": "app/javascript/mastodon/features/notifications/containers/column_settings_container.json" @@ -2339,6 +2451,10 @@ "defaultMessage": "Notifications", "id": "column.notifications" }, + { + "defaultMessage": "Mark every notification as read", + "id": "notifications.mark_as_read" + }, { "defaultMessage": "You don't have any notifications yet. Interact with others to start the conversation.", "id": "empty_column.notifications" @@ -2346,6 +2462,60 @@ ], "path": "app/javascript/mastodon/features/notifications/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Reply", + "id": "status.reply" + }, + { + "defaultMessage": "Reply to thread", + "id": "status.replyAll" + }, + { + "defaultMessage": "Boost", + "id": "status.reblog" + }, + { + "defaultMessage": "Boost with original visibility", + "id": "status.reblog_private" + }, + { + "defaultMessage": "Unboost", + "id": "status.cancel_reblog_private" + }, + { + "defaultMessage": "This post cannot be boosted", + "id": "status.cannot_reblog" + }, + { + "defaultMessage": "Favourite", + "id": "status.favourite" + }, + { + "defaultMessage": "Reply", + "id": "confirmations.reply.confirm" + }, + { + "defaultMessage": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "id": "confirmations.reply.message" + }, + { + "defaultMessage": "Expand this status", + "id": "status.open" + } + ], + "path": "app/javascript/mastodon/features/picture_in_picture/components/footer.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + } + ], + "path": "app/javascript/mastodon/features/picture_in_picture/components/header.json" + }, { "descriptors": [ { @@ -2421,7 +2591,7 @@ "id": "status.reblog" }, { - "defaultMessage": "Boost to original audience", + "defaultMessage": "Boost with original visibility", "id": "status.reblog_private" }, { @@ -2619,15 +2789,6 @@ ], "path": "app/javascript/mastodon/features/status/index.json" }, - { - "descriptors": [ - { - "defaultMessage": "View context", - "id": "lightbox.view_context" - } - ], - "path": "app/javascript/mastodon/features/ui/components/audio_modal.json" - }, { "descriptors": [ { @@ -2785,6 +2946,14 @@ "defaultMessage": "Describe for the visually impaired", "id": "upload_form.description" }, + { + "defaultMessage": "Analyzing picture…", + "id": "upload_modal.analyzing_picture" + }, + { + "defaultMessage": "Preparing OCR…", + "id": "upload_modal.preparing_ocr" + }, { "defaultMessage": "Edit media", "id": "upload_modal.edit_media" @@ -2797,10 +2966,6 @@ "defaultMessage": "Change thumbnail", "id": "upload_form.thumbnail" }, - { - "defaultMessage": "Analyzing picture…", - "id": "upload_modal.analyzing_picture" - }, { "defaultMessage": "Detect text from picture", "id": "upload_modal.detect_text" @@ -2887,16 +3052,28 @@ { "defaultMessage": "Next", "id": "lightbox.next" - }, - { - "defaultMessage": "View context", - "id": "lightbox.view_context" } ], "path": "app/javascript/mastodon/features/ui/components/media_modal.json" }, { "descriptors": [ + { + "defaultMessage": "{number, plural, one {# minute} other {# minutes}}", + "id": "intervals.full.minutes" + }, + { + "defaultMessage": "{number, plural, one {# hour} other {# hours}}", + "id": "intervals.full.hours" + }, + { + "defaultMessage": "{number, plural, one {# day} other {# days}}", + "id": "intervals.full.days" + }, + { + "defaultMessage": "Indefinite", + "id": "mute_modal.indefinite" + }, { "defaultMessage": "Are you sure you want to mute {name}?", "id": "confirmations.mute.message" @@ -2909,6 +3086,10 @@ "defaultMessage": "Hide notifications from this user?", "id": "mute_modal.hide_notifications" }, + { + "defaultMessage": "Duration", + "id": "mute_modal.duration" + }, { "defaultMessage": "Cancel", "id": "confirmation_modal.cancel" @@ -3039,11 +3220,15 @@ { "descriptors": [ { - "defaultMessage": "View context", - "id": "lightbox.view_context" + "defaultMessage": "Compress image view box", + "id": "lightbox.compress" + }, + { + "defaultMessage": "Expand image view box", + "id": "lightbox.expand" } ], - "path": "app/javascript/mastodon/features/ui/components/video_modal.json" + "path": "app/javascript/mastodon/features/ui/components/zoomable_image.json" }, { "descriptors": [ diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 74b3e1c9a03e80bbba99b151f89c42c931c61b3c..7b73731659ad305d697fd0315c35f4a5adcb2900 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Δες πεÏισσότεÏα στο αÏχικό Ï€Ïοφίλ", "account.cancel_follow_request": "ΑκÏÏωση αιτήματος παÏακολοÏθησης", "account.direct": "Î Ïοσωπικό μήνυμα Ï€Ïος @{name}", + "account.disable_notifications": "Διακοπή ειδοποιήσεων για τις δημοσιεÏσεις του/της @{name}", "account.domain_blocked": "ΚÏυμμÎνος τομÎας", "account.edit_profile": "ΕπεξεÏγασία Ï€Ïοφίλ", + "account.enable_notifications": "ΈναÏξη ειδοποιήσεων για τις δημοσιεÏσεις του/της @{name}", "account.endorse": "Î Ïοβολή στο Ï€Ïοφίλ", "account.follow": "ΑκολοÏθησε", "account.followers": "Ακόλουθοι", "account.followers.empty": "Κανείς δεν ακολουθεί αυτό τον χÏήστη ακόμα.", "account.followers_counter": "{count, plural, one {{counter} Ακόλουθος} other {{counter} Ακόλουθοι}}", - "account.following_counter": "{count, plural, one {} other {{counter} Ακολουθεί}}", + "account.following_counter": "{count, plural, other {{counter} Ακολουθεί}}", "account.follows.empty": "Αυτός ο χÏήστης δεν ακολουθεί κανÎναν ακόμα.", "account.follows_you": "Σε ακολουθεί", "account.hide_reblogs": "ΑπόκÏυψη Ï€Ïοωθήσεων από @{name}", @@ -147,6 +149,7 @@ "emoji_button.search_results": "ΑποτελÎσματα αναζήτησης", "emoji_button.symbols": "ΣÏμβολα", "emoji_button.travel": "Ταξίδια & Τοποθεσίες", + "empty_column.account_suspended": "ΛογαÏιασμός σε αναστολή", "empty_column.account_timeline": "Δεν Îχει τουτ εδώ!", "empty_column.account_unavailable": "Μη διαθÎσιμο Ï€Ïοφίλ", "empty_column.blocks": "Δεν Îχεις αποκλείσει κανÎναν χÏήστη ακόμα.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Δεν Îχεις ειδοποιήσεις ακόμα. ΑλληλεπίδÏασε με άλλους χÏήστες για να ξεκινήσεις την κουβÎντα.", "empty_column.public": "Δεν υπάÏχει τίποτα εδώ! ΓÏάψε κάτι δημόσιο, ή ακολοÏθησε χειÏοκίνητα χÏήστες από άλλους κόμβους για να τη γεμίσεις", "error.unexpected_crash.explanation": "Είτε λόγω λάθους στον κώδικά μας ή λόγω ασυμβατότητας με τον browser, η σελίδα δε μπόÏεσε να εμφανιστεί σωστά.", + "error.unexpected_crash.explanation_addons": "Η σελίδα δεν μπόÏεσε να εμφανιστεί σωστά. Το Ï€Ïόβλημα οφείλεται πιθανόν σε κάποια επÎκταση του φυλλομετÏητή (browser extension) ή σε κάποιο αυτόματο εÏγαλείο μετάφÏασης.", "error.unexpected_crash.next_steps": "Δοκίμασε να ανανεώσεις τη σελίδα. Αν αυτό δε βοηθήσει, ίσως να μποÏÎσεις να χÏησιμοποιήσεις το Mastodon μÎσω διαφοÏÎµÏ„Î¹ÎºÎ¿Ï browser ή κάποιας εφαÏμογής.", + "error.unexpected_crash.next_steps_addons": "Δοκίμασε να τα απενεÏγοποιήσεις και ανανÎωσε τη σελίδα. Αν αυτό δεν βοηθήσει, ίσως να μποÏÎσεις να χÏησιμοποιήσεις το Mastodon μÎσω διαφοÏÎµÏ„Î¹ÎºÎ¿Ï Ï†Ï…Î»Î»Î¿Î¼ÎµÏ„Ïητή ή κάποιας εφαÏμογής.", "errors.unexpected_crash.copy_stacktrace": "ΑντιγÏαφή μηνυμάτων κώδικα στο Ï€ÏόχειÏο", "errors.unexpected_crash.report_issue": "ΑναφοÏά Ï€Ïοβλήματος", "follow_request.authorize": "ΕνÎκÏινε", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "απο-εστίαση του πεδίου σÏνθεσης/αναζήτησης", "keyboard_shortcuts.up": "κίνηση Ï€Ïος την κοÏυφή της λίστας", "lightbox.close": "Κλείσιμο", + "lightbox.compress": "Συμπίεση πλαισίου εμφάνισης εικόνας", + "lightbox.expand": "Ανάπτυξη πλαισίου εμφάνισης εικόνας", "lightbox.next": "Επόμενο", "lightbox.previous": "Î ÏοηγοÏμενο", - "lightbox.view_context": "Εμφάνιση πλαισίου", "lists.account.add": "Î Ïόσθεσε στη λίστα", "lists.account.remove": "Βγάλε από τη λίστα", "lists.delete": "ΔιαγÏαφή λίστας", @@ -260,6 +266,10 @@ "lists.edit.submit": "Αλλαγή τίτλου", "lists.new.create": "Î Ïοσθήκη λίστας", "lists.new.title_placeholder": "Τίτλος νÎας λίστα", + "lists.replies_policy.followed": "Οποιοσδήποτε χÏήστης που ακολουθείς", + "lists.replies_policy.list": "ΜÎλη της λίστας", + "lists.replies_policy.none": "ΚανÎνας", + "lists.replies_policy.title": "Εμφάνιση απαντήσεων σε:", "lists.search": "Αναζήτησε Î¼ÎµÏ„Î±Î¾Ï Ï„Ï‰Î½ ανθÏώπων που ακουλουθείς", "lists.subheading": "Οι λίστες σου", "load_pending": "{count, plural, one {# νÎο} other {# νÎα}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Εναλλαγή οÏατότητας", "missing_indicator.label": "Δε βÏÎθηκε", "missing_indicator.sublabel": "ΑδÏνατη η εÏÏεση Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… πόÏου", + "mute_modal.duration": "ΔιάÏκεια", "mute_modal.hide_notifications": "ΑπόκÏυψη ειδοποιήσεων Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… χÏήστη;", + "mute_modal.indefinite": "ΑόÏιστη", "navigation_bar.apps": "ΕφαÏμογÎÏ‚ φοÏητών συσκευών", "navigation_bar.blocks": "ΑποκλεισμÎνοι χÏήστες", "navigation_bar.bookmarks": "Σελιδοδείκτες", @@ -298,6 +310,7 @@ "notification.own_poll": "Η ψηφοφοÏία σου Îληξε", "notification.poll": "Τελείωσε μια από τις ψηφοφοÏίες που συμμετείχες", "notification.reblog": "Ο/Η {name} Ï€Ïοώθησε την κατάστασή σου", + "notification.status": "Ο/Η {name} μόλις ÎγÏαψε κάτι", "notifications.clear": "ΚαθαÏισμός ειδοποιήσεων", "notifications.clear_confirmation": "ΣίγουÏα θÎλεις να καθαÏίσεις όλες τις ειδοποιήσεις σου;", "notifications.column_settings.alert": "Ειδοποιήσεις επιφάνειας εÏγασίας", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Î Ïοωθήσεις:", "notifications.column_settings.show": "Εμφάνισε σε στήλη", "notifications.column_settings.sound": "Ηχητική ειδοποίηση", + "notifications.column_settings.status": "ÎÎα τουτ:", "notifications.filter.all": "Όλες", "notifications.filter.boosts": "Î Ïοωθήσεις", "notifications.filter.favourites": "ΑγαπημÎνα", "notifications.filter.follows": "Ακόλουθοι", "notifications.filter.mentions": "ΑναφοÏÎÏ‚", "notifications.filter.polls": "ΑποτελÎσματα ψηφοφοÏίας", + "notifications.filter.statuses": "ΕνημεÏώσεις από όσους ακολουθείς", + "notifications.grant_permission": "ΧοÏήγηση άδειας.", "notifications.group": "{count} ειδοποιήσεις", + "notifications.mark_as_read": "Σημείωσε όλες τις ειδοποιήσεις ως αναγνωσμÎνες", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Οι ειδοποιήσεις δεν είναι διαθÎσιμες επειδή δεν Îχει δοθεί η απαιτοÏμενη άδεια.", + "notifications_permission_banner.enable": "ΕνεÏγοποίηση ειδοποιήσεων επιφάνειας εÏγασίας", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Μη χάσετε τίποτα", + "picture_in_picture.restore": "ΕπαναφοÏά", "poll.closed": "Κλειστή", "poll.refresh": "ΑνανÎωση", "poll.total_people": "{count, plural, one {# άτομο} other {# άτομα}}", @@ -388,7 +412,7 @@ "status.pin": "ΚαÏφίτσωσε στο Ï€Ïοφίλ", "status.pinned": "ΚαÏφιτσωμÎνο τουτ", "status.read_more": "ΠεÏισσότεÏα", - "status.reblog": "Î Ïοώθησε", + "status.reblog": "Î Ïοώθηση", "status.reblog_private": "Î Ïοώθησε στους αÏχικοÏÏ‚ παÏαλήπτες", "status.reblogged_by": "{name} Ï€Ïοώθησε", "status.reblogs.empty": "Κανείς δεν Ï€Ïοώθησε αυτό το τουτ ακόμα. Μόλις το κάνει κάποια, θα εμφανιστοÏν εδώ.", @@ -430,7 +454,7 @@ "units.short.million": "{count}Ε", "units.short.thousand": "{count}Χ", "upload_area.title": "Drag & drop για να ανεβάσεις", - "upload_button.label": "Î Ïόσθεσε πολυμÎσα ({formats})", + "upload_button.label": "Î Ïόσθεσε πολυμÎσα", "upload_error.limit": "ΥπÎÏβαση οÏίου μεγÎθους ανεβασμÎνων αÏχείων.", "upload_error.poll": "Στις δημοσκοπήσεις δεν επιτÏÎπεται η μεταφόÏτωση αÏχείου.", "upload_form.audio_description": "ΠεÏιγÏαφή για άτομα με Ï€Ïοβλήματα ακοής", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "ΑναγνώÏιση κειμÎνου από την εικόνα", "upload_modal.edit_media": "ΕπεξεÏγασία ΠολυμÎσων", "upload_modal.hint": "Κάνε κλικ ή σείÏε τον κÏκλο στην Ï€Ïοεπισκόπηση για να επιλÎξεις το σημείο εστίασης που θα είναι πάντα εμφανÎÏ‚ σε όλες τις μικÏογÏαφίες.", + "upload_modal.preparing_ocr": "Î Ïοετοιμασία αναγνώÏισης κειμÎνου…", "upload_modal.preview_label": "Î Ïοεπισκόπηση ({ratio})", "upload_progress.label": "Ανεβαίνει...", "video.close": "Κλείσε το βίντεο", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 381ff028bbaabd510dc2fb095e9c2152048a1386..3f8d3724929462886e0e1372494d3f5ce1062e9d 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain blocked", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your toot", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 88608339277959192a4979d8d4c8d2aea28091b5..5cff6c5af688c694e3411ba68f0164ddc465ac24 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -4,19 +4,21 @@ "account.badges.bot": "Roboto", "account.badges.group": "Grupo", "account.block": "Bloki @{name}", - "account.block_domain": "KaÅi ĉion de {domain}", + "account.block_domain": "Bloki {domain}", "account.blocked": "Blokita", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Rigardi pli al la originala profilo", "account.cancel_follow_request": "Nuligi peton de sekvado", "account.direct": "Rekte mesaÄi @{name}", - "account.domain_blocked": "Domajno kaÅita", + "account.disable_notifications": "Stop notifying me when @{name} posts", + "account.domain_blocked": "Domajno blokita", "account.edit_profile": "Redakti profilon", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Montri en profilo", "account.follow": "Sekvi", "account.followers": "Sekvantoj", "account.followers.empty": "AnkoraÅ neniu sekvas tiun uzanton.", "account.followers_counter": "{count, plural, one{{counter} Sekvanto} other {{counter} Sekvantoj}}", - "account.following_counter": "{count, plural, other{{counter} Sekvi}}", + "account.following_counter": "{count, plural, one {{counter} Sekvato} other {{counter} Sekvatoj}}", "account.follows.empty": "Tiu uzanto ankoraÅ ne sekvas iun.", "account.follows_you": "Sekvas vin", "account.hide_reblogs": "KaÅi diskonigojn de @{name}", @@ -36,14 +38,14 @@ "account.requested": "Atendo de aprobo. Alklaku por nuligi peton de sekvado", "account.share": "Diskonigi la profilon de @{name}", "account.show_reblogs": "Montri diskonigojn de @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Tooto} other {{counter} Tootoj}}", + "account.statuses_counter": "{count, plural, one {{counter} MesaÄo} other {{counter} MesaÄoj}}", "account.unblock": "Malbloki @{name}", - "account.unblock_domain": "MalkaÅi {domain}", + "account.unblock_domain": "Malbloki {domain}", "account.unendorse": "Ne montri en profilo", "account.unfollow": "Ne plu sekvi", "account.unmute": "Malsilentigi @{name}", "account.unmute_notifications": "Malsilentigi sciigojn de @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Alklaku por aldoni noton", "alert.rate_limited.message": "Bonvolu reprovi post {retry_time, time, medium}.", "alert.rate_limited.title": "MesaÄkvante limigita", "alert.unexpected.message": "Neatendita eraro okazis.", @@ -62,7 +64,7 @@ "column.community": "Loka tempolinio", "column.direct": "Rektaj mesaÄoj", "column.directory": "Trarigardi profilojn", - "column.domain_blocks": "KaÅitaj domajnoj", + "column.domain_blocks": "Blokitaj domajnoj", "column.favourites": "Stelumoj", "column.follow_requests": "Petoj de sekvado", "column.home": "Hejmo", @@ -110,7 +112,7 @@ "confirmations.delete.message": "Ĉu vi certas, ke vi volas forigi ĉi tiun mesaÄon?", "confirmations.delete_list.confirm": "Forigi", "confirmations.delete_list.message": "Ĉu vi certas, ke vi volas porĉiame forigi ĉi tiun liston?", - "confirmations.domain_block.confirm": "KaÅi la tutan domajnon", + "confirmations.domain_block.confirm": "Bloki la tutan domajnon", "confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas. Vi ne vidos enhavon de tiu domajno en publika tempolinio aÅ en viaj sciigoj. Viaj sekvantoj de tiu domajno estos forigitaj.", "confirmations.logout.confirm": "Elsaluti", "confirmations.logout.message": "Ĉu vi certas ke vi volas elsaluti?", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Serĉaj rezultoj", "emoji_button.symbols": "Simboloj", "emoji_button.travel": "VojaÄoj kaj lokoj", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Neniu mesaÄo ĉi tie!", "empty_column.account_unavailable": "Profilo ne disponebla", "empty_column.blocks": "Vi ankoraÅ ne blokis uzanton.", @@ -166,12 +169,14 @@ "empty_column.notifications": "Vi ankoraÅ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.", "empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aÅ mane sekvu uzantojn de aliaj serviloj por plenigi la publikan tempolinion", "error.unexpected_crash.explanation": "Pro eraro en nia kodo, aÅ problemo de kongruo en via retumilo, ĉi tiu paÄo ne povis esti montrata Äuste.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Provu refreÅigi la paÄon. Se tio ne helpas, vi ankoraÅ povus uzi Mastodon per malsama retumilo aÅ operaciuma aplikajo.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopii stakspuron en tondujo", "errors.unexpected_crash.report_issue": "Raporti problemon", "follow_request.authorize": "Rajtigi", "follow_request.reject": "Rifuzi", - "follow_requests.unlocked_explanation": "137/5000\nKvankam via konto ne estas Ålosita, la dungitaro de {domain} opiniis, ke vi eble volus revizii petojn de sekvadon el ĉi tiuj kontoj permane.", + "follow_requests.unlocked_explanation": "Kvankam via konto ne estas Ålosita, la dungitaro de {domain} opiniis, ke vi eble volus revizii petojn de sekvadon el ĉi tiuj kontoj permane.", "generic.saved": "Konservita", "getting_started.developers": "Programistoj", "getting_started.directory": "Profilujo", @@ -232,7 +237,7 @@ "keyboard_shortcuts.hotkey": "Rapidklavo", "keyboard_shortcuts.legend": "montri ĉi tiun noton", "keyboard_shortcuts.local": "malfermi la lokan tempolinion", - "keyboard_shortcuts.mention": "por mencii la aÅtoron", + "keyboard_shortcuts.mention": "mencii la aÅtoron", "keyboard_shortcuts.muted": "malfermi la liston de silentigitaj uzantoj", "keyboard_shortcuts.my_profile": "malfermi vian profilon", "keyboard_shortcuts.notifications": "malfermi la kolumnon de sciigoj", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "respondi", "keyboard_shortcuts.requests": "malfermi la liston de petoj de sekvado", "keyboard_shortcuts.search": "enfokusigi la serĉilon", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "montri/kaÅi la kampon de enhava averto", "keyboard_shortcuts.start": "malfermi la kolumnon «por komenci»", "keyboard_shortcuts.toggle_hidden": "montri/kaÅi tekston malantaÅ enhava averto", "keyboard_shortcuts.toggle_sensitivity": "montri/kaÅi aÅdovidaĵojn", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "malenfokusigi la tekstujon aÅ la serĉilon", "keyboard_shortcuts.up": "iri supren en la listo", "lightbox.close": "Fermi", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Sekva", "lightbox.previous": "AntaÅa", - "lightbox.view_context": "Vidi kuntekston", "lists.account.add": "Aldoni al la listo", "lists.account.remove": "Forigi de la listo", "lists.delete": "Forigi la liston", @@ -260,6 +266,10 @@ "lists.edit.submit": "ÅœanÄi titolon", "lists.new.create": "Aldoni liston", "lists.new.title_placeholder": "Titolo de la nova listo", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Montri respondon al:", "lists.search": "Serĉi inter la homoj, kiujn vi sekvas", "lists.subheading": "Viaj listoj", "load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Baskuligi videblecon", "missing_indicator.label": "Ne trovita", "missing_indicator.sublabel": "Ĉi tiu elemento ne estis trovita", + "mute_modal.duration": "DaÅro", "mute_modal.hide_notifications": "Ĉu vi volas kaÅi la sciigojn de ĉi tiu uzanto?", + "mute_modal.indefinite": "Nedifinita", "navigation_bar.apps": "Telefonaj aplikaĵoj", "navigation_bar.blocks": "Blokitaj uzantoj", "navigation_bar.bookmarks": "Legosignoj", @@ -275,7 +287,7 @@ "navigation_bar.compose": "Skribi novan mesaÄon", "navigation_bar.direct": "Rektaj mesaÄoj", "navigation_bar.discover": "Esplori", - "navigation_bar.domain_blocks": "KaÅitaj domajnoj", + "navigation_bar.domain_blocks": "Blokitaj domajnoj", "navigation_bar.edit_profile": "Redakti profilon", "navigation_bar.favourites": "Stelumoj", "navigation_bar.filters": "Silentigitaj vortoj", @@ -298,6 +310,7 @@ "notification.own_poll": "Via balotenketo finiÄitis", "notification.poll": "Partoprenita balotenketo finiÄis", "notification.reblog": "{name} diskonigis vian mesaÄon", + "notification.status": "{name} ĵus afiÅita", "notifications.clear": "ForviÅi sciigojn", "notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviÅi ĉiujn viajn sciigojn?", "notifications.column_settings.alert": "Retumilaj sciigoj", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Diskonigoj:", "notifications.column_settings.show": "Montri en kolumno", "notifications.column_settings.sound": "Eligi sonon", + "notifications.column_settings.status": "Novaj mesaÄoj:", "notifications.filter.all": "Ĉiuj", "notifications.filter.boosts": "Diskonigoj", "notifications.filter.favourites": "Stelumoj", "notifications.filter.follows": "Sekvoj", "notifications.filter.mentions": "Mencioj", "notifications.filter.polls": "Balotenketaj rezultoj", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} sciigoj", + "notifications.mark_as_read": "Marki ĉiujn sciigojn legita", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Ebligi retumilajn sciigojn", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Neniam preterlasas iun ajn", + "picture_in_picture.restore": "Put it back", "poll.closed": "Finita", "poll.refresh": "Aktualigi", "poll.total_people": "{count, plural, one {# homo} other {# homoj}}", @@ -329,13 +353,13 @@ "poll_button.add_poll": "Aldoni balotenketon", "poll_button.remove_poll": "Forigi balotenketon", "privacy.change": "Agordi mesaÄan privatecon", - "privacy.direct.long": "AfiÅi nur al menciitaj uzantoj", + "privacy.direct.long": "Videbla nur al menciitaj uzantoj", "privacy.direct.short": "Rekta", - "privacy.private.long": "AfiÅi nur al sekvantoj", - "privacy.private.short": "Nur por sekvantoj", - "privacy.public.long": "AfiÅi en publikaj tempolinioj", + "privacy.private.long": "Videbla nur al viaj sekvantoj", + "privacy.private.short": "Nur al sekvantoj", + "privacy.public.long": "Videbla al ĉiuj, afiÅita en publikaj tempolinioj", "privacy.public.short": "Publika", - "privacy.unlisted.long": "Ne afiÅi en publikaj tempolinioj", + "privacy.unlisted.long": "Videbla al ĉiuj, sed ne en publikaj tempolinioj", "privacy.unlisted.short": "Nelistigita", "refresh": "RefreÅigu", "regeneration_indicator.label": "Åœargado…", @@ -422,11 +446,11 @@ "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", "timeline_hint.resources.followers": "Sekvantoj", "timeline_hint.resources.follows": "Sekvatoj", - "timeline_hint.resources.statuses": "Pli malnovaj tootoj", + "timeline_hint.resources.statuses": "Pli malnovaj mesaÄoj", "trends.counter_by_accounts": "{count, plural, one {{counter} persono} other {{counter} personoj}} parolante", "trends.trending_now": "Nunaj furoraĵoj", "ui.beforeunload": "Via malneto perdiÄos se vi eliras de Mastodon.", - "units.short.billion": "{count}B", + "units.short.billion": "{count}Md", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Altreni kaj lasi por alÅuti", @@ -441,11 +465,12 @@ "upload_form.video_description": "Priskribi por homoj kiuj malfacile aÅdi aÅ vidi", "upload_modal.analyzing_picture": "Bilda analizado…", "upload_modal.apply": "Apliki", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Elekti bildon", "upload_modal.description_placeholder": "LaÅ Ludoviko Zamenhof bongustas freÅa ĉeÄ¥a manÄaĵo kun spicoj", "upload_modal.detect_text": "Detekti tekston de la bildo", "upload_modal.edit_media": "Redakti aÅdovidaĵon", "upload_modal.hint": "Klaku aÅ trenu la cirklon en la antaÅvidilo por elekti la fokuspunkton kiu ĉiam videblos en ĉiuj etigitaj bildoj.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "AntaÅvido ({ratio})", "upload_progress.label": "AlÅutado…", "video.close": "Fermi la videon", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index fda38645541c06bf3f3e797c9d0ecdcd6e4c38f7..434382e204a7d6a08515c844a6f679f0c236168a 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -1,16 +1,18 @@ { - "account.account_note_header": "Tu nota para @{name}", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Agregar o quitar de las listas", "account.badges.bot": "Bot", "account.badges.group": "Grupo", "account.block": "Bloquear a @{name}", - "account.block_domain": "Ocultar todo de {domain}", + "account.block_domain": "Bloquear dominio {domain}", "account.blocked": "Bloqueado", "account.browse_more_on_origin_server": "Explorar más en el perfil original", "account.cancel_follow_request": "Cancelar la solicitud de seguimiento", "account.direct": "Mensaje directo a @{name}", - "account.domain_blocked": "Dominio oculto", + "account.disable_notifications": "Dejar de notificarme cuando @{name} tootee", + "account.domain_blocked": "Dominio bloqueado", "account.edit_profile": "Editar perfil", + "account.enable_notifications": "Notificarme cuando @{name} tootee", "account.endorse": "Destacar en el perfil", "account.follow": "Seguir", "account.followers": "Seguidores", @@ -25,27 +27,27 @@ "account.locked_info": "El estado de privacidad de esta cuenta está establecido como bloqueado. El propietario manualmente revisa quién puede seguirle.", "account.media": "Medios", "account.mention": "Mencionar a @{name}", - "account.moved_to": "{name} se ha muó a:", + "account.moved_to": "{name} se ha mudó a:", "account.mute": "Silenciar a @{name}", "account.mute_notifications": "Silenciar notificaciones de @{name}", "account.muted": "Silenciado", "account.never_active": "Nunca", "account.posts": "Toots", - "account.posts_with_replies": "Toots con respuestas", + "account.posts_with_replies": "Toots y respuestas", "account.report": "Denunciar a @{name}", - "account.requested": "Esperando aprobación. Hacé clic para cancelar la solicitud de seguimiento.", + "account.requested": "Esperando aprobación. Hacé clic para cancelar la solicitud de seguimiento", "account.share": "Compartir el perfil de @{name}", "account.show_reblogs": "Mostrar retoots de @{name}", "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", "account.unblock": "Desbloquear a @{name}", - "account.unblock_domain": "Mostrar {domain}", + "account.unblock_domain": "Desbloquear dominio {domain}", "account.unendorse": "No destacar en el perfil", "account.unfollow": "Dejar de seguir", "account.unmute": "Dejar de silenciar a @{name}", "account.unmute_notifications": "Dejar de silenciar las notificaciones de @{name}", - "account_note.placeholder": "No se ofreció ningún comentario", + "account_note.placeholder": "Hacé clic par agregar una nota", "alert.rate_limited.message": "Por favor, reintentá después de las {retry_time, time, medium}.", - "alert.rate_limited.title": "Tarifa limitada", + "alert.rate_limited.title": "Acción limitada", "alert.unexpected.message": "Ocurrió un error.", "alert.unexpected.title": "¡Epa!", "announcement.announcement": "Anuncio", @@ -62,7 +64,7 @@ "column.community": "LÃnea temporal local", "column.direct": "Mensajes directos", "column.directory": "Explorar perfiles", - "column.domain_blocks": "Dominios ocultos", + "column.domain_blocks": "Dominios bloqueados", "column.favourites": "Favoritos", "column.follow_requests": "Solicitudes de seguimiento", "column.home": "Principal", @@ -85,19 +87,19 @@ "compose_form.direct_message_warning": "Este toot sólo será enviado a los usuarios mencionados.", "compose_form.direct_message_warning_learn_more": "Aprendé más", "compose_form.hashtag_warning": "Este toot no se mostrará bajo hashtags porque no es público. Sólo los toots públicos se pueden buscar por hashtag.", - "compose_form.lock_disclaimer": "Tu cuenta no está {locked}. Todos pueden seguirte para ver tus toots marcados como \"sólo para seguidores\".", + "compose_form.lock_disclaimer": "Tu cuenta no está {locked}. Todos pueden seguirte para ver tus toots marcados como \"Sólo para seguidores\".", "compose_form.lock_disclaimer.lock": "bloqueada", "compose_form.placeholder": "¿Qué onda?", "compose_form.poll.add_option": "Agregá una opción", "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.remove_option": "Quitá esta opción", + "compose_form.poll.remove_option": "Quitar esta opción", "compose_form.poll.switch_to_multiple": "Cambiar encuesta para permitir opciones múltiples", "compose_form.poll.switch_to_single": "Cambiar encuesta para permitir una sola opción", "compose_form.publish": "Tootear", "compose_form.publish_loud": "¡{publish}!", "compose_form.sensitive.hide": "Marcar medio como sensible", - "compose_form.sensitive.marked": "El medio se marcó como sensible", + "compose_form.sensitive.marked": "{count, plural, one {El medio está marcado como sensible} other {Los medios están marcados como sensibles}}", "compose_form.sensitive.unmarked": "El medio no está marcado como sensible", "compose_form.spoiler.marked": "El texto está oculto detrás de la advertencia", "compose_form.spoiler.unmarked": "El texto no está oculto", @@ -107,10 +109,10 @@ "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "¿Estás seguro que querés bloquear a {name}?", "confirmations.delete.confirm": "Eliminar", - "confirmations.delete.message": "¿Estás seguro que querés eliminar este estado?", + "confirmations.delete.message": "¿Estás seguro que querés eliminar este toot?", "confirmations.delete_list.confirm": "Eliminar", "confirmations.delete_list.message": "¿Estás seguro que querés eliminar permanentemente esta lista?", - "confirmations.domain_block.confirm": "Ocultar dominio entero", + "confirmations.domain_block.confirm": "Bloquear dominio entero", "confirmations.domain_block.message": "¿Estás completamente seguro que querés bloquear el {domain} entero? En la mayorÃa de los casos, unos cuantos bloqueos y silenciados puntuales son suficientes y preferibles. No vas a ver contenido de ese dominio en ninguna de tus lÃneas temporales o en tus notificaciones. Tus seguidores de ese dominio serán quitados.", "confirmations.logout.confirm": "Cerrar sesión", "confirmations.logout.message": "¿Estás seguro que querés cerrar la sesión?", @@ -118,19 +120,19 @@ "confirmations.mute.explanation": "Se ocultarán los mensajes de esta cuenta y los mensajes de otras cuentas que mencionen a ésta, pero todavÃa esta cuenta podrá ver tus mensajes o seguirte.", "confirmations.mute.message": "¿Estás seguro que querés silenciar a {name}?", "confirmations.redraft.confirm": "Eliminar toot original y editarlo", - "confirmations.redraft.message": "¿Estás seguro que querés eliminar este estado y volver a editarlo? Se perderán las veces marcadas como favoritos y los retoots, y las respuestas a la publicación original quedarán huérfanas.", + "confirmations.redraft.message": "¿Estás seguro que querés eliminar este toot y volver a editarlo? Se perderán las veces marcadas como favoritos y los retoots, y las respuestas a la publicación original quedarán huérfanas.", "confirmations.reply.confirm": "Responder", "confirmations.reply.message": "Responder ahora sobreescribirá el mensaje que estás redactando actualmente. ¿Estás seguro que querés seguir?", "confirmations.unfollow.confirm": "Dejar de seguir", "confirmations.unfollow.message": "¿Estás seguro que querés dejar de seguir a {name}?", "conversation.delete": "Eliminar conversación", - "conversation.mark_as_read": "Marcar como leÃdo", + "conversation.mark_as_read": "Marcar como leÃda", "conversation.open": "Ver conversación", "conversation.with": "Con {names}", "directory.federated": "Desde fediverso conocido", "directory.local": "Sólo de {domain}", "directory.new_arrivals": "Recién llegados", - "directory.recently_active": "Recientemente activo", + "directory.recently_active": "Recientemente activos", "embed.instructions": "Insertá este toot a tu sitio web copiando el código de abajo.", "embed.preview": "Asà es cómo se verá:", "emoji_button.activity": "Actividad", @@ -143,17 +145,18 @@ "emoji_button.objects": "Objetos", "emoji_button.people": "Gente", "emoji_button.recent": "Usados frecuentemente", - "emoji_button.search": "Buscar…", + "emoji_button.search": "Buscar...", "emoji_button.search_results": "Resultados de búsqueda", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viajes y lugares", - "empty_column.account_timeline": "¡No hay toots aquÃ!", + "empty_column.account_suspended": "Cuenta suspendida", + "empty_column.account_timeline": "¡No hay toots acá!", "empty_column.account_unavailable": "Perfil no disponible", "empty_column.blocks": "TodavÃa no bloqueaste a ningún usuario.", - "empty_column.bookmarked_statuses": "TodavÃa no tenés toots guardados en marcadores. Cuando guardés uno en marcadores, se mostrará acá.", + "empty_column.bookmarked_statuses": "TodavÃa no tenés toots guardados en \"Marcadores\". Cuando guardés uno en \"Marcadores\", se mostrará acá.", "empty_column.community": "La lÃnea temporal local está vacÃa. ¡Escribà algo en modo público para que se empiece a correr la bola!", "empty_column.direct": "TodavÃa no tenés ningún mensaje directo. Cuando enviés o recibás uno, se mostrará acá.", - "empty_column.domain_blocks": "TodavÃa no hay dominios ocultos.", + "empty_column.domain_blocks": "TodavÃa no hay dominios bloqueados.", "empty_column.favourited_statuses": "TodavÃa no tenés toots favoritos. Cuando marqués uno como favorito, se mostrará acá.", "empty_column.favourites": "TodavÃa nadie marcó este toot como favorito. Cuando alguien lo haga, se mostrará acá.", "empty_column.follow_requests": "TodavÃa no tenés ninguna solicitud de seguimiento. Cuando recibás una, se mostrará acá.", @@ -161,12 +164,14 @@ "empty_column.home": "¡Tu lÃnea temporal principal está vacÃa! Visitá {public} o usá la búsqueda para comenzar y encontrar a otros usuarios.", "empty_column.home.public_timeline": "la lÃnea temporal pública", "empty_column.list": "TodavÃa no hay nada en esta lista. Cuando miembros de esta lista envÃen nuevos toots, se mostrarán acá.", - "empty_column.lists": "TodavÃa no tienes ninguna lista. Cuando creés una, se mostrará acá.", + "empty_column.lists": "TodavÃa no tenés ninguna lista. Cuando creés una, se mostrará acá.", "empty_column.mutes": "TodavÃa no silenciaste a ningún usuario.", "empty_column.notifications": "TodavÃa no tenés ninguna notificación. Interactuá con otros para iniciar la conversación.", - "empty_column.public": "¡Naranja! Escribà algo públicamente, o seguà usuarios manualmente de otros servidores para ir llenando esta lÃnea temporal.", + "empty_column.public": "¡Naranja! Escribà algo públicamente, o seguà usuarios manualmente de otros servidores para ir llenando esta lÃnea temporal", "error.unexpected_crash.explanation": "Debido a un error en nuestro código o a un problema de compatibilidad con el navegador web, esta página no se pudo mostrar correctamente.", + "error.unexpected_crash.explanation_addons": "No se pudo mostrar correctamente esta página. Este error probablemente es causado por un complemento del navegador web o por herramientas de traducción automática.", "error.unexpected_crash.next_steps": "Intentá recargar la página. Si eso no ayuda, podés usar Mastodon a través de un navegador web diferente o aplicación nativa.", + "error.unexpected_crash.next_steps_addons": "Intentá deshabilitarlos y recargá la página. Si eso no ayuda, podés usar Mastodon a través de un navegador web diferente o aplicación nativa.", "errors.unexpected_crash.copy_stacktrace": "Copiar stacktrace al portapapeles", "errors.unexpected_crash.report_issue": "Informar problema", "follow_request.authorize": "Autorizar", @@ -177,9 +182,9 @@ "getting_started.directory": "Directorio de perfiles", "getting_started.documentation": "Documentación", "getting_started.heading": "Introducción", - "getting_started.invite": "Invitar usuarios", + "getting_started.invite": "Invitar gente", "getting_started.open_source_notice": "Mastodon es software libre. Podés contribuir o informar errores en {github}.", - "getting_started.security": "Seguridad", + "getting_started.security": "Configuración de la cuenta", "getting_started.terms": "Términos del servicio", "hashtag.column_header.tag_mode.all": "y {additional}", "hashtag.column_header.tag_mode.any": "o {additional}", @@ -199,31 +204,31 @@ "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", "introduction.federation.action": "Siguiente", - "introduction.federation.federated.headline": "Federado", + "introduction.federation.federated.headline": "Federada", "introduction.federation.federated.text": "Los toots públicos de otros servidores del fediverso aparecerán en la lÃnea temporal federada.", "introduction.federation.home.headline": "Principal", - "introduction.federation.home.text": "Los toots de las personas que seguÃs aparecerán en tu lÃnea temporal principal. ¡Podés seguir a cualquiera en cualquier servidor!", + "introduction.federation.home.text": "Los toots de las cuentas que seguÃs aparecerán en tu lÃnea temporal principal. ¡Podés seguir a cualquiera en cualquier servidor!", "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Los toots públicos de las personas en el mismo servidor aparecerán en la lÃnea temporal local.", + "introduction.federation.local.text": "Los toots públicos de las cuentas en el mismo servidor aparecerán en la lÃnea temporal local.", "introduction.interactions.action": "¡Terminar tutorial!", - "introduction.interactions.favourite.headline": "Favorito", + "introduction.interactions.favourite.headline": "Favoritos", "introduction.interactions.favourite.text": "Podés guardar un toot para más tarde, y hacerle saber al autor que te gustó, marcándolo como favorito.", "introduction.interactions.reblog.headline": "Retootear", - "introduction.interactions.reblog.text": "Podés compartir los toots de otras personas con tus seguidores retooteando los mismos.", + "introduction.interactions.reblog.text": "Podés compartir los toots de otras cuentas con tus seguidores retooteando los mismos.", "introduction.interactions.reply.headline": "Responder", - "introduction.interactions.reply.text": "Podés responder a tus propios toots y los de otras personas, que se encadenarán juntos en una conversación.", + "introduction.interactions.reply.text": "Podés responder a tus propios toots y los de otras cuentas, que se encadenarán juntos en una conversación.", "introduction.welcome.action": "¡Dale!", "introduction.welcome.headline": "Primeros pasos", "introduction.welcome.text": "¡Bienvenido al fediverso! En unos pocos minutos, vas a poder transmitir mensajes y hablar con tus amigos a través de una amplia variedad de servidores. Pero este servidor, {domain}, es especial: aloja tu perfil, asà que acordate de su nombre.", "keyboard_shortcuts.back": "para volver", "keyboard_shortcuts.blocked": "para abrir la lista de usuarios bloqueados", "keyboard_shortcuts.boost": "para retootear", - "keyboard_shortcuts.column": "para enfocar un estado en una de las columnas", + "keyboard_shortcuts.column": "para enfocar un toot en una de las columnas", "keyboard_shortcuts.compose": "para enfocar el área de texto de redacción", "keyboard_shortcuts.description": "Descripción", "keyboard_shortcuts.direct": "para abrir columna de mensajes directos", "keyboard_shortcuts.down": "para bajar en la lista", - "keyboard_shortcuts.enter": "para abrir el estado", + "keyboard_shortcuts.enter": "para abrir el toot", "keyboard_shortcuts.favourite": "para marcar como favorito", "keyboard_shortcuts.favourites": "para abrir la lista de favoritos", "keyboard_shortcuts.federated": "para abrir la lÃnea temporal federada", @@ -233,11 +238,11 @@ "keyboard_shortcuts.legend": "para mostrar este texto", "keyboard_shortcuts.local": "para abrir la lÃnea temporal local", "keyboard_shortcuts.mention": "para mencionar al autor", - "keyboard_shortcuts.muted": "abrir la lista de usuarios silenciados", + "keyboard_shortcuts.muted": "para abrir la lista de usuarios silenciados", "keyboard_shortcuts.my_profile": "para abrir tu perfil", "keyboard_shortcuts.notifications": "para abrir la columna de notificaciones", - "keyboard_shortcuts.open_media": "para abrir archivos de medios", - "keyboard_shortcuts.pinned": "para abrir lista de toots fijados", + "keyboard_shortcuts.open_media": "para abrir los archivos de medios", + "keyboard_shortcuts.pinned": "para abrir la lista de toots fijados", "keyboard_shortcuts.profile": "para abrir el perfil del autor", "keyboard_shortcuts.reply": "para responder", "keyboard_shortcuts.requests": "para abrir la lista de solicitudes de seguimiento", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "para quitar el enfoque del área de texto de redacción o de búsqueda", "keyboard_shortcuts.up": "para subir en la lista", "lightbox.close": "Cerrar", + "lightbox.compress": "Comprimir cuadro de vista de imagen", + "lightbox.expand": "Expandir cuadro de vista de imagen", "lightbox.next": "Siguiente", "lightbox.previous": "Anterior", - "lightbox.view_context": "Ver contexto", "lists.account.add": "Agregar a lista", "lists.account.remove": "Quitar de lista", "lists.delete": "Eliminar lista", @@ -260,14 +266,20 @@ "lists.edit.submit": "Cambiar tÃtulo", "lists.new.create": "Agregar lista", "lists.new.title_placeholder": "Nuevo tÃtulo de lista", + "lists.replies_policy.followed": "Cualquier cuenta seguida", + "lists.replies_policy.list": "Miembros de la lista", + "lists.replies_policy.none": "Nadie", + "lists.replies_policy.title": "Mostrar respuestas a:", "lists.search": "Buscar entre la gente que seguÃs", "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", - "loading_indicator.label": "Cargando…", - "media_gallery.toggle_visible": "Cambiar visibilidad", + "loading_indicator.label": "Cargando...", + "media_gallery.toggle_visible": "Ocultar {number, plural, one {imagen} other {imágenes}}", "missing_indicator.label": "No se encontró", "missing_indicator.sublabel": "No se encontró este recurso", + "mute_modal.duration": "Duración", "mute_modal.hide_notifications": "¿Querés ocultar las notificaciones de este usuario?", + "mute_modal.indefinite": "Indefinida", "navigation_bar.apps": "Aplicaciones móviles", "navigation_bar.blocks": "Usuarios bloqueados", "navigation_bar.bookmarks": "Marcadores", @@ -275,12 +287,12 @@ "navigation_bar.compose": "Redactar un nuevo toot", "navigation_bar.direct": "Mensajes directos", "navigation_bar.discover": "Descubrir", - "navigation_bar.domain_blocks": "Dominios ocultos", + "navigation_bar.domain_blocks": "Dominios bloqueados", "navigation_bar.edit_profile": "Editar perfil", "navigation_bar.favourites": "Favoritos", "navigation_bar.filters": "Palabras silenciadas", "navigation_bar.follow_requests": "Solicitudes de seguimiento", - "navigation_bar.follows_and_followers": "Personas seguidas y seguidores", + "navigation_bar.follows_and_followers": "Cuentas seguidas y seguidores", "navigation_bar.info": "Acerca de este servidor", "navigation_bar.keyboard_shortcuts": "Atajos", "navigation_bar.lists": "Listas", @@ -291,13 +303,14 @@ "navigation_bar.preferences": "Configuración", "navigation_bar.public_timeline": "LÃnea temporal federada", "navigation_bar.security": "Seguridad", - "notification.favourite": "{name} marcó tu estado como favorito", + "notification.favourite": "{name} marcó tu toot como favorito", "notification.follow": "{name} te empezó a seguir", "notification.follow_request": "{name} solicitó seguirte", "notification.mention": "{name} te mencionó", "notification.own_poll": "Tu encuesta finalizó", "notification.poll": "Finalizó una encuesta en la que votaste", "notification.reblog": "{name} retooteó tu estado", + "notification.status": "{name} acaba de tootear", "notifications.clear": "Limpiar notificaciones", "notifications.clear_confirmation": "¿Estás seguro que querés limpiar todas tus notificaciones permanentemente?", "notifications.column_settings.alert": "Notificaciones de escritorio", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Retoots:", "notifications.column_settings.show": "Mostrar en columna", "notifications.column_settings.sound": "Reproducir sonido", + "notifications.column_settings.status": "Nuevos toots:", "notifications.filter.all": "Todas", "notifications.filter.boosts": "Retoots", "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguidores", "notifications.filter.mentions": "Menciones", - "notifications.filter.polls": "Resultados de la encuesta", + "notifications.filter.polls": "Resultados de encuesta", + "notifications.filter.statuses": "Actualizaciones de cuentas que seguÃs", + "notifications.grant_permission": "Conceder permiso.", "notifications.group": "{count} notificaciones", + "notifications.mark_as_read": "Marcar cada notificación como leÃda", + "notifications.permission_denied": "Las notificaciones de escritorio no están disponibles, debido a una solicitud de permiso del navegador web previamente denegada", + "notifications.permission_denied_alert": "No se pueden habilitar las notificaciones de escritorio, ya que el permiso del navegador fue denegado antes", + "notifications.permission_required": "Las notificaciones de escritorio no están disponibles porque no se concedió el permiso requerido.", + "notifications_permission_banner.enable": "Habilitar notificaciones de escritorio", + "notifications_permission_banner.how_to_control": "Para recibir notificaciones cuando Mastodon no está abierto, habilitá las notificaciones de escritorio. Podés controlar con precisión qué tipos de interacciones generan notificaciones de escritorio a través del botón {icon} de arriba, una vez que estén habilitadas.", + "notifications_permission_banner.title": "No te pierdas nada", + "picture_in_picture.restore": "Restaurar", "poll.closed": "Cerrada", "poll.refresh": "Refrescar", "poll.total_people": "{count, plural, one {# persona} other {# personas}}", @@ -328,14 +352,14 @@ "poll.voted": "Votaste esta opción", "poll_button.add_poll": "Agregar una encuesta", "poll_button.remove_poll": "Quitar encuesta", - "privacy.change": "Configurar privacidad de estado", - "privacy.direct.long": "Enviar toot sólo a los usuarios mencionados", + "privacy.change": "Configurar privacidad de toot", + "privacy.direct.long": "Visible sólo a los usuarios mencionados", "privacy.direct.short": "Directo", - "privacy.private.long": "Enviar toot sólo a los seguidores", + "privacy.private.long": "Visible sólo a los seguidores", "privacy.private.short": "Sólo a seguidores", - "privacy.public.long": "Enviar toot a las lÃneas temporales públicas", + "privacy.public.long": "Visible para todos, mostrado en las lÃneas temporales públicas", "privacy.public.short": "Público", - "privacy.unlisted.long": "No enviar toot a las lÃneas temporales públicas", + "privacy.unlisted.long": "Visible para todos, pero no en las lÃneas temporales públicas", "privacy.unlisted.short": "No listado", "refresh": "Refrescar", "regeneration_indicator.label": "Cargando…", @@ -355,28 +379,28 @@ "report.target": "Denunciando a {target}", "search.placeholder": "Buscar", "search_popout.search_format": "Formato de búsqueda avanzada", - "search_popout.tips.full_text": "Las búsquedas de texto simple devuelven los estados que escribiste, los marcados como favoritos, los retooteados o en los que te mencionaron, asà como nombres usuarios, nombres mostrados y etiquetas.", + "search_popout.tips.full_text": "Las búsquedas de texto simple devuelven los toots que escribiste, los marcados como favoritos, los retooteados o en los que te mencionaron, asà como nombres de usuarios, nombres mostrados y etiquetas.", "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estado", + "search_popout.tips.status": "toot", "search_popout.tips.text": "Las búsquedas de texto simple devuelven nombres de usuarios, nombres mostrados y etiquetas que coincidan", "search_popout.tips.user": "usuario", "search_results.accounts": "Gente", "search_results.hashtags": "Etiquetas", "search_results.statuses": "Toots", - "search_results.statuses_fts_disabled": "No se puede buscar toots por contenido en este servidor de Mastodon.", + "search_results.statuses_fts_disabled": "No se pueden buscar toots por contenido en este servidor de Mastodon.", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "status.admin_account": "Abrir interface de moderación para @{name}", - "status.admin_status": "Abrir este estado en la interface de moderación", + "status.admin_status": "Abrir este toot en la interface de moderación", "status.block": "Bloquear a @{name}", - "status.bookmark": "Marcador", + "status.bookmark": "Marcar", "status.cancel_reblog_private": "Quitar retoot", "status.cannot_reblog": "No se puede retootear este toot", - "status.copy": "Copiar enlace al estado", + "status.copy": "Copiar enlace al toot", "status.delete": "Eliminar", "status.detailed_status": "Vista de conversación detallada", "status.direct": "Mensaje directo a @{name}", "status.embed": "Insertar", - "status.favourite": "Favorito", + "status.favourite": "Marcar como favorito", "status.filtered": "Filtrado", "status.load_more": "Cargar más", "status.media_hidden": "Medios ocultos", @@ -384,10 +408,10 @@ "status.more": "Más", "status.mute": "Silenciar a @{name}", "status.mute_conversation": "Silenciar conversación", - "status.open": "Expandir este estado", + "status.open": "Expandir este toot", "status.pin": "Fijar en el perfil", "status.pinned": "Toot fijado", - "status.read_more": "Leer más", + "status.read_more": "Leé más", "status.reblog": "Retootear", "status.reblog_private": "Retootear a la audiencia original", "status.reblogged_by": "{name} retooteó", @@ -409,7 +433,7 @@ "status.unpin": "Dejar de fijar", "suggestions.dismiss": "Descartar sugerencia", "suggestions.header": "Es posible que te interese…", - "tabs_bar.federated_timeline": "Federado", + "tabs_bar.federated_timeline": "Federada", "tabs_bar.home": "Principal", "tabs_bar.local_timeline": "Local", "tabs_bar.notifications": "Notificaciones", @@ -430,15 +454,15 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}mil", "upload_area.title": "Para subir, arrastrá y soltá", - "upload_button.label": "Agregar medios ({formats})", + "upload_button.label": "Agregá imágenes o un archivo de audio o video", "upload_error.limit": "Se excedió el lÃmite de subida de archivos.", "upload_error.poll": "No se permite la subida de archivos en encuestas.", - "upload_form.audio_description": "Describir para personas con problemas auditivos", - "upload_form.description": "Agregar descripción para los usuarios con dificultades visuales", + "upload_form.audio_description": "Agregá una descripción para personas con dificultades auditivas", + "upload_form.description": "Agregá una descripción para personas con dificultades visuales", "upload_form.edit": "Editar", "upload_form.thumbnail": "Cambiar miniatura", "upload_form.undo": "Eliminar", - "upload_form.video_description": "Describir para personas con problemas auditivos o visuales", + "upload_form.video_description": "Agregá una descripción para personas con dificultades auditivas o visuales", "upload_modal.analyzing_picture": "Analizando imagen…", "upload_modal.apply": "Aplicar", "upload_modal.choose_image": "Elegir imagen", @@ -446,12 +470,13 @@ "upload_modal.detect_text": "Detectar texto de la imagen", "upload_modal.edit_media": "Editar medio", "upload_modal.hint": "Hacé clic o arrastrá el cÃrculo en la previsualización para elegir el punto focal que siempre estará a la vista en todas las miniaturas.", + "upload_modal.preparing_ocr": "Preparando OCR…", "upload_modal.preview_label": "Previsualización ({ratio})", - "upload_progress.label": "Subiendo…", + "upload_progress.label": "Subiendo...", "video.close": "Cerrar video", "video.download": "Descargar archivo", "video.exit_fullscreen": "Salir de pantalla completa", - "video.expand": "Expandir vÃdeo", + "video.expand": "Expandir video", "video.fullscreen": "Pantalla completa", "video.hide": "Ocultar video", "video.mute": "Silenciar sonido", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index c0615d7579c7eaae9d1de460edda99456bb065ce..dfad44c6d68f63c9bcca11ede0e9958fbb9c374f 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Ver más en el perfil original", "account.cancel_follow_request": "Cancelar la solicitud de seguimiento", "account.direct": "Mensaje directo a @{name}", + "account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo", "account.domain_blocked": "Dominio oculto", "account.edit_profile": "Editar perfil", + "account.enable_notifications": "Notificarme cuando @{name} publique algo", "account.endorse": "Mostrar en perfil", "account.follow": "Seguir", "account.followers": "Seguidores", @@ -118,7 +120,7 @@ "confirmations.mute.explanation": "Esto esconderá las publicaciones de ellos y en las que los has mencionado, pero les permitirá ver tus mensajes y seguirte.", "confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?", "confirmations.redraft.confirm": "Borrar y volver a borrador", - "confirmations.redraft.message": "Estás seguro de que quieres borrar este estado y volverlo a borrador? Perderás todas las respuestas, impulsos y favoritos asociados a él, y las respuestas a la publicación original quedarán huérfanos.", + "confirmations.redraft.message": "¿Estás seguro de que quieres eliminar este toot y convertirlo en borrador? Perderás todas las respuestas, retoots y favoritos asociados a él, y las respuestas a la publicación original quedarán huérfanas.", "confirmations.reply.confirm": "Responder", "confirmations.reply.message": "Responder sobrescribirá el mensaje que estás escribiendo. ¿Estás seguro de que deseas continuar?", "confirmations.unfollow.confirm": "Dejar de seguir", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultados de búsqueda", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viajes y lugares", + "empty_column.account_suspended": "Cuenta suspendida", "empty_column.account_timeline": "¡No hay toots aquÃ!", "empty_column.account_unavailable": "Perfil no disponible", "empty_column.blocks": "Aún no has bloqueado a ningún usuario.", @@ -166,7 +169,9 @@ "empty_column.notifications": "No tienes ninguna notificación aún. Interactúa con otros para empezar una conversación.", "empty_column.public": "¡No hay nada aquÃ! Escribe algo públicamente, o sigue usuarios de otras instancias manualmente para llenarlo", "error.unexpected_crash.explanation": "Debido a un error en nuestro código o a un problema de compatibilidad con el navegador, esta página no se ha podido mostrar correctamente.", + "error.unexpected_crash.explanation_addons": "No se pudo mostrar correctamente esta página. Este error probablemente fue causado por un complemento del navegador web o por herramientas de traducción automática.", "error.unexpected_crash.next_steps": "Intenta actualizar la página. Si eso no ayuda, es posible que puedas usar Mastodon a través de otro navegador o aplicación nativa.", + "error.unexpected_crash.next_steps_addons": "Intenta deshabilitarlos y recarga la página. Si eso no ayuda, podrÃas usar Mastodon a través de un navegador web diferente o aplicación nativa.", "errors.unexpected_crash.copy_stacktrace": "Copiar el seguimiento de pila en el portapapeles", "errors.unexpected_crash.report_issue": "Informar de un problema/error", "follow_request.authorize": "Autorizar", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda", "keyboard_shortcuts.up": "para ir hacia arriba en la lista", "lightbox.close": "Cerrar", + "lightbox.compress": "Comprimir cuadro de visualización de imagen", + "lightbox.expand": "Expandir cuadro de visualización de imagen", "lightbox.next": "Siguiente", "lightbox.previous": "Anterior", - "lightbox.view_context": "Ver contexto", "lists.account.add": "Añadir a lista", "lists.account.remove": "Quitar de lista", "lists.delete": "Borrar lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Cambiar tÃtulo", "lists.new.create": "Añadir lista", "lists.new.title_placeholder": "TÃtulo de la nueva lista", + "lists.replies_policy.followed": "Cualquier usuario seguido", + "lists.replies_policy.list": "Miembros de la lista", + "lists.replies_policy.none": "Nadie", + "lists.replies_policy.title": "Mostrar respuestas a:", "lists.search": "Buscar entre la gente a la que sigues", "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Cambiar visibilidad", "missing_indicator.label": "No encontrado", "missing_indicator.sublabel": "No se encontró este recurso", + "mute_modal.duration": "Duración", "mute_modal.hide_notifications": "Ocultar notificaciones de este usuario?", + "mute_modal.indefinite": "Indefinida", "navigation_bar.apps": "Aplicaciones móviles", "navigation_bar.blocks": "Usuarios bloqueados", "navigation_bar.bookmarks": "Marcadores", @@ -298,6 +310,7 @@ "notification.own_poll": "Tu encuesta ha terminado", "notification.poll": "Una encuesta en la que has votado ha terminado", "notification.reblog": "{name} ha retooteado tu estado", + "notification.status": "{name} acaba de publicar", "notifications.clear": "Limpiar notificaciones", "notifications.clear_confirmation": "¿Seguro que quieres limpiar permanentemente todas tus notificaciones?", "notifications.column_settings.alert": "Notificaciones de escritorio", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Retoots:", "notifications.column_settings.show": "Mostrar en columna", "notifications.column_settings.sound": "Reproducir sonido", + "notifications.column_settings.status": "Nuevos toots:", "notifications.filter.all": "Todos", "notifications.filter.boosts": "Retoots", "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguidores", "notifications.filter.mentions": "Menciones", "notifications.filter.polls": "Resultados de la votación", + "notifications.filter.statuses": "Actualizaciones de gente a la que sigues", + "notifications.grant_permission": "Conceder permiso.", "notifications.group": "{count} notificaciones", + "notifications.mark_as_read": "Marcar todas las notificaciones como leÃdas", + "notifications.permission_denied": "No se pueden habilitar las notificaciones de escritorio ya que se denegó el permiso.", + "notifications.permission_denied_alert": "No se pueden habilitar las notificaciones de escritorio, ya que el permiso del navegador fue denegado anteriormente", + "notifications.permission_required": "Las notificaciones de escritorio no están disponibles porque no se ha concedido el permiso requerido.", + "notifications_permission_banner.enable": "Habilitar notificaciones de escritorio", + "notifications_permission_banner.how_to_control": "Para recibir notificaciones cuando Mastodon no esté abierto, habilite las notificaciones de escritorio. Puedes controlar con precisión qué tipos de interacciones generan notificaciones de escritorio a través del botón {icon} de arriba una vez que estén habilitadas.", + "notifications_permission_banner.title": "Nunca te pierdas nada", + "picture_in_picture.restore": "Restaurar", "poll.closed": "Cerrada", "poll.refresh": "Actualizar", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -357,7 +381,7 @@ "search_popout.search_format": "Formato de búsqueda avanzada", "search_popout.tips.full_text": "Búsquedas de texto recuperan posts que has escrito, marcado como favoritos, retooteado o en los que has sido mencionado, asà como usuarios, nombres y hashtags.", "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estado", + "search_popout.tips.status": "toot", "search_popout.tips.text": "El texto simple devuelve correspondencias de nombre, usuario y hashtag", "search_popout.tips.user": "usuario", "search_results.accounts": "Gente", @@ -368,8 +392,8 @@ "status.admin_account": "Abrir interfaz de moderación para @{name}", "status.admin_status": "Abrir este estado en la interfaz de moderación", "status.block": "Bloquear a @{name}", - "status.bookmark": "Marcador", - "status.cancel_reblog_private": "Des-impulsar", + "status.bookmark": "Añadir marcador", + "status.cancel_reblog_private": "Eliminar retoot", "status.cannot_reblog": "Este toot no puede retootearse", "status.copy": "Copiar enlace al estado", "status.delete": "Borrar", @@ -391,7 +415,7 @@ "status.reblog": "Retootear", "status.reblog_private": "Implusar a la audiencia original", "status.reblogged_by": "Retooteado por {name}", - "status.reblogs.empty": "Nadie impulsó este toot todavÃa. Cuando alguien lo haga, aparecerá aqui.", + "status.reblogs.empty": "Nadie retooteó este toot todavÃa. Cuando alguien lo haga, aparecerá aquÃ.", "status.redraft": "Borrar y volver a borrador", "status.remove_bookmark": "Eliminar marcador", "status.reply": "Responder", @@ -403,7 +427,7 @@ "status.show_less_all": "Mostrar menos para todo", "status.show_more": "Mostrar más", "status.show_more_all": "Mostrar más para todo", - "status.show_thread": "Ver hilo", + "status.show_thread": "Mostrar hilo", "status.uncached_media_warning": "No disponible", "status.unmute_conversation": "Dejar de silenciar conversación", "status.unpin": "Dejar de fijar", @@ -426,9 +450,9 @@ "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} personas}} hablando", "trends.trending_now": "Tendencia ahora", "ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.", - "units.short.billion": "{count}MM", + "units.short.billion": "{count}B", "units.short.million": "{count}M", - "units.short.thousand": "{count}mil", + "units.short.thousand": "{count}K", "upload_area.title": "Arrastra y suelta para subir", "upload_button.label": "Subir multimedia (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "LÃmite de subida de archivos excedido.", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detectar texto de la imagen", "upload_modal.edit_media": "Editar multimedia", "upload_modal.hint": "Haga clic o arrastre el cÃrculo en la vista previa para elegir el punto focal que siempre estará a la vista en todas las miniaturas.", + "upload_modal.preparing_ocr": "Preparando OCR…", "upload_modal.preview_label": "Vista previa ({ratio})", "upload_progress.label": "Subiendo…", "video.close": "Cerrar video", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 558fe38de259012796fcb3ad141c3840eac671ab..54f4159fe3982125fc11d6c5a9e1e708ea1f2d96 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Tühista jälgimistaotlus", "account.direct": "Otsesõnum @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domeen peidetud", "account.edit_profile": "Muuda profiili", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Too profiilil esile", "account.follow": "Jälgi", "account.followers": "Jälgijad", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Otsitulemused", "emoji_button.symbols": "Sümbolid", "emoji_button.travel": "Reisimine & Kohad", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Siin tuute ei ole!", "empty_column.account_unavailable": "Profiil pole saadaval", "empty_column.blocks": "Sa ei ole veel ühtegi kasutajat blokeerinud.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Teil ei ole veel teateid. Suhelge teistega alustamaks vestlust.", "empty_column.public": "Siin pole midagi! Kirjuta midagi avalikut või jälgi ise kasutajaid täitmaks seda ruumi", "error.unexpected_crash.explanation": "Meie poolse probleemi või veebilehitseja ühilduvus probleemi tõttu ei suutnud me Teile seda lehekülge korrektselt näidata.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Proovige lehekülge uuesti avada. Kui see ei aita, võite proovida kasutada Mastodoni mõne muu veebilehitseja või äppi kaudu.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopeeri stacktrace lõikelauale", "errors.unexpected_crash.report_issue": "Teavita veast", "follow_request.authorize": "Autoriseeri", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "tekstiala/otsingu koostamise mittefokuseerimiseks", "keyboard_shortcuts.up": "liikumaks nimistus üles", "lightbox.close": "Sulge", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Järgmine", "lightbox.previous": "Eelmine", - "lightbox.view_context": "Vaata konteksti", "lists.account.add": "Lisa nimistusse", "lists.account.remove": "Eemalda nimistust", "lists.delete": "Kustuta nimistu", @@ -260,6 +266,10 @@ "lists.edit.submit": "Muuda pealkiri", "lists.new.create": "Lisa nimistu", "lists.new.title_placeholder": "Uus nimistu pealkiri", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Otsi Teie poolt jälgitavate inimese hulgast", "lists.subheading": "Teie nimistud", "load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Lülita nähtavus", "missing_indicator.label": "Ei leitud", "missing_indicator.sublabel": "Seda ressurssi ei leitud", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Kas peita teated sellelt kasutajalt?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobiilrakendused", "navigation_bar.blocks": "Blokeeritud kasutajad", "navigation_bar.bookmarks": "Järjehoidjad", @@ -298,6 +310,7 @@ "notification.own_poll": "Teie küsitlus on lõppenud", "notification.poll": "Küsitlus, milles osalesite, on lõppenud", "notification.reblog": "{name} upitas Teie staatust", + "notification.status": "{name} just posted", "notifications.clear": "Puhasta teated", "notifications.clear_confirmation": "Olete kindel, et soovite püsivalt kõik oma teated eemaldada?", "notifications.column_settings.alert": "Töölauateated", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Upitused:", "notifications.column_settings.show": "Kuva tulbas", "notifications.column_settings.sound": "Mängi heli", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Kõik", "notifications.filter.boosts": "Upitused", "notifications.filter.favourites": "Lemmikud", "notifications.filter.follows": "Jälgib", "notifications.filter.mentions": "Mainimised", "notifications.filter.polls": "Küsitluse tulemused", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} teated", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Suletud", "poll.refresh": "Värskenda", "poll.total_people": "{count, plural,one {# inimene} other {# inimest}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Tuvasta teksti pildilt", "upload_modal.edit_media": "Muuda meediat", "upload_modal.hint": "Vajuta või tõmba ringi eelvaatel, et valida fookuspunkti, mis on alati nähtaval kõikidel eelvaadetel.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Eelvaade ({ratio})", "upload_progress.label": "Laeb üles....", "video.close": "Sulge video", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 09471ff2ab42975a89d0482cf94cf6ffbe15bbb8..80119dc003b0761861037ef43b234043ac6ad0bb 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Ezeztatu jarraitzeko eskaria", "account.direct": "Mezu zuzena @{name}(r)i", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Ezkutatutako domeinua", "account.edit_profile": "Aldatu profila", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Nabarmendu profilean", "account.follow": "Jarraitu", "account.followers": "Jarraitzaileak", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Bilaketaren emaitzak", "emoji_button.symbols": "Sinboloak", "emoji_button.travel": "Bidaiak eta tokiak", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ez dago tootik hemen!", "empty_column.account_unavailable": "Profila ez dago eskuragarri", "empty_column.blocks": "Ez duzu erabiltzailerik blokeatu oraindik.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Ez duzu jakinarazpenik oraindik. Jarri besteekin harremanetan elkarrizketa abiatzeko.", "empty_column.public": "Ez dago ezer hemen! Idatzi zerbait publikoki edo jarraitu eskuz beste zerbitzari batzuetako erabiltzaileak hau betetzen joateko", "error.unexpected_crash.explanation": "Gure kodean arazoren bat dela eta, edo nabigatzailearekin bateragarritasun arazoren bat dela eta, orri hau ezin izan da ongi bistaratu.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Saiatu orria berritzen. Horrek ez badu laguntzen, agian Mastodon erabiltzeko aukera duzu oraindik ere beste nabigatzaile bat edo aplikazio natibo bat erabilita.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopiatu irteera arbelera", "errors.unexpected_crash.report_issue": "Eman arazoaren berri", "follow_request.authorize": "Baimendu", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "testua konposatzeko area / bilaketatik fokua kentzea", "keyboard_shortcuts.up": "zerrendan gora mugitzea", "lightbox.close": "Itxi", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Hurrengoa", "lightbox.previous": "Aurrekoa", - "lightbox.view_context": "Ikusi testuingurua", "lists.account.add": "Gehitu zerrendara", "lists.account.remove": "Kendu zerrendatik", "lists.delete": "Ezabatu zerrenda", @@ -260,6 +266,10 @@ "lists.edit.submit": "Aldatu izenburua", "lists.new.create": "Gehitu zerrenda", "lists.new.title_placeholder": "Zerrenda berriaren izena", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Bilatu jarraitzen dituzun pertsonen artean", "lists.subheading": "Zure zerrendak", "load_pending": "{count, plural, one {eleentuberri #} other {# elementu berri}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Txandakatu ikusgaitasuna", "missing_indicator.label": "Ez aurkitua", "missing_indicator.sublabel": "Baliabide hau ezin izan da aurkitu", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Ezkutatu erabiltzaile honen jakinarazpenak?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mugikorrerako aplikazioak", "navigation_bar.blocks": "Blokeatutako erabiltzaileak", "navigation_bar.bookmarks": "Laster-markak", @@ -298,6 +310,7 @@ "notification.own_poll": "Zure inkesta amaitu da", "notification.poll": "Zuk erantzun duzun inkesta bat bukatu da", "notification.reblog": "{name}(e)k bultzada eman dio zure mezuari", + "notification.status": "{name} just posted", "notifications.clear": "Garbitu jakinarazpenak", "notifications.clear_confirmation": "Ziur zure jakinarazpen guztiak behin betirako garbitu nahi dituzula?", "notifications.column_settings.alert": "Mahaigaineko jakinarazpenak", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Bultzadak:", "notifications.column_settings.show": "Erakutsi zutabean", "notifications.column_settings.sound": "Jo soinua", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Denak", "notifications.filter.boosts": "Bultzadak", "notifications.filter.favourites": "Gogokoak", "notifications.filter.follows": "Jarraipenak", "notifications.filter.mentions": "Aipamenak", "notifications.filter.polls": "Inkestaren emaitza", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} jakinarazpen", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Itxita", "poll.refresh": "Berritu", "poll.total_people": "{count, plural, one {pertsona #} other {# pertsona}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Antzeman testua iruditik", "upload_modal.edit_media": "Editatu media", "upload_modal.hint": "Sakatu eta jaregin aurrebistako zirkulua iruditxoetan beti ikusgai egongo den puntu fokala hautatzeko.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Aurreikusi ({ratio})", "upload_progress.label": "Igotzen...", "video.close": "Itxi bideoa", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 6685b2ccb1ec1597257462f6aa2f465aacabcdbe..b062ec18b1ae9db3f2a770e205ae5e221bf8ae2f 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -4,13 +4,15 @@ "account.badges.bot": "ربات", "account.badges.group": "گروه", "account.block": "مسدودسازی @{name}", - "account.block_domain": "Ù†Ù‡ÙØªÙ† همه چیز از {domain}", + "account.block_domain": "بستن دامنه {domain}", "account.blocked": "مسدود", "account.browse_more_on_origin_server": "مرور بیش‌تر روی نمایهٔ اصلی", "account.cancel_follow_request": "لغو درخواست پیگیری", "account.direct": "پیام خصوصی به @{name}", - "account.domain_blocked": "دامنهٔ Ù†Ù‡ÙØªÙ‡", + "account.disable_notifications": "آگاهی به من هنگام ÙØ±Ø³ØªØ§Ø¯Ù†â€ŒÙ‡Ø§ÛŒ @{name} پایان یابد", + "account.domain_blocked": "دامنه بسته شد", "account.edit_profile": "ویرایش نمایه", + "account.enable_notifications": "آگاهی هنگام ارسال‌های @{name}", "account.endorse": "معرّÙÛŒ در نمایه", "account.follow": "Ù¾ÛŒ بگیرید", "account.followers": "پی‌گیران", @@ -38,7 +40,7 @@ "account.show_reblogs": "نمایش بازبوق‌های @{name}", "account.statuses_counter": "{count, plural, one {{counter} بوق} other {{counter} بوق}}", "account.unblock": "Ø±ÙØ¹ انسداد @{name}", - "account.unblock_domain": "Ø±ÙØ¹ Ù†Ù‡ÙØªÙ† {domain}", + "account.unblock_domain": "گشودن دامنه {domain}", "account.unendorse": "معرّÙÛŒ نکردن در نمایه", "account.unfollow": "پایان پیگیری", "account.unmute": "Ø±ÙØ¹ خموشی @{name}", @@ -62,7 +64,7 @@ "column.community": "نوشته‌های Ù…ØÙ„ÛŒ", "column.direct": "پیام‌های خصوصی", "column.directory": "مرور نمایه‌ها", - "column.domain_blocks": "دامنه‌های Ù†Ù‡ÙØªÙ‡", + "column.domain_blocks": "دامنه‌های بسته", "column.favourites": "پسندیده‌ها", "column.follow_requests": "درخواست‌های پیگیری", "column.home": "خانه", @@ -78,8 +80,8 @@ "column_header.pin": "ثابت‌کردن", "column_header.show_settings": "نمایش تنظیمات", "column_header.unpin": "رهاکردن", - "column_subheading.settings": "تنظیمات", - "community.column_settings.local_only": "تنها بومی", + "column_subheading.settings": "ساماندهی", + "community.column_settings.local_only": "Ùقط Ù…ØÙ„Ù‘ÛŒ", "community.column_settings.media_only": "Ùقط رسانه", "community.column_settings.remote_only": "تنها دوردست", "compose_form.direct_message_warning": "این بوق تنها به کاربرانی Ú©Ù‡ از آن‌ها نام برده شده ÙØ±Ø³ØªØ§Ø¯Ù‡ خواهد شد.", @@ -96,7 +98,7 @@ "compose_form.poll.switch_to_single": "تبدیل به نظرسنجی تک‌گزینه‌ای", "compose_form.publish": "بوق", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "علامت‌گذاری به عنوان ØØ³Ø§Ø³", + "compose_form.sensitive.hide": "علامت‌گذاری رسانه به عنوان ØØ³Ø§Ø³", "compose_form.sensitive.marked": "رسانه به عنوان ØØ³Ø§Ø³ علامت‌گذاری شده", "compose_form.sensitive.unmarked": "رسانه به عنوان ØØ³Ø§Ø³ علامت‌گذاری نشده", "compose_form.spoiler.marked": "نوشته پشت هشدار پنهان است", @@ -147,6 +149,7 @@ "emoji_button.search_results": "نتایج جستجو", "emoji_button.symbols": "نمادها", "emoji_button.travel": "Ø³ÙØ± Ùˆ مکان", + "empty_column.account_suspended": "ØØ³Ø§Ø¨ معلق شد", "empty_column.account_timeline": "هیچ بوقی این‌جا نیست!", "empty_column.account_unavailable": "نمایهٔ موجود نیست", "empty_column.blocks": "هنوز کسی را مسدود نکرده‌اید.", @@ -166,7 +169,9 @@ "empty_column.notifications": "هنوز هیچ اعلانی ندارید. به دیگران واکنش نشان دهید تا Ú¯ÙØªÚ¯Ùˆ آغاز شود.", "empty_column.public": "این‌جا هنوز چیزی نیست! خودتان چیزی بنویسید یا کاربران کارسازهای دیگر را Ù¾ÛŒ بگیرید تا این‌جا پر شود", "error.unexpected_crash.explanation": "به خاطر اشکالی در کدهای ما یا ناسازگاری با مرورگر شما، این ØµÙØÙ‡ به درستی نمایش Ù†ÛŒØ§ÙØª.", + "error.unexpected_crash.explanation_addons": "این ØµÙØÙ‡ نمی‌تواند درست نشان داده شود. Ø§ØØªÙ…الاً این خطا ناشی از یک Ø§ÙØ²ÙˆÙ†Ù‡Ù” مرورگر یا ابزار ترجمهٔ خودکار است.", "error.unexpected_crash.next_steps": "Ù„Ø·ÙØ§Ù‹ ØµÙØÙ‡ را دوباره باز کنید. اگر Ú©Ù…Ú©ÛŒ نکرد، شاید همچنان بتوانید با ماستودون از راه یک مرورگر دیگر یا با یکی از اپ‌های آن کار کنید.", + "error.unexpected_crash.next_steps_addons": "Ù„Ø·ÙØ§Ù‹ از کارشان انداخته Ùˆ ØµÙØÙ‡ را نوسازی کنید. اگر Ú©Ù…Ú©ÛŒ نکرد، شاید همچنان بتوانید با مرورگری دیگر یا با کاره‌ای بومی از ماستودون Ø§Ø³ØªÙØ§Ø¯Ù‡ کنید.", "errors.unexpected_crash.copy_stacktrace": "رونوشت از جزئیات اشکال", "errors.unexpected_crash.report_issue": "گزارش مشکل", "follow_request.authorize": "اجازه دهید", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "برای برداشتن تمرکز از نوشتن/جستجو", "keyboard_shortcuts.up": "برای بالا Ø±ÙØªÙ† در Ùهرست", "lightbox.close": "بستن", + "lightbox.compress": "ÙØ´Ø±Ø¯Ù‡â€ŒØ³Ø§Ø²ÛŒ جعبه نمایش تصویر", + "lightbox.expand": "گسترش جعبه نمایش تصویر", "lightbox.next": "بعدی", "lightbox.previous": "قبلی", - "lightbox.view_context": "نمایش Ú¯ÙØªÚ¯Ùˆ", "lists.account.add": "Ø§ÙØ²ÙˆØ¯Ù† به Ùهرست", "lists.account.remove": "برداشتن از Ùهرست", "lists.delete": "ØØ°Ù Ùهرست", @@ -260,6 +266,10 @@ "lists.edit.submit": "تغییر عنوان", "lists.new.create": "Ø§ÙØ²ÙˆØ¯Ù† Ùهرست", "lists.new.title_placeholder": "عنوان Ùهرست تازه", + "lists.replies_policy.followed": "هر کاربر Ù¾ÛŒÚ¯Ø±ÙØªÙ‡", + "lists.replies_policy.list": "اعضای Ùهرست", + "lists.replies_policy.none": "هیچ کدام", + "lists.replies_policy.title": "نمایش پاسخ‌ها به:", "lists.search": "بین کسانی Ú©Ù‡ Ù¾ÛŒ می‌گیرید بگردید", "lists.subheading": "Ùهرست‌های شما", "load_pending": "{count, plural, one {# مورد تازه} other {# مورد تازه}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "تغییر وضعیت نمایانی", "missing_indicator.label": "پیدا نشد", "missing_indicator.sublabel": "این منبع پیدا نشد", + "mute_modal.duration": "مدت زمان", "mute_modal.hide_notifications": "اعلان‌های این کاربر پنهان شود؟", + "mute_modal.indefinite": "نامعلوم", "navigation_bar.apps": "اپ‌های موبایل", "navigation_bar.blocks": "کاربران مسدودشده", "navigation_bar.bookmarks": "نشانک‌ها", @@ -275,7 +287,7 @@ "navigation_bar.compose": "نوشتن بوق تازه", "navigation_bar.direct": "پیام‌های مستقیم", "navigation_bar.discover": "گشت Ùˆ گذار", - "navigation_bar.domain_blocks": "دامنه‌های Ù†Ù‡ÙØªÙ‡", + "navigation_bar.domain_blocks": "دامنه‌های بسته", "navigation_bar.edit_profile": "ویرایش نمایه", "navigation_bar.favourites": "پسندیده‌ها", "navigation_bar.filters": "واژگان خموش", @@ -298,6 +310,7 @@ "notification.own_poll": "نظرسنجی شما به پایان رسید", "notification.poll": "نظرسنجی‌ای Ú©Ù‡ در آن رأی دادید به پایان رسیده است", "notification.reblog": "‫{name}‬ وضعیتتان را تقویت کرد", + "notification.status": "{name} چیزی ÙØ±Ø³ØªØ§Ø¯", "notifications.clear": "پاک‌کردن اعلان‌ها", "notifications.clear_confirmation": "مطمئنید می‌خواهید همهٔ اعلان‌هایتان را برای همیشه پاک کنید؟", "notifications.column_settings.alert": "اعلان‌های میزکار", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "بازبوق‌ها:", "notifications.column_settings.show": "نمایش در ستون", "notifications.column_settings.sound": "پخش صدا", + "notifications.column_settings.status": "بوق‌های جدید:", "notifications.filter.all": "همه", "notifications.filter.boosts": "بازبوق‌ها", "notifications.filter.favourites": "پسندها", "notifications.filter.follows": "پیگیری‌ها", "notifications.filter.mentions": "نام‌بردن‌ها", "notifications.filter.polls": "نتایج نظرسنجی", + "notifications.filter.statuses": "به‌روز رسانی‌ها از کسانی Ú©Ù‡ پی‌گیرشانید", + "notifications.grant_permission": "اعطای مجوز.", "notifications.group": "{count} اعلان", + "notifications.mark_as_read": "نشانه‌گذاری همهٔ آگاهی‌ها به عنوان خوانده‌شده", + "notifications.permission_denied": "آگاهی‌های میزکار به دلیل رد کردن درخواست اجازهٔ پیشین مرورگر، در دسترس نیستند", + "notifications.permission_denied_alert": "از آن‌جا Ú©Ù‡ پیش از این اجازهٔ مرورگر رد شده است، آگاهی‌های میزکار نمی‌توانند به کار Ø¨ÛŒÙØªÙ†Ø¯", + "notifications.permission_required": "اعلان‌های میزکار در دسترس نیستند زیرا نیازمند مجوزی هستند Ú©Ù‡ اعطا نشده است.", + "notifications_permission_banner.enable": "به کار انداختن آگاهی‌های میزکار", + "notifications_permission_banner.how_to_control": "اگر می‌خواهید ØØªÛŒ زمانی Ú©Ù‡ ماستودون باز نیست اعلان‌ها نمایش یابند، اعلان‌های میزکار را ÙØ¹Ø§Ù„ کنید. به Ù…ØØ¶ ÙØ¹Ø§Ù„ شدن از طریق دکمه {icon} بالا می‌توانید به دقت کنترل کنید Ú©Ù‡ Ú†Ù‡ نوع از تعامل‌ها باعث صادر شدن اعلان‌ها شوند.", + "notifications_permission_banner.title": "هرگز چیزی را از دست ندهید", + "picture_in_picture.restore": "برگرداندن", "poll.closed": "Ù¾Ø§ÛŒØ§Ù†â€ŒÛŒØ§ÙØªÙ‡", "poll.refresh": "به‌روزرسانی", "poll.total_people": "{count, plural, one {# Ù†ÙØ±} other {# Ù†ÙØ±}}", @@ -389,7 +413,7 @@ "status.pinned": "بوق ثابت", "status.read_more": "بیشتر بخوانید", "status.reblog": "بازبوقیدن", - "status.reblog_private": "بازبوق به مخاطبان اولیه", + "status.reblog_private": "تقویت برای مخاطبان نخستین", "status.reblogged_by": "‫{name}‬ بازبوقید", "status.reblogs.empty": "هنوز هیچ کسی این بوق را بازنبوقیده است. وقتی کسی چنین کاری کند، این‌جا نمایش خواهد ÛŒØ§ÙØª.", "status.redraft": "پاک‌کردن Ùˆ بازنویسی", @@ -398,7 +422,7 @@ "status.replyAll": "پاسخ به رشته", "status.report": "گزارش @{name}", "status.sensitive_warning": "Ù…ØØªÙˆØ§ÛŒ ØØ³Ø§Ø³", - "status.share": "هم‌رسانی", + "status.share": "همرسانی", "status.show_less": "نمایش کمتر", "status.show_less_all": "نمایش کمتر همه", "status.show_more": "نمایش بیشتر", @@ -430,7 +454,7 @@ "units.short.million": "{count}میلیون", "units.short.thousand": "{count}هزار", "upload_area.title": "برای بارگذاری به این‌جا بکشید", - "upload_button.label": "Ø§ÙØ²ÙˆØ¯Ù† رسانه ({formats})", + "upload_button.label": "Ø§ÙØ²ÙˆØ¯Ù† رسانه", "upload_error.limit": "از ØØ¯ مجاز باگذاری پرونده ÙØ±Ø§ØªØ± Ø±ÙØªÛŒØ¯.", "upload_error.poll": "بارگذاری پرونده در نظرسنجی‌ها مجاز نیست.", "upload_form.audio_description": "برای ناشنوایان ØªÙˆØµÛŒÙØ´ کنید", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "تشخیص متن درون عکس", "upload_modal.edit_media": "ویرایش رسانه", "upload_modal.hint": "ØØªÛŒ اگر تصویر بریده یا Ú©ÙˆÚ†Ú© شود، نقطهٔ کانونی آن همیشه دیده خواهد شد. نقطهٔ کانونی را با کلیک یا جابه‌جا کردن آن تنظیم کنید.", + "upload_modal.preparing_ocr": "در ØØ§Ù„ آماده سازی OCR…", "upload_modal.preview_label": "پیش‌نمایش ({ratio})", "upload_progress.label": "در ØØ§Ù„ بارگذاری…", "video.close": "بستن ویدیو", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 44589aa4afb3e9a8424289e62ef860a577d539d4..8916d4339d992076fae7fe581d6e412e203248b6 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -1,16 +1,18 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Muistiinpanot", "account.add_or_remove_from_list": "Lisää tai poista listoilta", "account.badges.bot": "Botti", "account.badges.group": "Ryhmä", "account.block": "Estä @{name}", "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", "account.blocked": "Estetty", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella", "account.cancel_follow_request": "Peruuta seurauspyyntö", "account.direct": "Viesti käyttäjälle @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Verkko-osoite piilotettu", "account.edit_profile": "Muokkaa profiilia", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Suosittele profiilissasi", "account.follow": "Seuraa", "account.followers": "Seuraajaa", @@ -43,7 +45,7 @@ "account.unfollow": "Lakkaa seuraamasta", "account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Lisää muistiinpano napsauttamalla", "alert.rate_limited.message": "Yritä uudestaan {retry_time, time, medium} jälkeen.", "alert.rate_limited.title": "Määrää rajoitettu", "alert.unexpected.message": "Tapahtui odottamaton virhe.", @@ -79,7 +81,7 @@ "column_header.show_settings": "Näytä asetukset", "column_header.unpin": "Poista kiinnitys", "column_subheading.settings": "Asetukset", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "Vain paikalliset", "community.column_settings.media_only": "Vain media", "community.column_settings.remote_only": "Remote only", "compose_form.direct_message_warning": "Tämä tuuttaus näkyy vain mainituille käyttäjille.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Hakutulokset", "emoji_button.symbols": "Symbolit", "emoji_button.travel": "Matkailu", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ei ole 'toots' täällä!", "empty_column.account_unavailable": "Profiilia ei löydy", "empty_column.blocks": "Et ole vielä estänyt yhtään käyttäjää.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Aloita keskustelu juttelemalla muille.", "empty_column.public": "Täällä ei ole mitään! Saat sisältöä, kun kirjoitat jotain julkisesti tai käyt seuraamassa muiden instanssien käyttäjiä", "error.unexpected_crash.explanation": "Sivua ei voi näyttää oikein, johtuen bugista tai ongelmasta selaimen yhteensopivuudessa.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Kokeile päivittää sivu. Jos tämä ei auta, saatat yhä pystyä käyttämään Mastodonia toisen selaimen tai sovelluksen kautta.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopioi stacktrace leikepöydälle", "errors.unexpected_crash.report_issue": "Ilmoita ongelmasta", "follow_request.authorize": "Valtuuta", "follow_request.reject": "Hylkää", "follow_requests.unlocked_explanation": "Vaikka tilisi ei ole lukittu, {domain} ylläpitäjien mielestä haluat tarkistaa näiden tilien seurauspyynnöt manuaalisesti.", - "generic.saved": "Saved", + "generic.saved": "Tallennettu", "getting_started.developers": "Kehittäjille", "getting_started.directory": "Profiilihakemisto", "getting_started.documentation": "Documentaatio", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "vastaa", "keyboard_shortcuts.requests": "avaa lista seurauspyynnöistä", "keyboard_shortcuts.search": "siirry hakukenttään", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "näyttääksesi/piilottaaksesi CW kentän", "keyboard_shortcuts.start": "avaa \"Aloitus\" -sarake", "keyboard_shortcuts.toggle_hidden": "näytä/piilota sisältövaroituksella merkitty teksti", "keyboard_shortcuts.toggle_sensitivity": "näytä/piilota media", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "siirry pois tekstikentästä tai hakukentästä", "keyboard_shortcuts.up": "siirry listassa ylöspäin", "lightbox.close": "Sulje", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Seuraava", "lightbox.previous": "Edellinen", - "lightbox.view_context": "Näytä kontekstissa", "lists.account.add": "Lisää listaan", "lists.account.remove": "Poista listasta", "lists.delete": "Poista lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Vaihda otsikko", "lists.new.create": "Lisää lista", "lists.new.title_placeholder": "Uuden listan nimi", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Etsi seuraamistasi henkilöistä", "lists.subheading": "Omat listat", "load_pending": "{count, plural, one {# uusi kappale} other {# uutta kappaletta}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Säädä näkyvyyttä", "missing_indicator.label": "Ei löytynyt", "missing_indicator.sublabel": "Tätä resurssia ei löytynyt", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Piilota tältä käyttäjältä tulevat ilmoitukset?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobiilisovellukset", "navigation_bar.blocks": "Estetyt käyttäjät", "navigation_bar.bookmarks": "Kirjanmerkit", @@ -298,6 +310,7 @@ "notification.own_poll": "Kyselysi on päättynyt", "notification.poll": "Kysely, johon osallistuit, on päättynyt", "notification.reblog": "{name} buustasi tilaasi", + "notification.status": "{name} just posted", "notifications.clear": "Tyhjennä ilmoitukset", "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?", "notifications.column_settings.alert": "Työpöytäilmoitukset", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Buustit:", "notifications.column_settings.show": "Näytä sarakkeessa", "notifications.column_settings.sound": "Äänimerkki", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Kaikki", "notifications.filter.boosts": "Buustit", "notifications.filter.favourites": "Suosikit", "notifications.filter.follows": "Seuraa", "notifications.filter.mentions": "Maininnat", "notifications.filter.polls": "Kyselyn tulokset", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} ilmoitusta", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Suljettu", "poll.refresh": "Päivitä", "poll.total_people": "{count, plural, one {# henkilö} other {# henkilöä}}", @@ -420,15 +444,15 @@ "time_remaining.moments": "Hetki jäljellä", "time_remaining.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} jäljellä", "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", + "timeline_hint.resources.followers": "Seuraajat", + "timeline_hint.resources.follows": "Seuraa", + "timeline_hint.resources.statuses": "Vanhemmat tuuttaukset", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", "trends.trending_now": "Suosittua nyt", "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.", "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.million": "{count}m", + "units.short.thousand": "{count}k", "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän", "upload_button.label": "Lisää mediaa", "upload_error.limit": "Tiedostolatauksien raja ylitetty.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Kuvaile kuulovammaisille", "upload_form.description": "Anna kuvaus näkörajoitteisia varten", "upload_form.edit": "Muokkaa", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Vaihda pikkukuva", "upload_form.undo": "Peru", "upload_form.video_description": "Kuvaile kuulo- tai näkövammaisille", "upload_modal.analyzing_picture": "Analysoidaan kuvaa…", "upload_modal.apply": "Käytä", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Valitse kuva", "upload_modal.description_placeholder": "Eräänä jäätävänä ja pimeänä yönä gorilla ratkaisi sudokun kahdessa minuutissa", "upload_modal.detect_text": "Tunnista teksti kuvasta", "upload_modal.edit_media": "Muokkaa mediaa", "upload_modal.hint": "Klikkaa tai vedä ympyrä esikatselussa valitaksesi keskipiste, joka näkyy aina pienoiskuvissa.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Esikatselu ({ratio})", "upload_progress.label": "Ladataan...", "video.close": "Sulje video", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index 6376ca35112714dabeff88e203b15723b773041d..214f3aeea687d9507831a72ebdaf64c6dda2a9a0 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Parcourir davantage sur le profil original", "account.cancel_follow_request": "Annuler la demande de suivi", "account.direct": "Envoyer un message direct à @{name}", + "account.disable_notifications": "Arrêter de me notifier quand @{name} publie", "account.domain_blocked": "Domaine bloqué", "account.edit_profile": "Modifier le profil", + "account.enable_notifications": "Me notifier quand @{name} publie", "account.endorse": "Recommander sur le profil", "account.follow": "Suivre", "account.followers": "Abonné·e·s", @@ -97,7 +99,7 @@ "compose_form.publish": "Pouet", "compose_form.publish_loud": "{publish} !", "compose_form.sensitive.hide": "Marquer le média comme sensible", - "compose_form.sensitive.marked": "Média marqué comme sensible", + "compose_form.sensitive.marked": "{count, plural, one {Le média est marqué comme sensible} other {Les médias sont marqués comme sensibles}}", "compose_form.sensitive.unmarked": "Le média n’est pas marqué comme sensible", "compose_form.spoiler.marked": "Le texte est caché derrière un avertissement", "compose_form.spoiler.unmarked": "Le texte n’est pas caché", @@ -147,13 +149,14 @@ "emoji_button.search_results": "Résultats de la recherche", "emoji_button.symbols": "Symboles", "emoji_button.travel": "Lieux & Voyages", + "empty_column.account_suspended": "Compte suspendu", "empty_column.account_timeline": "Aucun pouet ici !", "empty_column.account_unavailable": "Profil non disponible", "empty_column.blocks": "Vous n’avez bloqué aucun·e utilisateur·rice pour le moment.", "empty_column.bookmarked_statuses": "Vous n'avez pas de pouets enregistrés comme marque-pages pour le moment. Lorsque vous en ajouterez un, il apparaîtra ici.", "empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !", "empty_column.direct": "Vous n’avez pas encore de messages directs. Lorsque vous en enverrez ou recevrez un, il s’affichera ici.", - "empty_column.domain_blocks": "Il n’y a aucun domaine caché pour le moment.", + "empty_column.domain_blocks": "Il n’y a aucun domaine bloqué pour le moment.", "empty_column.favourited_statuses": "Vous n’avez aucun pouet favoris pour le moment. Lorsque vous en mettrez un en favori, il apparaîtra ici.", "empty_column.favourites": "Personne n’a encore mis ce pouet en favori. Lorsque quelqu’un le fera, il apparaîtra ici.", "empty_column.follow_requests": "Vous n’avez pas encore de demande de suivi. Lorsque vous en recevrez une, elle apparaîtra ici.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.", "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres serveurs pour remplir le fil public", "error.unexpected_crash.explanation": "En raison d’un bug dans notre code ou d’un problème de compatibilité avec votre navigateur, cette page n’a pas pu être affichée correctement.", + "error.unexpected_crash.explanation_addons": "Cette page n’a pas pu être affichée correctement. Cette erreur est probablement causée par une extension de navigateur ou des outils de traduction automatique.", "error.unexpected_crash.next_steps": "Essayez de rafraîchir la page. Si cela n’aide pas, vous pouvez toujours utiliser Mastodon via un autre navigateur ou une application native.", + "error.unexpected_crash.next_steps_addons": "Essayez de les désactiver et de rafraîchir la page. Si cela ne vous aide pas, vous pouvez toujours utiliser Mastodon via un autre navigateur ou une application native.", "errors.unexpected_crash.copy_stacktrace": "Copier la trace d'appels dans le presse-papier", "errors.unexpected_crash.report_issue": "Signaler le problème", "follow_request.authorize": "Accepter", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "quitter la zone de rédaction/recherche", "keyboard_shortcuts.up": "remonter dans la liste", "lightbox.close": "Fermer", + "lightbox.compress": "Compresser la fenêtre de visualisation des images", + "lightbox.expand": "Agrandir la fenêtre de visualisation des images", "lightbox.next": "Suivant", "lightbox.previous": "Précédent", - "lightbox.view_context": "Voir le contexte", "lists.account.add": "Ajouter à la liste", "lists.account.remove": "Supprimer de la liste", "lists.delete": "Supprimer la liste", @@ -260,6 +266,10 @@ "lists.edit.submit": "Modifier le titre", "lists.new.create": "Ajouter une liste", "lists.new.title_placeholder": "Titre de la nouvelle liste", + "lists.replies_policy.followed": "N’importe quel·le utilisateur·rice suivi·e", + "lists.replies_policy.list": "Membres de la liste", + "lists.replies_policy.none": "Personne", + "lists.replies_policy.title": "Afficher les réponses à :", "lists.search": "Rechercher parmi les gens que vous suivez", "lists.subheading": "Vos listes", "load_pending": "{count, plural, one {# nouvel élément} other {# nouveaux éléments}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Intervertir la visibilité", "missing_indicator.label": "Non trouvé", "missing_indicator.sublabel": "Ressource introuvable", + "mute_modal.duration": "Durée", "mute_modal.hide_notifications": "Masquer les notifications de cette personne ?", + "mute_modal.indefinite": "Indéfinie", "navigation_bar.apps": "Applications mobiles", "navigation_bar.blocks": "Comptes bloqués", "navigation_bar.bookmarks": "Marque-pages", @@ -298,6 +310,7 @@ "notification.own_poll": "Votre sondage est terminé", "notification.poll": "Un sondage auquel vous avez participé vient de se terminer", "notification.reblog": "{name} a partagé votre statut", + "notification.status": "{name} vient de publier", "notifications.clear": "Effacer les notifications", "notifications.clear_confirmation": "Voulez-vous vraiment effacer toutes vos notifications ?", "notifications.column_settings.alert": "Notifications du navigateur", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Partages :", "notifications.column_settings.show": "Afficher dans la colonne", "notifications.column_settings.sound": "Émettre un son", + "notifications.column_settings.status": "Nouveaux pouets :", "notifications.filter.all": "Tout", "notifications.filter.boosts": "Partages", "notifications.filter.favourites": "Favoris", "notifications.filter.follows": "Abonnés", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Résultats des sondages", + "notifications.filter.statuses": "Mises à jour des personnes que vous suivez", + "notifications.grant_permission": "Accorder l’autorisation.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Marquer toutes les notifications comme lues", + "notifications.permission_denied": "Impossible d’activer les notifications de bureau car l’autorisation a été refusée.", + "notifications.permission_denied_alert": "Les notifications de bureau ne peuvent pas être activées, car l’autorisation du navigateur a été refusée avant", + "notifications.permission_required": "Les notifications de bureau ne sont pas disponibles car l’autorisation requise n’a pas été accordée.", + "notifications_permission_banner.enable": "Activer les notifications de bureau", + "notifications_permission_banner.how_to_control": "Pour recevoir des notifications lorsque Mastodon n’est pas ouvert, activez les notifications du bureau. Vous pouvez contrôler précisément quels types d’interactions génèrent des notifications de bureau via le bouton {icon} ci-dessus une fois qu’elles sont activées.", + "notifications_permission_banner.title": "Toujours au courant", + "picture_in_picture.restore": "Remettre en place", "poll.closed": "Fermé", "poll.refresh": "Actualiser", "poll.total_people": "{count, plural, one {# personne} other {# personnes}}", @@ -414,8 +438,8 @@ "tabs_bar.local_timeline": "Fil public local", "tabs_bar.notifications": "Notifications", "tabs_bar.search": "Chercher", - "time_remaining.days": "{number, plural, one {# day} other {# days}} restants", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} restantes", + "time_remaining.days": "{number, plural, one {# jour} other {# jours}} restant·s", + "time_remaining.hours": "{number, plural, one {# heure} other {# heures}} restantes", "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} restantes", "time_remaining.moments": "Encore quelques instants", "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} restantes", @@ -423,14 +447,14 @@ "timeline_hint.resources.followers": "Les abonnés", "timeline_hint.resources.follows": "Les abonnements", "timeline_hint.resources.statuses": "Les anciens pouets", - "trends.counter_by_accounts": "{count, plural, one {{counter} personne} other {{counter} personnes}} en parle·nt", + "trends.counter_by_accounts": "{count, plural, one {{counter} personne en parle} other {{counter} personnes en parlent}}", "trends.trending_now": "Tendance en ce moment", "ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.", - "units.short.billion": "{count}B", + "units.short.billion": "{count}Md", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Glissez et déposez pour envoyer", - "upload_button.label": "Joindre un média ({formats})", + "upload_button.label": "Ajouter des images, une vidéo ou un fichier audio", "upload_error.limit": "Taille maximale d'envoi de fichier dépassée.", "upload_error.poll": "L’envoi de fichiers n’est pas autorisé avec les sondages.", "upload_form.audio_description": "Décrire pour les personnes ayant des difficultés d’audition", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Détecter le texte de l’image", "upload_modal.edit_media": "Modifier le média", "upload_modal.hint": "Cliquez ou faites glisser le cercle sur l’aperçu pour choisir le point focal qui sera toujours visible sur toutes les miniatures.", + "upload_modal.preparing_ocr": "Préparation de l’OCR…", "upload_modal.preview_label": "Aperçu ({ratio})", "upload_progress.label": "Envoi en cours…", "video.close": "Fermer la vidéo", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 5de7b27a50b6ce91d66d35304cc85246d36154a3..928742dd711ca3747ca8bd909d012898aa18ccf2 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide media", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index e0180a0839e33134955e9d723c6ed3dd068bd55c..854e31554f1c76452178aa117943c2fb9c97b537 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "A túa nota para @{name}", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Engadir ou eliminar das listaxes", "account.badges.bot": "Bot", "account.badges.group": "Grupo", @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Busca máis no perfil orixinal", "account.cancel_follow_request": "Desbotar solicitude de seguimento", "account.direct": "Mensaxe directa @{name}", + "account.disable_notifications": "Deixar de notificarme cando @{name} publica", "account.domain_blocked": "Dominio agochado", "account.edit_profile": "Editar perfil", + "account.enable_notifications": "Noficarme cando @{name} publique", "account.endorse": "Amosar no perfil", "account.follow": "Seguir", "account.followers": "Seguidoras", "account.followers.empty": "AÃnda ninguén segue esta usuaria.", "account.followers_counter": "{count, plural, one {{counter} Seguidora} other {{counter} Seguidoras}}", - "account.following_counter": "{count, plural, one {} other {{counter} Seguindo}}", + "account.following_counter": "{count, plural, one {{counter} Seguindo} other {{counter} Seguindo}}", "account.follows.empty": "Esta usuaria aÃnda non segue a ninguén.", "account.follows_you": "Séguete", "account.hide_reblogs": "Agochar repeticións de @{name}", @@ -43,10 +45,10 @@ "account.unfollow": "Deixar de seguir", "account.unmute": "Deixar de silenciar a @{name}", "account.unmute_notifications": "Deixar de silenciar as notificacións de @{name}", - "account_note.placeholder": "Sen comentarios", + "account_note.placeholder": "Preme para engadir nota", "alert.rate_limited.message": "Téntao novamente após {retry_time, time, medium}.", "alert.rate_limited.title": "LÃmite de intentos", - "alert.unexpected.message": "Ocorreu un erro non agardado.", + "alert.unexpected.message": "Aconteceu un fallo non agardado.", "alert.unexpected.title": "Vaites!", "announcement.announcement": "Anuncio", "autosuggest_hashtag.per_week": "{count} por semana", @@ -71,7 +73,7 @@ "column.notifications": "Notificacións", "column.pins": "Toots fixados", "column.public": "CronoloxÃa federada", - "column_back_button.label": "Voltar", + "column_back_button.label": "Volver", "column_header.hide_settings": "Agochar axustes", "column_header.moveLeft_settings": "Mover columna cara a esquerda", "column_header.moveRight_settings": "Mover columna cara a dereita", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Mudar a enquisa para permitir unha soa escolla", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Marcar coma contido multimedia sensÃbel", - "compose_form.sensitive.marked": "Contido multimedia marcado coma sensÃbel", - "compose_form.sensitive.unmarked": "Contido multimedia non marcado coma sensÃbel", + "compose_form.sensitive.hide": "{count, plural, one {Marca multimedia como sensible} other {Marca multimedia como sensibles}}", + "compose_form.sensitive.marked": "{count, plural, one {Multimedia marcado como sensible} other {Multimedia marcados como sensibles}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "O texto está agochado tras un aviso", "compose_form.spoiler.unmarked": "O texto non está agochado", "compose_form.spoiler_placeholder": "Escribe o teu aviso aquÃ", @@ -107,7 +109,7 @@ "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Tes a certeza de querer bloquear a {name}?", "confirmations.delete.confirm": "Eliminar", - "confirmations.delete.message": "Tes a certeza de querer eliminar este estado?", + "confirmations.delete.message": "Tes a certeza de querer eliminar este toot?", "confirmations.delete_list.confirm": "Eliminar", "confirmations.delete_list.message": "Tes a certeza de querer eliminar de xeito permanente esta listaxe?", "confirmations.domain_block.confirm": "Agochar dominio enteiro", @@ -118,7 +120,7 @@ "confirmations.mute.explanation": "Isto agochará as publicacións delas ou nas que as mencionen, mais permitirá que vexan as túas publicacións e sexan seguidoras túas.", "confirmations.mute.message": "Tes a certeza de querer acalar a {name}?", "confirmations.redraft.confirm": "Eliminar e reescribir", - "confirmations.redraft.message": "Tes a certeza de querer eliminar este estado e reescribilo? Perderás os compartidos e favoritos, e as respostas á publicación orixinal ficarán orfas.", + "confirmations.redraft.message": "Tes a certeza de querer eliminar este toot e reescribilo? Perderás os compartidos e favoritos, e as respostas á publicación orixinal ficarán orfas.", "confirmations.reply.confirm": "Responder", "confirmations.reply.message": "Responder agora sobrescribirá a mensaxe que estás a compor. Tes a certeza de que queres continuar?", "confirmations.unfollow.confirm": "Deixar de seguir", @@ -131,7 +133,7 @@ "directory.local": "Só de {domain}", "directory.new_arrivals": "Recén chegadas", "directory.recently_active": "Activas recentemente", - "embed.instructions": "Engade este estado ó teu sitio web copiando o seguinte código.", + "embed.instructions": "Engade este toot ó teu sitio web copiando o seguinte código.", "embed.preview": "Asà será mostrado:", "emoji_button.activity": "Actividade", "emoji_button.custom": "Personalizado", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultados da procura", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viaxes e Lugares", + "empty_column.account_suspended": "Conta suspendida", "empty_column.account_timeline": "Non hai toots aquÃ!", "empty_column.account_unavailable": "Perfil non dispoñible", "empty_column.blocks": "AÃnda non bloqueaches a ningún usuaria.", @@ -160,13 +163,15 @@ "empty_column.hashtag": "AÃnda non hai nada con este cancelo.", "empty_column.home": "A túa cronoloxÃa inicial está baleira! Visita {public} ou emprega a procura para atopar outras usuarias.", "empty_column.home.public_timeline": "a cronoloxÃa pública", - "empty_column.list": "AÃnda non hai nada nesta listaxe. Cando os usuarios incluÃdas na listaxe publiquen mensaxes, amosaranse aquÃ.", + "empty_column.list": "AÃnda non hai nada nesta listaxe. Cando as usuarias incluÃdas na listaxe publiquen mensaxes, amosaranse aquÃ.", "empty_column.lists": "AÃnda non tes listaxes. Cando crees unha, amosarase aquÃ.", "empty_column.mutes": "AÃnda non silenciaches a ningúnha usuaria.", "empty_column.notifications": "AÃnda non tes notificacións. Interactúa con outras para comezar unha conversa.", "empty_column.public": "Nada por aquÃ! Escribe algo de xeito público, ou segue de xeito manual usuarias doutros servidores para ir enchéndoo", "error.unexpected_crash.explanation": "Debido a un erro no noso código ou a unha compatilidade co teu navegador, esta páxina non pode ser amosada correctamente.", + "error.unexpected_crash.explanation_addons": "Non se puido mostrar correctamente a páxina. Habitualmente este erro está causado por algún engadido do navegador ou ferramentas de tradución automática.", "error.unexpected_crash.next_steps": "Tenta actualizar a páxina. Se esto non axuda podes tamén empregar Mastodon noutro navegador ou aplicación nativa.", + "error.unexpected_crash.next_steps_addons": "Intenta desactivalas e actualiza a páxina. Se isto non funciona, podes seguir usando Mastodon nun navegador diferente ou aplicación nativa.", "errors.unexpected_crash.copy_stacktrace": "Copiar trazas (stacktrace) ó portapapeis", "errors.unexpected_crash.report_issue": "Informar sobre un problema", "follow_request.authorize": "Autorizar", @@ -215,15 +220,15 @@ "introduction.welcome.action": "Imos!", "introduction.welcome.headline": "Primeiros pasos", "introduction.welcome.text": "Benvida ó fediverso! Nun intre poderás difundir mensaxes e falar coas túas amizades nun grande número de servidores. Mais este servidor, {domain}, é especial—hospeda o teu perfil, por iso lémbra o seu nome.", - "keyboard_shortcuts.back": "para voltar atrás", + "keyboard_shortcuts.back": "para volver atrás", "keyboard_shortcuts.blocked": "abrir lista de usuarias bloqueadas", "keyboard_shortcuts.boost": "promover", - "keyboard_shortcuts.column": "para destacar un estado nunha das columnas", + "keyboard_shortcuts.column": "para destacar un toot nunha das columnas", "keyboard_shortcuts.compose": "para destacar a área de escritura", "keyboard_shortcuts.description": "Descrición", "keyboard_shortcuts.direct": "para abrir a columna de mensaxes directas", "keyboard_shortcuts.down": "para mover cara abaixo na listaxe", - "keyboard_shortcuts.enter": "para abrir estado", + "keyboard_shortcuts.enter": "para abrir toot", "keyboard_shortcuts.favourite": "para engadir a favoritos", "keyboard_shortcuts.favourites": "para abrir a listaxe dos favoritos", "keyboard_shortcuts.federated": "para abrir a cronoloxÃa federada", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "para deixar de destacar a área de escritura/procura", "keyboard_shortcuts.up": "para mover cara arriba na listaxe", "lightbox.close": "Fechar", + "lightbox.compress": "Comprimir a caixa de vista da imaxe", + "lightbox.expand": "Expandir a caixa de vista da imaxe", "lightbox.next": "Seguinte", "lightbox.previous": "Anterior", - "lightbox.view_context": "Ollar contexto", "lists.account.add": "Engadir á listaxe", "lists.account.remove": "Eliminar da listaxe", "lists.delete": "Eliminar listaxe", @@ -260,14 +266,20 @@ "lists.edit.submit": "Mudar o tÃtulo", "lists.new.create": "Engadir listaxe", "lists.new.title_placeholder": "TÃtulo da nova listaxe", + "lists.replies_policy.followed": "Toda usuaria seguida", + "lists.replies_policy.list": "Membros da lista", + "lists.replies_policy.none": "Ninguén", + "lists.replies_policy.title": "Mostrar respostas a:", "lists.search": "Procurar entre as persoas que segues", "lists.subheading": "As túas listaxes", "load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}", "loading_indicator.label": "Estase a cargar...", - "media_gallery.toggle_visible": "Trocar visibilidade", + "media_gallery.toggle_visible": "Agochar {number, plural, one {imaxe} other {imaxes}}", "missing_indicator.label": "Non atopado", "missing_indicator.sublabel": "Este recurso non foi atopado", + "mute_modal.duration": "Duración", "mute_modal.hide_notifications": "Agochar notificacións desta usuaria?", + "mute_modal.indefinite": "Indefinida", "navigation_bar.apps": "Aplicacións móbiles", "navigation_bar.blocks": "Usuarias bloqueadas", "navigation_bar.bookmarks": "Marcadores", @@ -291,13 +303,14 @@ "navigation_bar.preferences": "Preferencias", "navigation_bar.public_timeline": "CronoloxÃa federada", "navigation_bar.security": "Seguranza", - "notification.favourite": "{name} marcou o teu estado coma favorito", + "notification.favourite": "{name} marcou o teu toot coma favorito", "notification.follow": "{name} comezou a seguirte", "notification.follow_request": "{name} solicitou seguirte", "notification.mention": "{name} mencionoute", "notification.own_poll": "A túa enquisa rematou", "notification.poll": "Unha enquisa na que votaches rematou", - "notification.reblog": "{name} compartiu o teu estado", + "notification.reblog": "{name} compartiu o teu toot", + "notification.status": "{name} publicou", "notifications.clear": "Limpar notificacións", "notifications.clear_confirmation": "Tes a certeza de querer limpar de xeito permanente todas as túas notificacións?", "notifications.column_settings.alert": "Notificacións de escritorio", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Promocións:", "notifications.column_settings.show": "Amosar en columna", "notifications.column_settings.sound": "Reproducir son", + "notifications.column_settings.status": "Novos toots:", "notifications.filter.all": "Todo", "notifications.filter.boosts": "Compartidos", "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguimentos", "notifications.filter.mentions": "Mencións", "notifications.filter.polls": "Resultados da enquisa", + "notifications.filter.statuses": "Actualizacións de xente á que segues", + "notifications.grant_permission": "Conceder permiso.", "notifications.group": "{count} notificacións", + "notifications.mark_as_read": "Marcar todas as notificacións como lidas", + "notifications.permission_denied": "Non se activaron as notificacións de escritorio porque se denegou o permiso", + "notifications.permission_denied_alert": "Non se poden activar as notificacións de escritorio, xa que o permiso para o navegador foi denegado previamente", + "notifications.permission_required": "As notificacións de escritorio non están dispoñibles porque non se concedeu o permiso necesario.", + "notifications_permission_banner.enable": "Activar notificacións de escritorio", + "notifications_permission_banner.how_to_control": "Activa as notificacións de escritorio para recibir notificacións mentras Mastodon non está aberto. Podes controlar de xeito preciso o tipo de interaccións que crean as notificacións de escritorio a través da {icon} superior unha vez están activadas.", + "notifications_permission_banner.title": "Non perder nada", + "picture_in_picture.restore": "Devolver", "poll.closed": "Pechado", "poll.refresh": "Actualizar", "poll.total_people": "{count, plural,one {# persoa} other {# persoas}}", @@ -338,7 +362,7 @@ "privacy.unlisted.long": "Non publicar nas cronoloxÃas públicas", "privacy.unlisted.short": "Non listado", "refresh": "Actualizar", - "regeneration_indicator.label": "Cargando…", + "regeneration_indicator.label": "Estase a cargar…", "regeneration_indicator.sublabel": "Estase a preparar a túa cronoloxÃa de inicio!", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", @@ -355,9 +379,9 @@ "report.target": "Denunciar a {target}", "search.placeholder": "Procurar", "search_popout.search_format": "Formato de procura avanzada", - "search_popout.tips.full_text": "Texto simple devolve estados que ti escribiches, promoviches, marcaches favoritos, ou foches mencionada, asà como nomes de usuaria coincidentes, nomes públicos e cancelos.", + "search_popout.tips.full_text": "Texto simple devolve toots que ti escribiches, promoviches, marcaches favoritos, ou foches mencionada, asà como nomes de usuaria coincidentes, nomes públicos e cancelos.", "search_popout.tips.hashtag": "cancelo", - "search_popout.tips.status": "estado", + "search_popout.tips.status": "toot", "search_popout.tips.text": "Texto simple devolve coincidencias con nomes públicos, nomes de usuaria e cancelos", "search_popout.tips.user": "usuaria", "search_results.accounts": "Persoas", @@ -366,12 +390,12 @@ "search_results.statuses_fts_disabled": "Procurar toots polo seu contido non está activado neste servidor do Mastodon.", "search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}", "status.admin_account": "Abrir interface de moderación para @{name}", - "status.admin_status": "Abrir este estado na interface de moderación", + "status.admin_status": "Abrir este toot na interface de moderación", "status.block": "Bloquear a @{name}", "status.bookmark": "Marcar", "status.cancel_reblog_private": "Desfacer compartido", "status.cannot_reblog": "Esta publicación non pode ser promovida", - "status.copy": "Copiar ligazón ó estado", + "status.copy": "Copiar ligazón ó toot", "status.delete": "Eliminar", "status.detailed_status": "Vista detallada da conversa", "status.direct": "Mensaxe directa a @{name}", @@ -384,12 +408,12 @@ "status.more": "Máis", "status.mute": "Silenciar @{name}", "status.mute_conversation": "Silenciar conversa", - "status.open": "Expandir este estado", + "status.open": "Expandir este toot", "status.pin": "Fixar no perfil", "status.pinned": "Toot fixado", "status.read_more": "Ler máis", "status.reblog": "Promover", - "status.reblog_private": "Compartir á audiencia orixinal", + "status.reblog_private": "Compartir coa audiencia orixinal", "status.reblogged_by": "{name} promoveu", "status.reblogs.empty": "AÃnda ninguén promoveu este toot. Cando alguén o faga, amosarase aquÃ.", "status.redraft": "Eliminar e reescribir", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Arrastra e solta para subir", - "upload_button.label": "Engadir multimedia ({formats})", + "upload_button.label": "Engadir imaxes, un vÃdeo ou ficheiro de audio", "upload_error.limit": "LÃmite máximo do ficheiro a subir excedido.", "upload_error.poll": "Non se poden subir ficheiros nas enquisas.", "upload_form.audio_description": "Describir para persoas con problemas auditivos", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detectar texto na imaxe", "upload_modal.edit_media": "Editar multimedia", "upload_modal.hint": "Preme ou arrastra o cÃrculo na vista previa para escoller o punto focal que sempre estará á vista en todas as miniaturas.", + "upload_modal.preparing_ocr": "Preparando OCR…", "upload_modal.preview_label": "Vista previa ({ratio})", "upload_progress.label": "Estase a subir...", "video.close": "Pechar vÃdeo", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 91fce039f5bb07a4b55cd8407cd5eb54e7d0b730..123b2e85541a7f89107fee68cb77c621eab7906f 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "המשך לגלוש בפרופיל המקורי", "account.cancel_follow_request": "בטל בקשת מעקב", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "הדומיין חסוי", "account.edit_profile": "עריכת פרופיל", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "הצג בפרופיל", "account.follow": "מעקב", "account.followers": "עוקבי×", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "ללחוש", "compose_form.publish_loud": "לחצרץ!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "×זהרת תוכן", @@ -147,6 +149,7 @@ "emoji_button.search_results": "תוצ×ות חיפוש", "emoji_button.symbols": "סמלי×", "emoji_button.travel": "×˜×™×•×œ×™× ×•×תרי×", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "×ין התר×ות עדיין. ×™×ללה, ×”×’×™×¢ הזמן להתחיל להתערבב.", "empty_column.public": "×ין פה כלו×! כדי ×œ×ž×œ× ×ת הטור ×”×–×” ×פשר לכתוב משהו, ×ו להתחיל לעקוב ×חרי ×× ×©×™× ×ž×§×”×™×œ×•×ª ×חרות", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "קבלה", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "לצ×ת מתיבת חיבור/חיפוש", "keyboard_shortcuts.up": "×œ× ×•×¢ במעלה הרשימה", "lightbox.close": "סגירה", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "הל××”", "lightbox.previous": "הקוד×", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "× ×¨××”\\בלתי × ×¨××”", "missing_indicator.label": "×œ× × ×ž×¦×", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "להסתיר הודעות מחשבון ×–×”?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "חסימות", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "חצרוצך הודהד על ידי {name}", + "notification.status": "{name} just posted", "notifications.clear": "הסרת התר×ות", "notifications.clear_confirmation": "להסיר ×ת כל ההתר×ות? בטוח?", "notifications.column_settings.alert": "התר×ות לשולחן העבודה", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "הדהודי×:", "notifications.column_settings.show": "הצגה בטור", "notifications.column_settings.sound": "שמע מופעל", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "הדהוד", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "הודהד על ידי {name}", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "עולה...", "video.close": "סגירת ויד×ו", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index ff207d6406f64eb305435f56e88ecd0feed96182..7e0fe4e7a723fedea6f1b884b7359bf311f14442 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤", "account.add_or_remove_from_list": "सूची में जोड़ें या हटाà¤", "account.badges.bot": "बॉट", - "account.badges.group": "Group", + "account.badges.group": "समूह", "account.block": "@{name} को बà¥à¤²à¥‰à¤• करें", "account.block_domain": "{domain} के सारी चीज़े छà¥à¤ªà¤¾à¤à¤‚", "account.blocked": "बà¥à¤²à¥‰à¤•", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "मूल पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² पर अधिक बà¥à¤°à¤¾à¤‰à¤œà¤¼ करें", "account.cancel_follow_request": "फ़ॉलो रिकà¥à¤µà¥‡à¤¸à¥à¤Ÿ रदà¥à¤¦ करें", "account.direct": "पà¥à¤°à¤¤à¥à¤¯à¤•à¥à¤· संदेश @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "छिपा हà¥à¤† डोमेन", "account.edit_profile": "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² संपादित करें", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² पर दिखाà¤", "account.follow": "फॉलो करें", "account.followers": "फॉलोवर", "account.followers.empty": "कोई à¤à¥€ इस यूज़रॠको फ़ॉलो नहीं करता है", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} अनà¥à¤—ामी} other {{counter} समरà¥à¤¥à¤•}}", + "account.following_counter": "{count, plural, one {{counter} निमà¥à¤¨à¤²à¤¿à¤–ित} other {{counter} निमà¥à¤¨à¤²à¤¿à¤–ित}}", "account.follows.empty": "यह यूज़रॠअà¤à¥€ तक किसी को फॉलो नहीं करता है।", "account.follows_you": "आपको फॉलो करता है", "account.hide_reblogs": "@{name} के बूसà¥à¤Ÿ छà¥à¤ªà¤¾à¤à¤‚", @@ -36,19 +38,19 @@ "account.requested": "मंजूरी का इंतजार। फॉलो रिकà¥à¤µà¥‡à¤¸à¥à¤Ÿ को रदà¥à¤¦ करने के लिठकà¥à¤²à¤¿à¤• करें", "account.share": "@{name} की पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤² शेयर करे", "account.show_reblogs": "@{name} के बूसà¥à¤Ÿ दिखाà¤", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} à¤à¥‹à¤‚पू} other {{counter} à¤à¥‹à¤‚पू}}", "account.unblock": "@{name} को अनबà¥à¤²à¥‰à¤• करें", "account.unblock_domain": "{domain} दिखाà¤", "account.unendorse": "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² पर न दिखाà¤", "account.unfollow": "अनफॉलो करें", "account.unmute": "अनमà¥à¤¯à¥‚ट @{name}", "account.unmute_notifications": "@{name} के नोटिफिकेशन अनमà¥à¤¯à¥‚ट करे", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "नोटà¥à¤¸ जोड़ने के लिठकà¥à¤²à¤¿à¤• करें", "alert.rate_limited.message": "कृपà¥à¤¯à¤¾ {retry_time, time, medium} के बाद दà¥à¤¬à¤¾à¤°à¤¾ कोशिश करें", "alert.rate_limited.title": "सीमित दर", "alert.unexpected.message": "à¤à¤• अपà¥à¤°à¤¤à¥à¤¯à¤¾à¤¶à¤¿à¤¤ तà¥à¤°à¥à¤Ÿà¤¿ हà¥à¤ˆ है!", "alert.unexpected.title": "उफ़!", - "announcement.announcement": "Announcement", + "announcement.announcement": "घोषणा", "autosuggest_hashtag.per_week": "{count} हर सपà¥à¤¤à¤¾à¤¹", "boost_modal.combo": "अगली बार सà¥à¤•िप करने के लिठआप {combo} दबा सकते है", "bundle_column_error.body": "इस कॉमà¥à¤ªà¥‹à¤¨à¥‡à¤¨à¥à¤Ÿ को लोड करते वकà¥à¤¤ कà¥à¤› गलत हो गया", @@ -58,7 +60,7 @@ "bundle_modal_error.message": "इस कॉमà¥à¤ªà¥‹à¤¨à¥‡à¤¨à¥à¤Ÿ को लोड करते वकà¥à¤¤ कà¥à¤› गलत हो गया", "bundle_modal_error.retry": "दà¥à¤¬à¤¾à¤°à¤¾ कोशिश करें", "column.blocks": "बà¥à¤²à¥‰à¤•à¥à¤¡ यूज़रà¥à¤¸", - "column.bookmarks": "Bookmarks", + "column.bookmarks": "पà¥à¤¸à¥à¤¤à¤•चिहà¥à¤¨:", "column.community": "लोकल टाइमà¥à¤²à¤¾à¤‡à¤¨", "column.direct": "सीधा संदेश", "column.directory": "पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤²à¥à¤¸ खोजें", @@ -79,9 +81,9 @@ "column_header.show_settings": "सेटिंगà¥à¤¸ दिखाà¤à¤", "column_header.unpin": "अनपिन", "column_subheading.settings": "सेटिंगà¥à¤¸", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "सà¥à¤¥à¤¾à¤¨à¥€à¤¯ ही", "community.column_settings.media_only": "सिरà¥à¤«à¤¼ मीडिया", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "केवल सà¥à¤¦à¥‚र", "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.", "compose_form.direct_message_warning_learn_more": "और जानें", "compose_form.hashtag_warning": "यह टूटॠकिसी à¤à¥€ हैशटैग के तहत सूचीबदà¥à¤§ नहीं होगा कà¥à¤¯à¥‹à¤‚कि यह अनलिसà¥à¤Ÿà¥‡à¤¡ है। हैशटैग दà¥à¤µà¤¾à¤°à¤¾ केवल सारà¥à¤µà¤œà¤¨à¤¿à¤• टूटà¥à¤¸ खोजे जा सकते हैं।", @@ -92,8 +94,8 @@ "compose_form.poll.duration": "चà¥à¤¨à¤¾à¤µ की अवधि", "compose_form.poll.option_placeholder": "कà¥à¤² विकलà¥à¤ª {number}", "compose_form.poll.remove_option": "इस विकलà¥à¤ª को हटाà¤à¤", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.poll.switch_to_multiple": "कई विकलà¥à¤ªà¥‹à¤‚ की अनà¥à¤®à¤¤à¤¿ देने के लिठपोल बदलें", + "compose_form.poll.switch_to_single": "à¤à¤• ही विकलà¥à¤ª के लिठअनà¥à¤®à¤¤à¤¿ देने के लिठपोल बदलें", "compose_form.publish": "टूटà¥", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.hide": "मीडिया को संवेदनशील के रूप में चिहà¥à¤¨à¤¿à¤¤ करें", @@ -147,10 +149,11 @@ "emoji_button.search_results": "खोज परिणाम", "emoji_button.symbols": "पà¥à¤°à¤¤à¥€à¤•", "emoji_button.travel": "यातà¥à¤°à¤¾ à¤à¤µà¤‚ सà¥à¤¥à¤¾à¤¨", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "सनà¥à¤¨à¤¾à¤Ÿà¤¾! यहां कोई टूटà¥à¤¸ नहीं!", "empty_column.account_unavailable": "पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤² उपलबà¥à¤§ नहीं", "empty_column.blocks": "आप अà¤à¥€ तक किसी à¤à¥€ यूजर के दà¥à¤µà¤¾à¤°à¤¾ बà¥à¤²à¥‰à¤•à¥à¤¡ नहीं हो।", - "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", + "empty_column.bookmarked_statuses": "आपके पास अà¤à¥€ तक कोई बà¥à¤•मारà¥à¤• नहीं है। जब आप à¤à¤• बà¥à¤•मारà¥à¤• करते हैं, तो यह यहां दिखाई देगा।", "empty_column.community": "लोकल टाइमà¥à¤²à¤¾à¤‡à¤¨ खाली है, कà¥à¤› देखने के लिये सारà¥à¤µà¤œà¤¨à¤¿à¤• रूप से कà¥à¤› लिखें!", "empty_column.direct": "आपके पास कोई सीधा सनà¥à¤¦à¥‡à¤¶ नहीं है, जब आप कोई à¤à¥‡à¤œà¥‡à¤‚गे पà¥à¤°à¤¾à¤ªà¥à¤¤ करेंगे तो यहाठदिखेगा।", "empty_column.domain_blocks": "अà¤à¥€ तक कोई छà¥à¤ªà¤¾ हà¥à¤† डोमेन नहीं है।", @@ -161,17 +164,19 @@ "empty_column.home": "आपकी मà¥à¤–à¥à¤¯ कालकà¥à¤°à¤® अà¤à¥€ खली है. अनà¥à¤¯ उपयोगकरà¥à¤¤à¤¾à¤“ं से मिलने के लिठऔर अपनी गतिविधियां शà¥à¤°à¥‚ करने के लिठया तो {public} पर जाà¤à¤‚ या खोज का उपयोग करें।", "empty_column.home.public_timeline": "सारà¥à¤µà¤œà¤¨à¤¿à¤• कालकà¥à¤°à¤®", "empty_column.list": "यह सूची अà¤à¥€ खाली है. जब इसके सदसà¥à¤¯ कोई अà¤à¤¿à¤µà¥à¤¯à¤•à¥à¤¤à¤¿ देंगे, तो वो यहां दिखाई देंगी.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", - "empty_column.mutes": "You haven't muted any users yet.", - "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", - "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", - "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "empty_column.lists": "आपके पास अà¤à¥€ तक कोई सूची नहीं है। जब आप à¤à¤• बनाते हैं, तो यह यहां दिखाई देगा।", + "empty_column.mutes": "आपने अà¤à¥€ तक किसी à¤à¥€ उपयोगकरà¥à¤¤à¤¾ को मà¥à¤¯à¥‚ट नहीं किया है।", + "empty_column.notifications": "आपके पास अà¤à¥€ तक कोई सूचना नहीं है। बातचीत शà¥à¤°à¥‚ करने के लिठदूसरों के साथ बातचीत करें।", + "empty_column.public": "यहां कà¥à¤› नहीं है! सारà¥à¤µà¤œà¤¨à¤¿à¤• रूप से कà¥à¤› लिखें, या इसे à¤à¤°à¤¨à¥‡ के लिठअनà¥à¤¯ सरà¥à¤µà¤° से उपयोगकरà¥à¤¤à¤¾à¤“ं का मैनà¥à¤¯à¥à¤…ल रूप से अनà¥à¤¸à¤°à¤£ करें", + "error.unexpected_crash.explanation": "हमारे कोड या बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤° संगतता समसà¥à¤¯à¤¾ में बग के कारण, यह पृषà¥à¤ सही ढंग से पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ नहीं हो सका।", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", - "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "सà¥à¤Ÿà¥ˆà¤•टà¥à¤°à¥‡à¤¸ को कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡ पर कॉपी करें", "errors.unexpected_crash.report_issue": "समसà¥à¤¯à¤¾ सूचित करें", "follow_request.authorize": "अधिकार दें", "follow_request.reject": "असà¥à¤µà¥€à¤•ार करें", - "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", + "follow_requests.unlocked_explanation": "हालाà¤à¤•ि आपका खाता लॉक नहीं है, फिर à¤à¥€ {domain} डोमेन सà¥à¤Ÿà¤¾à¤« ने सोचा कि आप इन खातों के मैनà¥à¤¯à¥à¤…ल अनà¥à¤°à¥‹à¤§à¥‹à¤‚ की समीकà¥à¤·à¤¾ करना चाहते हैं।", "generic.saved": "Saved", "getting_started.developers": "डेवॅलपरà¥à¤¸", "getting_started.directory": "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² निरà¥à¤¦à¥‡à¤¶à¤¿à¤•ा", @@ -193,31 +198,31 @@ "home.column_settings.basic": "बà¥à¤¨à¤¿à¤¯à¤¾à¤¦à¥€", "home.column_settings.show_reblogs": "बूसà¥à¤Ÿ दिखाà¤", "home.column_settings.show_replies": "जवाबों को दिखाà¤", - "home.hide_announcements": "Hide announcements", - "home.show_announcements": "Show announcements", + "home.hide_announcements": "घोषणाà¤à¤ छिपाà¤à¤", + "home.show_announcements": "घोषणाà¤à¤‚ दिखाà¤à¤‚", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", "introduction.federation.action": "अगला", "introduction.federation.federated.headline": "फ़ेडरेटेड", - "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.federated.text": "महासंघ के अनà¥à¤¯ सरà¥à¤µà¤°à¥‹à¤‚ से सारà¥à¤µà¤œà¤¨à¤¿à¤• पद संघटित समय-सीमा में दिखाई देंगे।", "introduction.federation.home.headline": "होम", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", + "introduction.federation.home.text": "आपके दà¥à¤µà¤¾à¤°à¤¾ अनà¥à¤¸à¤°à¤£ किठजाने वाले लोगों के पोसà¥à¤Ÿ आपके होम फीड में दिखाई देंगे। आप किसी à¤à¥€ सरà¥à¤µà¤° पर किसी को à¤à¥€ फॉलो कर सकते हैं!", "introduction.federation.local.headline": "लोकल", "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", "introduction.interactions.action": "Finish toot-orial!", "introduction.interactions.favourite.headline": "पसंदीदा", - "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", + "introduction.interactions.favourite.text": "आप बाद में इसके लिठà¤à¤• टोट को बचा सकते हैं, और लेखक को यह बता दें कि आपको यह पसंद आया, इसे फेवर करके।", "introduction.interactions.reblog.headline": "बूसà¥à¤Ÿ", "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", "introduction.interactions.reply.headline": "जवाब", "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", "introduction.welcome.action": "आइठशà¥à¤°à¥‚ करते हैं!", "introduction.welcome.headline": "पहले कदम", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", - "keyboard_shortcuts.back": "to navigate back", - "keyboard_shortcuts.blocked": "to open blocked users list", - "keyboard_shortcuts.boost": "to boost", + "introduction.welcome.text": "फेडवरà¥à¤¸ में आपका सà¥à¤µà¤¾à¤—त है! कà¥à¤› ही कà¥à¤·à¤£à¥‹à¤‚ में, आप संदेशों को पà¥à¤°à¤¸à¤¾à¤°à¤¿à¤¤ करने और अपने दोसà¥à¤¤à¥‹à¤‚ से विसà¥à¤¤à¥ƒà¤¤ सरà¥à¤µà¤° पर बात करने में सकà¥à¤·à¤® होंगे। लेकिन यह सरà¥à¤µà¤°, {domain}, विशेष है - यह आपकी पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² को होसà¥à¤Ÿ करता है, इसलिठइसका नाम याद रखें।", + "keyboard_shortcuts.back": "वापस जाने के लिà¤", + "keyboard_shortcuts.blocked": "अवरà¥à¤¦à¥à¤§ उपयोगकरà¥à¤¤à¤¾à¤“ं की सूची खोलने के लिà¤", + "keyboard_shortcuts.boost": "बढ़ावा देने के लिà¤", "keyboard_shortcuts.column": "to focus a status in one of the columns", "keyboard_shortcuts.compose": "कंपोज़ टेकà¥à¤¸à¥à¤Ÿ-à¤à¤°à¤¿à¤¯à¤¾ पर धà¥à¤¯à¤¾à¤¨ केंदà¥à¤°à¤¿à¤¤ करने के लिà¤", "keyboard_shortcuts.description": "विवरण", @@ -249,42 +254,49 @@ "keyboard_shortcuts.toot": "to start a brand new toot", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", - "lightbox.close": "Close", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lightbox.view_context": "View context", + "lightbox.close": "बंद करें", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "अगला", + "lightbox.previous": "पिछला", "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.delete": "Delete list", - "lists.edit": "Edit list", + "lists.account.remove": "सूची से निकालें", + "lists.delete": "सूची हटाà¤à¤", + "lists.edit": "सूची संपादित करें", "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", + "lists.new.create": "सूची जोड़ें", + "lists.new.title_placeholder": "नये सूची का शीरà¥à¤·à¤•", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lists.subheading": "आपकी सूचियाà¤", "load_pending": "{count, plural, one {# new item} other {# new items}}", "loading_indicator.label": "लोड हो रहा है...", "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "नहीं मिला", "missing_indicator.sublabel": "यह संसाधन नहीं मिल सका।", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "मोबाइल à¤à¤ªà¥à¤²à¤¿à¤•ेशंस", "navigation_bar.blocks": "बà¥à¤²à¥‰à¤•à¥à¤¡ यूज़रà¥à¤¸", - "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.bookmarks": "पà¥à¤¸à¥à¤¤à¤•चिहà¥à¤¨:", "navigation_bar.community_timeline": "लोकल टाइमà¥à¤²à¤¾à¤‡à¤¨", "navigation_bar.compose": "नया टूटॠलिखें", - "navigation_bar.direct": "Direct messages", - "navigation_bar.discover": "Discover", + "navigation_bar.direct": "सीधा संदेश", + "navigation_bar.discover": "खोजें", "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.edit_profile": "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤² संपादित करें", "navigation_bar.favourites": "Favourites", "navigation_bar.filters": "Muted words", - "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.follow_requests": "अनà¥à¤¸à¤°à¤£ करने के अनà¥à¤°à¥‹à¤§", "navigation_bar.follows_and_followers": "Follows and followers", - "navigation_bar.info": "About this server", + "navigation_bar.info": "इस सरà¥à¤µà¤° के बारे में", "navigation_bar.keyboard_shortcuts": "Hotkeys", - "navigation_bar.lists": "Lists", - "navigation_bar.logout": "Logout", + "navigation_bar.lists": "सूचियाà¤", + "navigation_bar.logout": "बाहर जाà¤", "navigation_bar.mutes": "Muted users", "navigation_bar.personal": "Personal", "navigation_bar.pins": "Pinned toots", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "बूसà¥à¤Ÿ:", "notifications.column_settings.show": "कॉलम में दिखाà¤à¤", "notifications.column_settings.sound": "धà¥à¤µà¤¨à¤¿ चलाà¤à¤", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "सà¤à¥€", "notifications.filter.boosts": "बूसà¥à¤Ÿ", "notifications.filter.favourites": "पसंदीदा", "notifications.filter.follows": "फॉलो", "notifications.filter.mentions": "उलà¥à¤²à¥‡à¤–", "notifications.filter.polls": "चà¥à¤¨à¤¾à¤µ परिणाम", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} सूचनाà¤à¤", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "बंद कर दिया", "poll.refresh": "रीफà¥à¤°à¥‡à¤¶ करें", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "बूसà¥à¤Ÿ", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "मीडिया में संशोधन करें", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "अपलोडिंग...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index 7179bc5364092161cc228c70bf02503a5fb226bd..f1b78eda42581490e4a5810b3e97fdd4f1622e45 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -1,366 +1,390 @@ { - "account.account_note_header": "Note", - "account.add_or_remove_from_list": "Add or Remove from lists", + "account.account_note_header": "BiljeÅ¡ka", + "account.add_or_remove_from_list": "Dodaj ili ukloni s liste", "account.badges.bot": "Bot", - "account.badges.group": "Group", + "account.badges.group": "Grupa", "account.block": "Blokiraj @{name}", - "account.block_domain": "Sakrij sve sa {domain}", - "account.blocked": "Blocked", - "account.browse_more_on_origin_server": "Browse more on the original profile", - "account.cancel_follow_request": "Cancel follow request", - "account.direct": "Direct Message @{name}", - "account.domain_blocked": "Domain hidden", + "account.block_domain": "Blokiraj domenu {domain}", + "account.blocked": "Blokirano", + "account.browse_more_on_origin_server": "Pogledajte viÅ¡e na izvornom profilu", + "account.cancel_follow_request": "Otkaži zahtjev za praćenje", + "account.direct": "PoÅ¡alji poruku @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", + "account.domain_blocked": "Domena je blokirana", "account.edit_profile": "Uredi profil", - "account.endorse": "Feature on profile", - "account.follow": "Slijedi", - "account.followers": "Sljedbenici", - "account.followers.empty": "No one follows this user yet.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", - "account.follows.empty": "This user doesn't follow anyone yet.", - "account.follows_you": "te slijedi", - "account.hide_reblogs": "Hide boosts from @{name}", - "account.last_status": "Last active", - "account.link_verified_on": "Ownership of this link was checked on {date}", - "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", - "account.media": "Media", + "account.enable_notifications": "Notify me when @{name} posts", + "account.endorse": "Istakni na profilu", + "account.follow": "Prati", + "account.followers": "Pratitelji", + "account.followers.empty": "Nitko joÅ¡ ne prati korisnika/cu.", + "account.followers_counter": "{count, plural, one {{counter} pratitelj} other {{counter} pratitelja}}", + "account.following_counter": "{count, plural, one {{counter} praćeni} few{{counter} praćena} other {{counter} praćenih}}", + "account.follows.empty": "Korisnik/ca joÅ¡ ne prati nikoga.", + "account.follows_you": "Prati te", + "account.hide_reblogs": "Sakrij boostove od @{name}", + "account.last_status": "Posljednja aktivnost", + "account.link_verified_on": "VlasniÅ¡tvo ove poveznice provjereno je {date}", + "account.locked_info": "Status privatnosti ovog raÄuna postavljen je na zakljuÄano. Vlasnik ruÄno pregledava tko ih može pratiti.", + "account.media": "Medijski sadržaj", "account.mention": "Spomeni @{name}", - "account.moved_to": "{name} has moved to:", + "account.moved_to": "RaÄun {name} je premjeÅ¡ten na:", "account.mute": "UtiÅ¡aj @{name}", - "account.mute_notifications": "Mute notifications from @{name}", - "account.muted": "Muted", - "account.never_active": "Never", - "account.posts": "Postovi", - "account.posts_with_replies": "Toots with replies", + "account.mute_notifications": "UtiÅ¡aj obavijesti od @{name}", + "account.muted": "UtiÅ¡ano", + "account.never_active": "Nikad", + "account.posts": "Tootovi", + "account.posts_with_replies": "Tootovi i odgovori", "account.report": "Prijavi @{name}", - "account.requested": "ÄŒeka pristanak", - "account.share": "Share @{name}'s profile", - "account.show_reblogs": "Show boosts from @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.requested": "ÄŒekanje na potvrdu. Kliknite za otkazivanje zahtjeva za praćenje", + "account.share": "Podijeli profil @{name}", + "account.show_reblogs": "Prikaži boostove od @{name}", + "account.statuses_counter": "{count, plural, one {{counter} toot} other {{counter} toota}}", "account.unblock": "Deblokiraj @{name}", - "account.unblock_domain": "PoniÅ¡ti sakrivanje {domain}", - "account.unendorse": "Don't feature on profile", - "account.unfollow": "Prestani slijediti", + "account.unblock_domain": "Deblokiraj domenu {domain}", + "account.unendorse": "Ne istiÄi na profilu", + "account.unfollow": "Prestani pratiti", "account.unmute": "PoniÅ¡ti utiÅ¡avanje @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", - "account_note.placeholder": "Click to add a note", - "alert.rate_limited.message": "Please retry after {retry_time, time, medium}.", - "alert.rate_limited.title": "Rate limited", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", - "announcement.announcement": "Announcement", - "autosuggest_hashtag.per_week": "{count} per week", - "boost_modal.combo": "MožeÅ¡ pritisnuti {combo} kako bi ovo preskoÄio sljedeći put", - "bundle_column_error.body": "Something went wrong while loading this component.", - "bundle_column_error.retry": "Try again", - "bundle_column_error.title": "Network error", - "bundle_modal_error.close": "Close", - "bundle_modal_error.message": "Something went wrong while loading this component.", - "bundle_modal_error.retry": "Try again", + "account.unmute_notifications": "Ne utiÅ¡avaj obavijesti od @{name}", + "account_note.placeholder": "Kliknite za dodavanje biljeÅ¡ke", + "alert.rate_limited.message": "Molimo pokuÅ¡ajte nakon {retry_time, time, medium}.", + "alert.rate_limited.title": "OgraniÄenje uÄestalosti", + "alert.unexpected.message": "Dogodila se neoÄekivana greÅ¡ka.", + "alert.unexpected.title": "Ups!", + "announcement.announcement": "Najava", + "autosuggest_hashtag.per_week": "{count} tjedno", + "boost_modal.combo": "Možete pritisnuti {combo} kako biste preskoÄili ovo sljedeći put", + "bundle_column_error.body": "NeÅ¡to je poÅ¡lo po zlu tijekom uÄitavanja ove komponente.", + "bundle_column_error.retry": "PokuÅ¡ajte ponovno", + "bundle_column_error.title": "GreÅ¡ka mreže", + "bundle_modal_error.close": "Zatvori", + "bundle_modal_error.message": "NeÅ¡to je poÅ¡lo po zlu tijekom uÄitavanja ove komponente.", + "bundle_modal_error.retry": "PokuÅ¡ajte ponovno", "column.blocks": "Blokirani korisnici", - "column.bookmarks": "Bookmarks", - "column.community": "Lokalni timeline", - "column.direct": "Direct messages", - "column.directory": "Browse profiles", - "column.domain_blocks": "Hidden domains", + "column.bookmarks": "Knjižne oznake", + "column.community": "Lokalna vremenska crta", + "column.direct": "Izravne poruke", + "column.directory": "Pregledavanje profila", + "column.domain_blocks": "Blokirane domene", "column.favourites": "Favoriti", - "column.follow_requests": "Zahtjevi za slijeÄ‘enje", - "column.home": "Dom", - "column.lists": "Lists", + "column.follow_requests": "Zahtjevi za praćenje", + "column.home": "PoÄetna", + "column.lists": "Liste", "column.mutes": "UtiÅ¡ani korisnici", - "column.notifications": "Notifikacije", - "column.pins": "Pinned toot", - "column.public": "Federalni timeline", + "column.notifications": "Obavijesti", + "column.pins": "PrikvaÄeni tootovi", + "column.public": "Federalna vremenska crta", "column_back_button.label": "Natrag", - "column_header.hide_settings": "Hide settings", - "column_header.moveLeft_settings": "Move column to the left", - "column_header.moveRight_settings": "Move column to the right", - "column_header.pin": "Pin", - "column_header.show_settings": "Show settings", - "column_header.unpin": "Unpin", + "column_header.hide_settings": "Sakrij postavke", + "column_header.moveLeft_settings": "Pomakni stupac ulijevo", + "column_header.moveRight_settings": "Pomakni stupac udesno", + "column_header.pin": "PrikvaÄi", + "column_header.show_settings": "Prikaži postavke", + "column_header.unpin": "OtkvaÄi", "column_subheading.settings": "Postavke", - "community.column_settings.local_only": "Local only", - "community.column_settings.media_only": "Media only", - "community.column_settings.remote_only": "Remote only", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", - "compose_form.direct_message_warning_learn_more": "Learn more", - "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", - "compose_form.lock_disclaimer": "Tvoj raÄun nije {locked}. Svatko te može slijediti kako bi vidio postove namijenjene samo tvojim sljedbenicima.", + "community.column_settings.local_only": "Samo lokalno", + "community.column_settings.media_only": "Samo medijski sadržaj", + "community.column_settings.remote_only": "Samo udaljeno", + "compose_form.direct_message_warning": "Ovaj toot bit će poslan samo spomenutim korisnicima.", + "compose_form.direct_message_warning_learn_more": "Saznajte viÅ¡e", + "compose_form.hashtag_warning": "Ovaj toot neće biti prikazan ni pod jednim hashtagom jer je postavljen kao neprikazan. Samo javni tootovi mogu biti pretraživani pomoći hashtagova.", + "compose_form.lock_disclaimer": "VaÅ¡ raÄun nije {locked}. Svatko Vas može pratiti kako bi vidjeli objave namijenjene VaÅ¡im pratiteljima.", "compose_form.lock_disclaimer.lock": "zakljuÄan", "compose_form.placeholder": "Å to ti je na umu?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", - "compose_form.publish": "Toot", + "compose_form.poll.add_option": "Dodaj opciju", + "compose_form.poll.duration": "Trajanje ankete", + "compose_form.poll.option_placeholder": "Opcija {number}", + "compose_form.poll.remove_option": "Ukloni ovu opciju", + "compose_form.poll.switch_to_multiple": "Omogući viÅ¡estruki odabir opcija ankete", + "compose_form.poll.switch_to_single": "Omogući odabir samo jedne opcije ankete", + "compose_form.publish": "Tootni", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", - "compose_form.spoiler_placeholder": "Upozorenje o sadržaju", + "compose_form.sensitive.hide": "OznaÄi medijski sadržaj kao osjetljiv", + "compose_form.sensitive.marked": "Medijski sadržaj oznaÄen je kao osjetljiv", + "compose_form.sensitive.unmarked": "Medijski sadržaj nije oznaÄen kao osjetljiv", + "compose_form.spoiler.marked": "Tekst je skriven iza upozorenja", + "compose_form.spoiler.unmarked": "Tekst nije skriven", + "compose_form.spoiler_placeholder": "Ovdje upiÅ¡ite upozorenje", "confirmation_modal.cancel": "Otkaži", - "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.block_and_report": "Blokiraj i prijavi", "confirmations.block.confirm": "Blokiraj", - "confirmations.block.message": "ŽeliÅ¡ li sigurno blokirati {name}?", + "confirmations.block.message": "Sigurno želite blokirati {name}?", "confirmations.delete.confirm": "ObriÅ¡i", - "confirmations.delete.message": "ŽeliÅ¡ li stvarno obrisati ovaj status?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", - "confirmations.domain_block.confirm": "Sakrij cijelu domenu", - "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiÅ¡ potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", - "confirmations.logout.confirm": "Log out", - "confirmations.logout.message": "Are you sure you want to log out?", + "confirmations.delete.message": "Stvarno želite obrisati ovaj toot?", + "confirmations.delete_list.confirm": "ObriÅ¡i", + "confirmations.delete_list.message": "Jeste li sigurni da želite trajno obrisati ovu listu?", + "confirmations.domain_block.confirm": "Blokiraj cijelu domenu", + "confirmations.domain_block.message": "Jeste li zaista, zaista sigurni da želite blokirati cijelu domenu {domain}? U većini sluÄajeva dovoljno je i preferirano nekoliko ciljanih blokiranja ili utiÅ¡avanja. Nećete vidjeti sadržaj s te domene ni u kojim javnim vremenskim crtama ili VaÅ¡im obavijestima. VaÅ¡i pratitelji s te domene bit će uklonjeni.", + "confirmations.logout.confirm": "Odjavi se", + "confirmations.logout.message": "Jeste li sigurni da se želite odjaviti?", "confirmations.mute.confirm": "UtiÅ¡aj", - "confirmations.mute.explanation": "This will hide posts from them and posts mentioning them, but it will still allow them to see your posts and follow you.", - "confirmations.mute.message": "Jesi li siguran da želiÅ¡ utiÅ¡ati {name}?", - "confirmations.redraft.confirm": "Delete & redraft", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", - "confirmations.reply.confirm": "Reply", + "confirmations.mute.explanation": "Ovo će sakriti njihove objave i objave koje ih spominju, ali i dalje će im dopuÅ¡tati da vide VaÅ¡e objave i da Vas prate.", + "confirmations.mute.message": "Jeste li sigurni da želite utiÅ¡ati {name}?", + "confirmations.redraft.confirm": "IzbriÅ¡i i ponovno uredi", + "confirmations.redraft.message": "Jeste li sigurni da želite izbrisati ovaj toot i ponovno ga urediti? Favoriti i boostovi bit će izgubljeni, a odgovori na izvornu objavu bit će odvojeni.", + "confirmations.reply.confirm": "Odgovori", "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", - "confirmations.unfollow.confirm": "Unfollow", + "confirmations.unfollow.confirm": "Prestani pratiti", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", - "conversation.delete": "Delete conversation", - "conversation.mark_as_read": "Mark as read", - "conversation.open": "View conversation", - "conversation.with": "With {names}", + "conversation.delete": "IzbriÅ¡i razgovor", + "conversation.mark_as_read": "OznaÄi kao proÄitano", + "conversation.open": "Prikaži razgovor", + "conversation.with": "S {names}", "directory.federated": "From known fediverse", - "directory.local": "From {domain} only", + "directory.local": "Samo iz {domain}", "directory.new_arrivals": "New arrivals", - "directory.recently_active": "Recently active", + "directory.recently_active": "Nedavno aktivni", "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", + "embed.preview": "Evo kako će izgledati:", "emoji_button.activity": "Aktivnost", - "emoji_button.custom": "Custom", + "emoji_button.custom": "PrilagoÄ‘eno", "emoji_button.flags": "Zastave", - "emoji_button.food": "Hrana & Piće", - "emoji_button.label": "Umetni smajlije", + "emoji_button.food": "Hrana i piće", + "emoji_button.label": "Umetni emotikone", "emoji_button.nature": "Priroda", - "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ â”»â”â”»", - "emoji_button.objects": "Objekti", + "emoji_button.not_found": "Nema emotikona!! (╯°□°)╯︵ â”»â”â”»", + "emoji_button.objects": "Predmeti", "emoji_button.people": "Ljudi", - "emoji_button.recent": "Frequently used", + "emoji_button.recent": "ÄŒesto koriÅ¡teno", "emoji_button.search": "Traži...", - "emoji_button.search_results": "Search results", + "emoji_button.search_results": "Rezultati pretraživanja", "emoji_button.symbols": "Simboli", - "emoji_button.travel": "Putovanja & Mjesta", - "empty_column.account_timeline": "No toots here!", - "empty_column.account_unavailable": "Profile unavailable", - "empty_column.blocks": "You haven't blocked any users yet.", + "emoji_button.travel": "Putovanje i mjesta", + "empty_column.account_suspended": "RaÄun je suspendiran", + "empty_column.account_timeline": "Ovdje nema tootova!", + "empty_column.account_unavailable": "Profil nije dostupan", + "empty_column.blocks": "JoÅ¡ niste blokirali nikoga.", "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", - "empty_column.community": "Lokalni timeline je prazan. NapiÅ¡i neÅ¡to javno kako bi pokrenuo stvari!", + "empty_column.community": "Lokalna vremenska crta je prazna. NapiÅ¡ite neÅ¡to javno da biste pokrenuli stvari!", "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", - "empty_column.domain_blocks": "There are no hidden domains yet.", + "empty_column.domain_blocks": "JoÅ¡ nema blokiranih domena.", "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", "empty_column.hashtag": "JoÅ¡ ne postoji niÅ¡ta s ovim hashtagom.", - "empty_column.home": "JoÅ¡ ne slijediÅ¡ nikoga. Posjeti {public} ili koristi tražilicu kako bi poÄeo i upoznao druge korisnike.", - "empty_column.home.public_timeline": "javni timeline", - "empty_column.list": "There is nothing in this list yet.", + "empty_column.home": "VaÅ¡a poÄetna vremenska crta je prazna! Posjetite {public} ili koristite tražilicu kako biste zapoÄeli i upoznali druge korisnike.", + "empty_column.home.public_timeline": "javnu vremensku crtu", + "empty_column.list": "Na ovoj listi joÅ¡ nema niÄega. Kada Älanovi ove liste objave nove tootove, oni će se pojaviti ovdje.", "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", - "empty_column.mutes": "You haven't muted any users yet.", - "empty_column.notifications": "JoÅ¡ nemaÅ¡ notifikacija. Komuniciraj sa drugima kako bi zapoÄeo razgovor.", - "empty_column.public": "Ovdje nema niÅ¡ta! NapiÅ¡i neÅ¡to javno, ili ruÄno slijedi korisnike sa drugih instanci kako bi popunio", + "empty_column.mutes": "Niste utiÅ¡ali nijednog korisnika.", + "empty_column.notifications": "JoÅ¡ nemate obavijesti. Komunicirajte s drugima kako biste zapoÄeli razgovor.", + "empty_column.public": "Ovdje nema niÅ¡ta! NapiÅ¡ite neÅ¡to javno ili ruÄno pratite korisnike s drugi poslužitelja da biste ovo popunili", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", - "errors.unexpected_crash.report_issue": "Report issue", + "errors.unexpected_crash.report_issue": "Prijavi problem", "follow_request.authorize": "Autoriziraj", "follow_request.reject": "Odbij", "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", - "getting_started.developers": "Developers", - "getting_started.directory": "Profile directory", - "getting_started.documentation": "Documentation", + "generic.saved": "Spremljeno", + "getting_started.developers": "Razvijatelji", + "getting_started.directory": "Direktorij profila", + "getting_started.documentation": "Dokumentacija", "getting_started.heading": "PoÄnimo", - "getting_started.invite": "Invite people", - "getting_started.open_source_notice": "Mastodon je softver otvorenog koda. MožeÅ¡ pridonijeti ili prijaviti probleme na GitHubu {github}.", - "getting_started.security": "Security", - "getting_started.terms": "Terms of service", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "hashtag.column_settings.select.no_options_message": "No suggestions found", - "hashtag.column_settings.select.placeholder": "Enter hashtags…", - "hashtag.column_settings.tag_mode.all": "All of these", - "hashtag.column_settings.tag_mode.any": "Any of these", - "hashtag.column_settings.tag_mode.none": "None of these", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "getting_started.invite": "Pozovi ljude", + "getting_started.open_source_notice": "Mastodon je softver otvorenog kôda. Možete pridonijeti ili prijaviti probleme na GitHubu na {github}.", + "getting_started.security": "Postavke raÄuna", + "getting_started.terms": "Uvjeti pružanja usluga", + "hashtag.column_header.tag_mode.all": "i {additional}", + "hashtag.column_header.tag_mode.any": "ili {additional}", + "hashtag.column_header.tag_mode.none": "bez {additional}", + "hashtag.column_settings.select.no_options_message": "Nisu pronaÄ‘eni prijedlozi", + "hashtag.column_settings.select.placeholder": "Unesite hashtagove…", + "hashtag.column_settings.tag_mode.all": "Sve navedeno", + "hashtag.column_settings.tag_mode.any": "Bilo koji navedeni", + "hashtag.column_settings.tag_mode.none": "Nijedan navedeni", + "hashtag.column_settings.tag_toggle": "UkljuÄi dodatne oznake za ovaj stupac", "home.column_settings.basic": "Osnovno", "home.column_settings.show_reblogs": "Pokaži boostove", "home.column_settings.show_replies": "Pokaži odgovore", - "home.hide_announcements": "Hide announcements", - "home.show_announcements": "Show announcements", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", - "introduction.federation.federated.headline": "Federated", - "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", - "introduction.interactions.action": "Finish toot-orial!", - "introduction.interactions.favourite.headline": "Favourite", - "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", - "introduction.interactions.reblog.headline": "Boost", - "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", - "keyboard_shortcuts.back": "to navigate back", - "keyboard_shortcuts.blocked": "to open blocked users list", - "keyboard_shortcuts.boost": "to boost", - "keyboard_shortcuts.column": "to focus a status in one of the columns", - "keyboard_shortcuts.compose": "to focus the compose textarea", - "keyboard_shortcuts.description": "Description", - "keyboard_shortcuts.direct": "to open direct messages column", - "keyboard_shortcuts.down": "to move down in the list", - "keyboard_shortcuts.enter": "to open status", - "keyboard_shortcuts.favourite": "to favourite", - "keyboard_shortcuts.favourites": "to open favourites list", - "keyboard_shortcuts.federated": "to open federated timeline", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.home": "to open home timeline", - "keyboard_shortcuts.hotkey": "Hotkey", - "keyboard_shortcuts.legend": "to display this legend", - "keyboard_shortcuts.local": "to open local timeline", - "keyboard_shortcuts.mention": "to mention author", - "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", - "keyboard_shortcuts.notifications": "to open notifications column", - "keyboard_shortcuts.open_media": "to open media", - "keyboard_shortcuts.pinned": "to open pinned toots list", - "keyboard_shortcuts.profile": "to open author's profile", - "keyboard_shortcuts.reply": "to reply", - "keyboard_shortcuts.requests": "to open follow requests list", - "keyboard_shortcuts.search": "to focus search", + "home.hide_announcements": "Sakrij najave", + "home.show_announcements": "Prikaži najave", + "intervals.full.days": "{number, plural, one {# dan} other {# dana}}", + "intervals.full.hours": "{number, plural, one {# sat} few {# sata} other {# sati}}", + "intervals.full.minutes": "{number, plural, one {# minuta} few {# minute} other {# minuta}}", + "introduction.federation.action": "Sljedeće", + "introduction.federation.federated.headline": "Federalno", + "introduction.federation.federated.text": "Javne objave s drugih poslužitelja fediverzuma prikazat će se u federalnoj vremenskoj crti.", + "introduction.federation.home.headline": "PoÄetna", + "introduction.federation.home.text": "Objave ljudi koje pratite prikazat će se na VaÅ¡oj poÄetnoj stranici. Možete pratiti bilo koga na bilo kojem poslužitelju!", + "introduction.federation.local.headline": "Lokalno", + "introduction.federation.local.text": "Javne objave ljudi na istom poslužitelju prikazat će se u lokalnoj vremenskoj crti.", + "introduction.interactions.action": "DovrÅ¡i tutorijal!", + "introduction.interactions.favourite.headline": "Favoriti", + "introduction.interactions.favourite.text": "Toot možete spremiti za kasnije i javiti njegovom autoru da Vam se sviÄ‘a tako Å¡to ga oznaÄite kao favorit.", + "introduction.interactions.reblog.headline": "Boostanje", + "introduction.interactions.reblog.text": "TuÄ‘e tootove možete dijeliti sa svojim pratiteljima tako Å¡to ih boostate.", + "introduction.interactions.reply.headline": "Odgovaranje", + "introduction.interactions.reply.text": "Možete odgovoriti na tuÄ‘e i svoje tootove, Äime će se oni povezati u razgovor.", + "introduction.welcome.action": "Krenimo!", + "introduction.welcome.headline": "Prvi koraci", + "introduction.welcome.text": "Dobro doÅ¡li na fediverzum! Za nekoliko trenutaka moći ćete dijeliti poruke i razgovara sa svojim prijateljima kroz Å¡iroki raspon poslužitelja. Ali ovaj poslužitelj, {domain}, je poseban — on sadrži VaÅ¡ profil, pa zapamtite njegovo ime.", + "keyboard_shortcuts.back": "za vraćanje natrag", + "keyboard_shortcuts.blocked": "za otvaranje liste blokiranih korisnika", + "keyboard_shortcuts.boost": "za boostanje", + "keyboard_shortcuts.column": "za fokusiranje na toot u jednom od stupaca", + "keyboard_shortcuts.compose": "za fokusiranje na tekstualni okvir za stvaranje", + "keyboard_shortcuts.description": "Opis", + "keyboard_shortcuts.direct": "za otvaranje stupca s izravnim porukama", + "keyboard_shortcuts.down": "za pomak dolje na listi", + "keyboard_shortcuts.enter": "za otvaranje toota", + "keyboard_shortcuts.favourite": "za oznaÄavanje favoritom", + "keyboard_shortcuts.favourites": "za otvaranje liste favorita", + "keyboard_shortcuts.federated": "za otvaranje federalne vremenske crte", + "keyboard_shortcuts.heading": "TipkovniÄki preÄaci", + "keyboard_shortcuts.home": "za otvaranje poÄetne vremenske crte", + "keyboard_shortcuts.hotkey": "TipkovniÄki preÄac", + "keyboard_shortcuts.legend": "za prikaz ove legende", + "keyboard_shortcuts.local": "za otvaranje lokalne vremenske crte", + "keyboard_shortcuts.mention": "za spominjanje autora", + "keyboard_shortcuts.muted": "za otvaranje liste utiÅ¡anih korisnika", + "keyboard_shortcuts.my_profile": "za otvaranje VaÅ¡eg profila", + "keyboard_shortcuts.notifications": "za otvaranje stupca s obavijestima", + "keyboard_shortcuts.open_media": "za otvaranje medijskog sadržaja", + "keyboard_shortcuts.pinned": "za otvaranje liste prikvaÄenih tootova", + "keyboard_shortcuts.profile": "za otvaranje autorovog profila", + "keyboard_shortcuts.reply": "za odgovaranje", + "keyboard_shortcuts.requests": "za otvaranje liste zahtjeva za praćenje", + "keyboard_shortcuts.search": "za fokusiranje na tražilicu", "keyboard_shortcuts.spoilers": "to show/hide CW field", "keyboard_shortcuts.start": "to open \"get started\" column", "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", - "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.toggle_sensitivity": "za prikaz/sakrivanje medijskog sadržaja", + "keyboard_shortcuts.toot": "za zapoÄinjanje novog toota", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Zatvori", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lightbox.view_context": "View context", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.delete": "Delete list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "Sljedeće", + "lightbox.previous": "Prethodno", + "lists.account.add": "Dodaj na listu", + "lists.account.remove": "Ukloni s liste", + "lists.delete": "IzbriÅ¡i listu", + "lists.edit": "Uredi listu", + "lists.edit.submit": "Promijeni naslov", + "lists.new.create": "Dodaj listu", + "lists.new.title_placeholder": "Naziv nove liste", + "lists.replies_policy.followed": "Bilo koji praćeni korisnik", + "lists.replies_policy.list": "ÄŒlanovi liste", + "lists.replies_policy.none": "Nitko", + "lists.replies_policy.title": "Show replies to:", + "lists.search": "Traži meÄ‘u praćenim ljudima", + "lists.subheading": "VaÅ¡e liste", "load_pending": "{count, plural, one {# new item} other {# new items}}", - "loading_indicator.label": "UÄitavam...", - "media_gallery.toggle_visible": "Preklopi vidljivost", - "missing_indicator.label": "Nije naÄ‘en", + "loading_indicator.label": "UÄitavanje...", + "media_gallery.toggle_visible": "Sakrij {number, plural, one {sliku} other {slike}}", + "missing_indicator.label": "Nije pronaÄ‘eno", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Trajanje", "mute_modal.hide_notifications": "Hide notifications from this user?", - "navigation_bar.apps": "Mobile apps", + "mute_modal.indefinite": "Indefinite", + "navigation_bar.apps": "Mobilne aplikacije", "navigation_bar.blocks": "Blokirani korisnici", "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.community_timeline": "Lokalni timeline", + "navigation_bar.community_timeline": "Lokalna vremenska crta", "navigation_bar.compose": "Compose new toot", - "navigation_bar.direct": "Direct messages", - "navigation_bar.discover": "Discover", - "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.direct": "Izravne poruke", + "navigation_bar.discover": "Istraživanje", + "navigation_bar.domain_blocks": "Blokirane domene", "navigation_bar.edit_profile": "Uredi profil", "navigation_bar.favourites": "Favoriti", - "navigation_bar.filters": "Muted words", - "navigation_bar.follow_requests": "Zahtjevi za slijeÄ‘enje", - "navigation_bar.follows_and_followers": "Follows and followers", - "navigation_bar.info": "ViÅ¡e informacija", - "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", - "navigation_bar.lists": "Lists", + "navigation_bar.filters": "UtiÅ¡ane rijeÄi", + "navigation_bar.follow_requests": "Zahtjevi za praćenje", + "navigation_bar.follows_and_followers": "Praćeni i pratitelji", + "navigation_bar.info": "O ovom poslužitelju", + "navigation_bar.keyboard_shortcuts": "TipkovniÄki preÄaci", + "navigation_bar.lists": "Liste", "navigation_bar.logout": "Odjavi se", "navigation_bar.mutes": "UtiÅ¡ani korisnici", - "navigation_bar.personal": "Personal", - "navigation_bar.pins": "Pinned toots", + "navigation_bar.personal": "Osobno", + "navigation_bar.pins": "PrikvaÄeni tootovi", "navigation_bar.preferences": "Postavke", - "navigation_bar.public_timeline": "Federalni timeline", - "navigation_bar.security": "Security", - "notification.favourite": "{name} je lajkao tvoj status", - "notification.follow": "{name} te sada slijedi", - "notification.follow_request": "{name} has requested to follow you", - "notification.mention": "{name} te je spomenuo", - "notification.own_poll": "Your poll has ended", - "notification.poll": "A poll you have voted in has ended", - "notification.reblog": "{name} je podigao tvoj status", - "notifications.clear": "OÄisti notifikacije", - "notifications.clear_confirmation": "ŽeliÅ¡ li zaista obrisati sve svoje notifikacije?", - "notifications.column_settings.alert": "Desktop notifikacije", + "navigation_bar.public_timeline": "Federalna vremenska crta", + "navigation_bar.security": "Sigurnost", + "notification.favourite": "{name} je favorizirao/la VaÅ¡ toot", + "notification.follow": "{name} Vas je poÄeo/la pratiti", + "notification.follow_request": "{name} zatražio/la je da Vas prati", + "notification.mention": "{name} Vas je spomenuo", + "notification.own_poll": "VaÅ¡a anketa je zavrÅ¡ila", + "notification.poll": "Anketa u kojoj ste glasali je zavrÅ¡ila", + "notification.reblog": "{name} je boostao/la VaÅ¡ status", + "notification.status": "{name} just posted", + "notifications.clear": "OÄisti obavijesti", + "notifications.clear_confirmation": "Želite li zaista trajno oÄistiti sve VaÅ¡e obavijesti?", + "notifications.column_settings.alert": "Obavijesti radne povrÅ¡ine", "notifications.column_settings.favourite": "Favoriti:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", - "notifications.column_settings.follow": "Novi sljedbenici:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.filter_bar.advanced": "Prikaži sve kategorije", + "notifications.column_settings.filter_bar.category": "Brza traka filtera", + "notifications.column_settings.filter_bar.show": "Prikaži", + "notifications.column_settings.follow": "Novi pratitelji:", + "notifications.column_settings.follow_request": "Novi zahtjevi za praćenje:", "notifications.column_settings.mention": "Spominjanja:", - "notifications.column_settings.poll": "Poll results:", - "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.poll": "Rezultati anketa:", + "notifications.column_settings.push": "Push obavijesti", "notifications.column_settings.reblog": "Boostovi:", "notifications.column_settings.show": "Prikaži u stupcu", "notifications.column_settings.sound": "Sviraj zvuk", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Boosts", - "notifications.filter.favourites": "Favourites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", - "notifications.filter.polls": "Poll results", - "notifications.group": "{count} notifications", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_people": "{count, plural, one {# person} other {# people}}", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll.voted": "You voted for this answer", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", - "privacy.change": "Podesi status privatnosti", - "privacy.direct.long": "Prikaži samo spomenutim korisnicima", - "privacy.direct.short": "Direktno", - "privacy.private.long": "Prikaži samo sljedbenicima", - "privacy.private.short": "Privatno", - "privacy.public.long": "Postaj na javne timeline", + "notifications.column_settings.status": "New toots:", + "notifications.filter.all": "Sve", + "notifications.filter.boosts": "Boostovi", + "notifications.filter.favourites": "Favoriti", + "notifications.filter.follows": "Praćenja", + "notifications.filter.mentions": "Spominjanja", + "notifications.filter.polls": "Rezultati anketa", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", + "notifications.group": "{count} obavijesti", + "notifications.mark_as_read": "OznaÄi sve obavijesti kao proÄitane", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", + "poll.closed": "ZavrÅ¡eno", + "poll.refresh": "Osvježi", + "poll.total_people": "{count, plural, one {# osoba} few {# osobe} other {# osoba}}", + "poll.total_votes": "{count, plural, one {# glas} few {# glasa} other {# glasova}}", + "poll.vote": "Glasaj", + "poll.voted": "Vi ste glasali za ovaj odgovor", + "poll_button.add_poll": "Dodaj anketu", + "poll_button.remove_poll": "Ukloni anketu", + "privacy.change": "Podesi privatnost toota", + "privacy.direct.long": "Vidljivo samo spomenutim korisnicima", + "privacy.direct.short": "Izravno", + "privacy.private.long": "Vidljivo samo pratiteljima", + "privacy.private.short": "Samo pratitelji", + "privacy.public.long": "Vidljivo svima, prikazano u javim vremenskim crtama", "privacy.public.short": "Javno", - "privacy.unlisted.long": "Ne prikazuj u javnim timelineovima", - "privacy.unlisted.short": "Unlisted", - "refresh": "Refresh", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "privacy.unlisted.long": "Vidljivo svima, ali se ne prikazuje u javnim vremenskim crtama", + "privacy.unlisted.short": "Neprikazano", + "refresh": "Osvježi", + "regeneration_indicator.label": "UÄitavanje…", + "regeneration_indicator.sublabel": "Priprema se VaÅ¡a poÄetna stranica!", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", - "relative_time.just_now": "now", + "relative_time.just_now": "sada", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", - "relative_time.today": "today", + "relative_time.today": "danas", "reply_indicator.cancel": "Otkaži", - "report.forward": "Forward to {target}", - "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", - "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "report.forward": "Proslijedi {target}", + "report.forward_hint": "RaÄun je s drugog poslužitelja. Poslati anonimiziranu kopiju prijave i tamo?", + "report.hint": "Prijava bit će poslana moderatorima poslužitelja. Ispod možete dati objaÅ¡njenje zaÅ¡to prijavljujete ovaj raÄun:", "report.placeholder": "Dodatni komentari", "report.submit": "PoÅ¡alji", - "report.target": "Prijavljivanje", + "report.target": "Prijavljivanje korisnika {target}", "search.placeholder": "Traži", - "search_popout.search_format": "Advanced search format", + "search_popout.search_format": "Format naprednog pretraživanja", "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "status", + "search_popout.tips.status": "toot", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", - "search_popout.tips.user": "user", - "search_results.accounts": "People", + "search_popout.tips.user": "korisnik", + "search_results.accounts": "Ljudi", "search_results.hashtags": "Hashtags", "search_results.statuses": "Toots", "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", @@ -370,92 +394,93 @@ "status.block": "Block @{name}", "status.bookmark": "Bookmark", "status.cancel_reblog_private": "Unboost", - "status.cannot_reblog": "Ovaj post ne može biti boostan", + "status.cannot_reblog": "Ova objava ne može biti boostana", "status.copy": "Copy link to status", "status.delete": "ObriÅ¡i", "status.detailed_status": "Detailed conversation view", "status.direct": "Direct message @{name}", "status.embed": "Embed", - "status.favourite": "OznaÄi omiljenim", + "status.favourite": "OznaÄi favoritom", "status.filtered": "Filtered", "status.load_more": "UÄitaj viÅ¡e", - "status.media_hidden": "Sakriven media sadržaj", + "status.media_hidden": "Sakriven medijski sadržaj", "status.mention": "Spomeni @{name}", "status.more": "More", "status.mute": "Mute @{name}", "status.mute_conversation": "UtiÅ¡aj razgovor", - "status.open": "ProÅ¡iri ovaj status", + "status.open": "ProÅ¡iri ovaj toot", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", - "status.read_more": "Read more", - "status.reblog": "Podigni", - "status.reblog_private": "Boost to original audience", - "status.reblogged_by": "{name} je podigao", - "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.remove_bookmark": "Remove bookmark", + "status.read_more": "ProÄitajte viÅ¡e", + "status.reblog": "Boostaj", + "status.reblog_private": "Boostaj s izvornom vidljivošću", + "status.reblogged_by": "{name} je boostao/la", + "status.reblogs.empty": "Nitko joÅ¡ nije boostao ovaj toot. Kada netko to uÄini, ovdje će biti prikazani.", + "status.redraft": "IzbriÅ¡i i ponovno uredi", + "status.remove_bookmark": "Ukloni knjižnu oznaku", "status.reply": "Odgovori", - "status.replyAll": "Odgovori na temu", + "status.replyAll": "Odgovori na niz", "status.report": "Prijavi @{name}", "status.sensitive_warning": "Osjetljiv sadržaj", - "status.share": "Share", + "status.share": "Podijeli", "status.show_less": "Pokaži manje", "status.show_less_all": "Show less for all", "status.show_more": "Pokaži viÅ¡e", "status.show_more_all": "Show more for all", - "status.show_thread": "Show thread", - "status.uncached_media_warning": "Not available", + "status.show_thread": "Prikaži nit", + "status.uncached_media_warning": "Nije dostupno", "status.unmute_conversation": "PoniÅ¡ti utiÅ¡avanje razgovora", - "status.unpin": "Unpin from profile", - "suggestions.dismiss": "Dismiss suggestion", - "suggestions.header": "You might be interested in…", - "tabs_bar.federated_timeline": "Federalni", - "tabs_bar.home": "Dom", + "status.unpin": "OtkvaÄi s profila", + "suggestions.dismiss": "Odbaci prijedlog", + "suggestions.header": "Možda Vas zanima…", + "tabs_bar.federated_timeline": "Federalno", + "tabs_bar.home": "PoÄetna", "tabs_bar.local_timeline": "Lokalno", - "tabs_bar.notifications": "Notifikacije", - "tabs_bar.search": "Search", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", + "tabs_bar.notifications": "Obavijesti", + "tabs_bar.search": "Traži", + "time_remaining.days": "{number, plural, one {preostao # dan} other {preostalo # dana}}", + "time_remaining.hours": "{number, plural, one {preostao # sat} few {preostalo # sata} other {preostalo # sati}}", + "time_remaining.minutes": "{number, plural, one {preostala # minuta} few {preostale # minute} other {preostalo # minuta}}", "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", + "time_remaining.seconds": "{number, plural, one {preostala # sekunda} few {preostale # sekunde} other {preostalo # sekundi}}", + "timeline_hint.remote_resource_not_displayed": "{resource} s drugih poslužitelja nisu prikazani.", + "timeline_hint.resources.followers": "Pratitelji", + "timeline_hint.resources.follows": "Praćenja", + "timeline_hint.resources.statuses": "Stariji tootovi", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", - "trends.trending_now": "Trending now", - "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", - "upload_area.title": "Povuci i spusti kako bi uploadao", - "upload_button.label": "Dodaj media", - "upload_error.limit": "File upload limit exceeded.", - "upload_error.poll": "File upload not allowed with polls.", - "upload_form.audio_description": "Describe for people with hearing loss", - "upload_form.description": "Describe for the visually impaired", - "upload_form.edit": "Edit", - "upload_form.thumbnail": "Change thumbnail", - "upload_form.undo": "PoniÅ¡ti", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", - "upload_modal.analyzing_picture": "Analyzing picture…", - "upload_modal.apply": "Apply", - "upload_modal.choose_image": "Choose image", + "trends.trending_now": "Popularno", + "ui.beforeunload": "VaÅ¡a skica bit će izgubljena ako napustite Mastodon.", + "units.short.billion": "{count} mlrd.", + "units.short.million": "{count} mil.", + "units.short.thousand": "{count} tis.", + "upload_area.title": "Povucite i ispustite za prijenos", + "upload_button.label": "Dodajte slike, video ili audio datoteku", + "upload_error.limit": "OgraniÄenje prijenosa datoteka je prekoraÄeno.", + "upload_error.poll": "Prijenos datoteka nije dopuÅ¡ten kod anketa.", + "upload_form.audio_description": "OpiÅ¡ite za ljude sa slabim sluhom", + "upload_form.description": "OpiÅ¡ite za ljude sa slabim vidom", + "upload_form.edit": "Uredi", + "upload_form.thumbnail": "Promijeni pretpregled", + "upload_form.undo": "ObriÅ¡i", + "upload_form.video_description": "OpiÅ¡ite za ljude sa slabim sluhom ili vidom", + "upload_modal.analyzing_picture": "Analiza slike…", + "upload_modal.apply": "Primijeni", + "upload_modal.choose_image": "Odaberite sliku", "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", - "upload_modal.detect_text": "Detect text from picture", - "upload_modal.edit_media": "Edit media", + "upload_modal.detect_text": "Detektiraj tekst sa slike", + "upload_modal.edit_media": "UreÄ‘ivanje medija", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", - "upload_progress.label": "Uploadam...", - "video.close": "Close video", - "video.download": "Download file", - "video.exit_fullscreen": "Exit full screen", - "video.expand": "Expand video", - "video.fullscreen": "Full screen", - "video.hide": "Hide video", - "video.mute": "Mute sound", - "video.pause": "Pause", - "video.play": "Play", - "video.unmute": "Unmute sound" + "upload_progress.label": "PrenoÅ¡enje...", + "video.close": "Zatvori video", + "video.download": "Preuzmi datoteku", + "video.exit_fullscreen": "IzaÄ‘i iz cijelog zaslona", + "video.expand": "ProÅ¡iri video", + "video.fullscreen": "Cijeli zaslon", + "video.hide": "Sakrij video", + "video.mute": "UtiÅ¡aj zvuk", + "video.pause": "Pauziraj", + "video.play": "Reproduciraj", + "video.unmute": "UkljuÄi zvuk" } diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 713abba5f72dd86978370560511655aac29e1dfe..a0ae7305cfbae88580ac9b13d77ff225f03ead60 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "Megjegyzés @{name} fiókhoz", + "account.account_note_header": "Feljegyzés", "account.add_or_remove_from_list": "Hozzáadás vagy eltávolÃtás a listáról", "account.badges.bot": "Bot", "account.badges.group": "Csoport", @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "További böngészés az eredeti profilon", "account.cancel_follow_request": "Követési kérelem törlése", "account.direct": "Közvetlen üzenet @{name} számára", + "account.disable_notifications": "Ne figyelmeztess, ha @{name} tülköl", "account.domain_blocked": "Rejtett domain", "account.edit_profile": "Profil szerkesztése", + "account.enable_notifications": "Figyelmeztess, ha @{name} tülköl", "account.endorse": "Kiemelés a profilodon", "account.follow": "Követés", "account.followers": "KövetÅ‘", "account.followers.empty": "Ezt a felhasználót még senki sem követi.", "account.followers_counter": "{count, plural, one {{counter} KövetÅ‘} other {{counter} KövetÅ‘}}", - "account.following_counter": "{count, plural, one {} other {{counter} Követett}}", + "account.following_counter": "{count, plural, other {{counter} Követett}}", "account.follows.empty": "Ez a felhasználó még senkit sem követ.", "account.follows_you": "Követ téged", "account.hide_reblogs": "@{name} megtolásainak némÃtása", @@ -43,7 +45,7 @@ "account.unfollow": "Követés vége", "account.unmute": "@{name} némÃtás feloldása", "account.unmute_notifications": "@{name} némÃtott értesÃtéseinek feloldása", - "account_note.placeholder": "Nincs megjegyzés", + "account_note.placeholder": "Klikk a feljegyzéshez", "alert.rate_limited.message": "Próbáld újra {retry_time, time, medium} után.", "alert.rate_limited.title": "Forgalomkorlátozás", "alert.unexpected.message": "Váratlan hiba történt.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Keresési találatok", "emoji_button.symbols": "Szimbólumok", "emoji_button.travel": "Utazás és Helyek", + "empty_column.account_suspended": "Fiók felfüggesztve", "empty_column.account_timeline": "Itt nincs tülkölés!", "empty_column.account_unavailable": "A profil nem érhetÅ‘ el", "empty_column.blocks": "Még senkit sem tiltottál le.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Jelenleg nincsenek értesÃtéseid. Lépj kapcsolatba másokkal, hogy elindÃtsd a beszélgetést.", "empty_column.public": "Jelenleg itt nincs semmi! Ãrj valamit nyilvánosan vagy kövess más szervereken levÅ‘ felhasználókat, hogy megtöltsd", "error.unexpected_crash.explanation": "Egy hiba vagy böngészÅ‘ inkompatibilitás miatt ez az oldal nem jelenÃthetÅ‘ meg rendesen.", + "error.unexpected_crash.explanation_addons": "Ezt az oldalt nem lehet helyesen megjelenÃteni. Ezt a hibát valószÃnűleg egy böngészÅ‘ beépülÅ‘ vagy egy automatikus fordÃtó okozza.", "error.unexpected_crash.next_steps": "Próbáld frissÃteni az oldalt. Ha ez nem segÃt, egy másik böngészÅ‘n vagy appon keresztül még mindig használhatod a Mastodont.", + "error.unexpected_crash.next_steps_addons": "Próbáld letiltani Å‘ket és frissÃteni az oldalt. Ha ez nem segÃt, egy másik böngészÅ‘n vagy appon keresztül még mindig használhatod a Mastodont.", "errors.unexpected_crash.copy_stacktrace": "VeremkiÃratás vágólapra másolása", "errors.unexpected_crash.report_issue": "Probléma jelentése", "follow_request.authorize": "Engedélyezés", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "tülk szerkesztés/keresés fókuszpontból való kivétele", "keyboard_shortcuts.up": "felfelé mozdÃtás a listában", "lightbox.close": "Bezárás", + "lightbox.compress": "Képnézet összecsukása", + "lightbox.expand": "Képnézet kinagyÃtása", "lightbox.next": "KövetkezÅ‘", "lightbox.previous": "ElÅ‘zÅ‘", - "lightbox.view_context": "Kontextus megtekintése", "lists.account.add": "Hozzáadás a listához", "lists.account.remove": "EltávolÃtás a listából", "lists.delete": "Lista törlése", @@ -260,6 +266,10 @@ "lists.edit.submit": "CÃm megváltoztatása", "lists.new.create": "Lista hozzáadása", "lists.new.title_placeholder": "Új lista cÃme", + "lists.replies_policy.followed": "Bármely követett felhasználó", + "lists.replies_policy.list": "A lista tagjai", + "lists.replies_policy.none": "Senki", + "lists.replies_policy.title": "Nekik mutassuk a válaszokat:", "lists.search": "Keresés a követett személyek között", "lists.subheading": "Listáid", "load_pending": "{count, plural, one {# új elem} other {# új elem}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Láthatóság állÃtása", "missing_indicator.label": "Nincs találat", "missing_indicator.sublabel": "Ez az erÅ‘forrás nem található", + "mute_modal.duration": "IdÅ‘tartam", "mute_modal.hide_notifications": "Rejtsük el a felhasználótól származó értesÃtéseket?", + "mute_modal.indefinite": "Határozatlan", "navigation_bar.apps": "Mobil appok", "navigation_bar.blocks": "Letiltott felhasználók", "navigation_bar.bookmarks": "KönyvjelzÅ‘k", @@ -298,6 +310,7 @@ "notification.own_poll": "A szavazásod véget ért", "notification.poll": "Egy szavazás, melyben részt vettél, véget ért", "notification.reblog": "{name} megtolta a tülködet", + "notification.status": "{name} tülkölt egyet", "notifications.clear": "ÉrtesÃtések törlése", "notifications.clear_confirmation": "Biztos, hogy véglegesen törölni akarod az összes értesÃtésed?", "notifications.column_settings.alert": "Asztali értesÃtések", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Megtolások:", "notifications.column_settings.show": "Oszlopban mutatás", "notifications.column_settings.sound": "Hang lejátszása", + "notifications.column_settings.status": "Új tülkök:", "notifications.filter.all": "Mind", "notifications.filter.boosts": "Megtolások", "notifications.filter.favourites": "Kedvencnek jelölések", "notifications.filter.follows": "Követések", "notifications.filter.mentions": "MegemlÃtések", "notifications.filter.polls": "Szavazások eredményei", + "notifications.filter.statuses": "FrissÃtések azoktól, akiket követsz", + "notifications.grant_permission": "Engedély megadása.", "notifications.group": "{count} értesÃtés", + "notifications.mark_as_read": "Minden értesÃtés olvasottnak jelölése", + "notifications.permission_denied": "Nem tudjuk engedélyezni az asztali értesÃtéseket, mert az engedélyt megtagadták.", + "notifications.permission_denied_alert": "Az asztali értesÃtések nem engedélyezhetÅ‘ek, mert az engedélyt megtagadták a böngészÅ‘ben", + "notifications.permission_required": "Az asztali értesÃtések nem elérhetÅ‘ek, mert a szükséges engedélyt nem adtad meg.", + "notifications_permission_banner.enable": "Asztali értesÃtések engedélyezése", + "notifications_permission_banner.how_to_control": "Ahhoz, hogy értesÃtéseket kapj akkor, amikor a Mastodon nincs megnyitva, engedélyezd az asztali értesÃtéseket. Pontosan be tudod állÃtani, hogy milyen interakciókról értesülj a fenti {icon} gombon keresztül, ha egyszer már engedélyezted Å‘ket.", + "notifications_permission_banner.title": "Soha ne mulassz el semmit", + "picture_in_picture.restore": "Visszarakás", "poll.closed": "Lezárva", "poll.refresh": "FrissÃtés", "poll.total_people": "{count, plural, one {# személy} other {# személy}}", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Húzd ide a feltöltéshez", - "upload_button.label": "Média hozzáadása ({formats})", + "upload_button.label": "Média hozzáadása", "upload_error.limit": "Túllépted a fájlfeltöltési korlátot.", "upload_error.poll": "Szavazásnál nem lehet fájlt feltölteni.", "upload_form.audio_description": "Ãrja le a hallássérültek számára", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Szöveg felismerése a képrÅ‘l", "upload_modal.edit_media": "Média szerkesztése", "upload_modal.hint": "Kattints vagy húzd a kört az elÅ‘nézetben arra a fókuszpontra, mely minden megjelenÃtett bélyegképen látható kell, legyen.", + "upload_modal.preparing_ocr": "OCR elÅ‘készÃtése…", "upload_modal.preview_label": "ElÅ‘nézet ({ratio})", "upload_progress.label": "Feltöltés...", "video.close": "Videó bezárása", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index 29810cd9fc7cbdc49748c5dbeb30ad5d845a0de1..5cdba58e8cce689cec3c2f87504eda9f45462e87 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´", "account.add_or_remove_from_list": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¯Õ¡Õ´ Õ°Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¥Ö€Õ«Ö", "account.badges.bot": "Ô²Õ¸Õ¿", "account.badges.group": "Ô½Õ¸Ö‚Õ´Õ¢", "account.block": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ @{name}ÖŠÕ«Õ¶", "account.block_domain": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¡Õ´Õ§Õ¶Õ¨ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¡Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ«ÖÕ {domain}", "account.blocked": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ§", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Ô´Õ«Õ¿Õ¥Õ¬ Õ¡Ö‚Õ¥Õ¬Õ«Õ¶ Õ«Ö€Õ¡Õ¯Õ¡Õ¶ ÕºÖ€Õ¸Ö†Õ«Õ¬Õ¸Ö‚Õ´", "account.cancel_follow_request": "Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖÕ¨", "account.direct": "Õ†Õ¡Õ´Õ¡Õ¯ Õ£Ö€Õ¥Õ¬ @{name} -Õ«Õ¶", + "account.disable_notifications": "Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ @{name} Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€", "account.domain_blocked": "ÕÕ«Ö€Õ¸ÕµÕ©Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ§", "account.edit_profile": "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨", + "account.enable_notifications": "Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¥Õ¬ Õ«Õ¶Õ± @{name} Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ´Õ¡Õ½Õ«Õ¶", "account.endorse": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¸Ö‚Õ´", "account.follow": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬", "account.followers": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€", "account.followers.empty": "Ô±ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ Õ¤Õ¥Õ¼ Õ¸Õ¹ Õ´Õ§Õ¯ Õ¹Õ« Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Ö‰", - "account.followers_counter": "{count, plural, one {{counter} Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤} other {{counter} Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€}}", - "account.following_counter": "{count, plural, one {} other {{counter} Õ€Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ Õ¥Õ¶}}", + "account.followers_counter": "{count, plural, one {{counter} Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤} other {{counter} Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€}}", + "account.following_counter": "{count, plural, other {{counter} Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶}}", "account.follows.empty": "Ô±ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¨ Õ¤Õ¥Õ¼ Õ¸Õ¹ Õ´Õ§Õ¯Õ« Õ¹Õ« Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Ö‰", "account.follows_you": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ§ Ö„Õ¥Õ¦", "account.hide_reblogs": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ @{name}ÖŠÕ« Õ¿Õ¡Ö€Õ¡Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ¨", @@ -43,7 +45,7 @@ "account.unfollow": "Ô±ÕºÕ¡Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬", "account.unmute": "Ô±ÕºÕ¡Õ¬Õ¼Õ¥ÖÕ¶Õ¥Õ¬ @{name}ÖŠÕ«Õ¶", "account.unmute_notifications": "Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ @{name}ÖŠÕ«Ö", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "ÕÕ¥Õ²Õ´Õ§Õ›Ö„ Õ£Ö€Õ¡Õ¼Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€\n", "alert.rate_limited.message": "Õ“Õ¸Ö€Õ±Õ§Ö„ Õ¸Ö€Õ¸Õ· ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¡Õ¶ÖÕ {retry_time, time, medium}Ö‰", "alert.rate_limited.title": "Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕµÕ¡Õ³Õ¡ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ£Õ¥Ö€Õ¡Õ¦Õ¡Õ¶ÖÕ¸Ö‚Õ´ Õ§ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬Õ«Õ¶", "alert.unexpected.message": "Ô±Õ¶Õ½ÕºÕ¡Õ½Õ¥Õ¬Õ« Õ½ÕÕ¡Õ¬ Õ¿Õ¥Õ²Õ« Õ¸Ö‚Õ¶Õ¥ÖÕ¡Ö‚Ö‰", @@ -55,9 +57,9 @@ "bundle_column_error.retry": "Ô¿Ö€Õ¯Õ«Õ¶ ÖƒÕ¸Ö€Õ±Õ¥Õ¬", "bundle_column_error.title": "Õ‘Õ¡Õ¶ÖÕ¡ÕµÕ«Õ¶ Õ½ÕÕ¡Õ¬", "bundle_modal_error.close": "Õ“Õ¡Õ¯Õ¥Õ¬", - "bundle_modal_error.message": "Ô±ÕµÕ½ Õ¢Õ¡Õ²Õ¡Õ¤Ö€Õ«Õ¹Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ«Õ¶Õ¹ÖŠÕ¸Ö€ Õ¢Õ¡Õ¶ ÕÕ¡ÖƒÕ¡Õ¶Õ¾Õ¥ÖÖ‰", + "bundle_modal_error.message": "Ô±ÕµÕ½ Õ¢Õ¡Õ²Õ¡Õ¤Ö€Õ«Õ¹Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ«Õ¶Õ¹ÖŠÕ¸Ö€ Õ¢Õ¡Õ¶ ÕÕ¡ÖƒÕ¡Õ¶Õ¸Ö‚Õ¥ÖÖ‰", "bundle_modal_error.retry": "Ô¿Ö€Õ¯Õ«Õ¶ ÖƒÕ¸Ö€Õ±Õ¥Õ¬", - "column.blocks": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€", + "column.blocks": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€", "column.bookmarks": "Ô·Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€", "column.community": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„", "column.direct": "Õ€Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€", @@ -67,27 +69,27 @@ "column.follow_requests": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖÕ¥Ö€", "column.home": "Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶", "column.lists": "Õ‘Õ¡Õ¶Õ¯Õ¥Ö€", - "column.mutes": "Ô¼Õ¼Õ¥ÖÖ€Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€", + "column.mutes": "Ô¼Õ¼Õ¥ÖÖ€Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€", "column.notifications": "Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€", - "column.pins": "Ô±Õ´Ö€Õ¡ÖÕ¾Õ¡Õ® Õ©Õ©Õ¥Ö€", + "column.pins": "Ô±Õ´Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ©Õ©Õ¥Ö€", "column.public": "Ô´Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„", "column_back_button.label": "ÔµÕ¿", - "column_header.hide_settings": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", + "column_header.hide_settings": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", "column_header.moveLeft_settings": "ÕÕ¥Õ²Õ¡Õ·Õ¡Ö€ÕªÕ¥Õ¬ Õ½Õ«Ö‚Õ¶Õ¨ Õ±Õ¡Õ", "column_header.moveRight_settings": "ÕÕ¥Õ²Õ¡Õ·Õ¡Ö€ÕªÕ¥Õ¬ Õ½Õ«Ö‚Õ¶Õ¨ Õ¡Õ»", "column_header.pin": "Ô±Õ´Ö€Õ¡ÖÕ¶Õ¥Õ¬", - "column_header.show_settings": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", + "column_header.show_settings": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", "column_header.unpin": "Õ€Õ¡Õ¶Õ¥Õ¬", - "column_subheading.settings": "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€", - "community.column_settings.local_only": "Õ„Õ«Õ¡ÕµÕ¶ Õ¶Õ¥Ö€Ö„Õ«Õ¶", - "community.column_settings.media_only": "Media only", - "community.column_settings.remote_only": "Õ„Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¼Õ¡Õ¯Õ¡", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", - "compose_form.direct_message_warning_learn_more": "Ô»Õ´Õ¡Õ¶Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶", - "compose_form.hashtag_warning": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¹Õ« Õ°Õ¡Õ·Õ¾Õ¡Õ¼Õ¾Õ« Õ¸Ö€Õ¥Ö‚Õ§ ÕºÕ«Õ¿Õ¡Õ¯Õ« Õ¿Õ¡Õ¯, Ö„Õ¡Õ¶Õ¦Õ« Õ¡ÕµÕ¶ Õ®Õ¡Õ®Õ¸Ö‚Õ¯ Õ§Ö‰ Õ„Õ«Õ¡ÕµÕ¶ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ©Õ©Õ¥Ö€Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§ Õ¸Ö€Õ¸Õ¶Õ¥Õ¬ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¸Õ¾Ö‰", + "column_subheading.settings": "Ô¿Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€", + "community.column_settings.local_only": "Õ„Õ«Õ¡ÕµÕ¶ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶", + "community.column_settings.media_only": "Õ„Õ«Õ¡ÕµÕ¶ Õ´Õ¥Õ¤Õ«Õ¡", + "community.column_settings.remote_only": "Õ„Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¼Õ¡Õ¯Õ¡Õµ", + "compose_form.direct_message_warning": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ¨ Õ¬Õ«Õ¶Õ« Õ´Õ«Õ¡ÕµÕ¶ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ«Õ¶Ö‰", + "compose_form.direct_message_warning_learn_more": "Ô»Õ´Õ¡Õ¶Õ¡Õ¬ Õ¡Ö‚Õ¥Õ¬Õ«Õ¶", + "compose_form.hashtag_warning": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¹Õ« Õ°Õ¡Õ·Õ¸Ö‚Õ¡Õ¼Õ¸Ö‚Õ« Õ¸Ö€Õ¥Ö‚Õ§ ÕºÕ«Õ¿Õ¡Õ¯Õ« Õ¿Õ¡Õ¯, Ö„Õ¡Õ¶Õ¦Õ« Õ¡ÕµÕ¶ Õ®Õ¡Õ®Õ¸Ö‚Õ¯ Õ§Ö‰ Õ„Õ«Õ¡ÕµÕ¶ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ©Õ©Õ¥Ö€Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ§ Õ¸Ö€Õ¸Õ¶Õ¥Õ¬ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¸Õ¾Ö‰", "compose_form.lock_disclaimer": "Õ”Õ¸ Õ°Õ¡Õ·Õ«Ö‚Õ¨ {locked} Õ¹Õ§Ö‰ Ô»Ö‚Ö€Õ¡Ö„Õ¡Õ¶Õ¹Õ«Ö‚Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¸Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Ö„Õ¥Õ¦ Õ¥Ö‚ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ¶Õ¡ÕÕ¡Õ¿Õ¥Õ½Õ¸Ö‚Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", "compose_form.lock_disclaimer.lock": "ÖƒÕ¡Õ¯", - "compose_form.placeholder": "Ô»ÕžÕ¶Õ¹ Õ¯Õ¡ Õ´Õ¿Ö„Õ«Õ¤", + "compose_form.placeholder": "Ô»ÕžÕ¶Õ¹ Õ¯Õ¡Õµ Õ´Õ¿Ö„Õ«Õ¤", "compose_form.poll.add_option": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯", "compose_form.poll.duration": "Õ€Õ¡Ö€ÖÕ´Õ¡Õ¶ Õ¿Õ¥Ö‚Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "compose_form.poll.option_placeholder": "ÕÕ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯ {number}", @@ -109,16 +111,16 @@ "confirmations.delete.confirm": "Õ‹Õ¶Õ»Õ¥Õ¬", "confirmations.delete.message": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ»Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨Ö‰", "confirmations.delete_list.confirm": "Õ‹Õ¶Õ»Õ¥Õ¬", - "confirmations.delete_list.message": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ´Õ·Õ¿Õ¡ÕºÕ¥Õ½ Õ»Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ½ ÖÕ¡Õ¶Õ¯Õ¨Ö‰", + "confirmations.delete_list.message": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ´Õ·Õ¿Õ¡ÕºÕ§Õ½ Õ»Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ½ ÖÕ¡Õ¶Õ¯Õ¨Ö‰", "confirmations.domain_block.confirm": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¨", - "confirmations.domain_block.message": "Õ€Õ¡Õ½Õ¿Õ¡Õ¿ÖŠÕ°Õ¡Õ½Õ¿Õ¡ÕžÕ¿ Õ¾Õ½Õ¿Õ¡Õ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ» {domain} Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¨Ö‰ ÕÕ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ Õ´Õ« Õ¥Ö€Õ¯Õ¸Ö‚ Õ©Õ«Ö€Õ¡ÕÕ¡Õ¾Õ¸Ö€Õ¾Õ¡Õ® Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ´ Õ¢Õ¡Õ¾Õ¡Õ¯Õ¡Õ¶ Õ§ Õ¸Ö‚ Õ¶Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¥Õ¬Õ«Ö‰", + "confirmations.domain_block.message": "Õ€Õ¡Õ½Õ¿Õ¡Õ¿ÖŠÕ°Õ¡Õ½Õ¿Õ¡ÕžÕ¿ Õ¾Õ½Õ¿Õ¡Õ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ» {domain} Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨Ö‰ ÕÕ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ Õ´Õ« Õ¥Ö€Õ¯Õ¸Ö‚ Õ©Õ«Ö€Õ¡ÕÕ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ¡Õ® Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ´ Õ¢Õ¡Ö‚Õ¡Õ¯Õ¡Õ¶ Õ§ Õ¸Ö‚ Õ¶Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¥Õ¬Õ«Ö‰", "confirmations.logout.confirm": "ÔµÕ¬Ö„", "confirmations.logout.message": "Õ€Õ¡Õ´Õ¸Õ¦Õ¸ÕžÖ‚Õ¡Õ® Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¤Õ¸Ö‚Ö€Õ½ Õ£Õ¡Õ¬", "confirmations.mute.confirm": "Ô¼Õ¼Õ¥ÖÕ¶Õ¥Õ¬", "confirmations.mute.explanation": "ÕÕ¡ Õ©Õ¡Ö„ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ¡ Õ«Ö€Õ¥Õ¶Ö Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Õ¥Ö‚ Õ«Ö€Õ¥Õ¶Ö Õ¶Õ·Õ¸Õ² Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶, Õ¢Õ¡ÕµÖ Õ«Ö€Õ¥Õ¶Ö„ Õ´Õ«Õ¥Ö‚Õ¶Õ¸ÕµÕ¶ Õ§ Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Õ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Õ±Õ¥Õ¦ Õ¥Ö‚ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", "confirmations.mute.message": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ {name}ÖŠÕ«Õ¶ Õ¬Õ¼Õ¥ÖÕ¶Õ¥Õ¬Ö‰", "confirmations.redraft.confirm": "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¥Ö‚ ÕÕ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¶Õ¸Ö€Õ«Ö", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", + "confirmations.redraft.message": "ÕŽÕ½Õ¿Õ¡Õ° Õ¥ÕžÕ½, Õ¸Ö€ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ Õ»Õ¶Õ»Õ¥Õ¬ Õ¥Ö‚ Õ¾Õ¥Ö€Õ¡ÕÕ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¡ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨Ö‰ Ô´Õ¸Ö‚ Õ¯Õ¨ Õ¯Õ¸Ö€ÖÕ¶Õ¥Õ½ Õ¡ÕµÕ½ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ¢Õ¸Õ¬Õ¸Ö€ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¶Õ¥Ö€Õ¨, Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ Õ°Õ¡Ö‚Õ¡Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", "confirmations.reply.confirm": "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬", "confirmations.reply.message": "Ô±ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬Õ¨ Õ¯Õ¨ Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ« Õ±Õ¥Ö€Õ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¡Õ¶Õ¡Ö‚Õ¡Ö€Õ¿ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰ Õ€Õ¡Õ´Õ¸Õ¦Õ¸Ö‚Õ¡ÕžÕ® Õ§Ö„Ö‰", "confirmations.unfollow.confirm": "Ô±ÕºÕ¡Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬", @@ -126,70 +128,73 @@ "conversation.delete": "Õ‹Õ¶Õ»Õ¥Õ¬ ÕÖ…Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "conversation.mark_as_read": "Õ†Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¨Õ¶Õ©Õ¥Ö€ÖÕ¸Ö‚Õ¡Õ®", "conversation.open": "Ô´Õ«Õ¿Õ¥Õ¬ ÕÖ…Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", - "conversation.with": "{names}ÖŠÕ¥Ö€Õ« Õ°Õ¥Õ¿", + "conversation.with": "{names}-Õ« Õ°Õ¥Õ¿", "directory.federated": "Õ…Õ¡ÕµÕ¿Õ¶Õ« Õ¤Õ¡Õ·Õ¶Õ¥Õ¦Õ¥Ö€Ö„Õ«Ö", "directory.local": "{domain} Õ¿Õ«Ö€Õ¸ÕµÕ©Õ«Ö Õ´Õ«Õ¡ÕµÕ¶", "directory.new_arrivals": "Õ†Õ¸Ö€Õ¥Õ¯Õ¶Õ¥Ö€", "directory.recently_active": "ÕŽÕ¥Ö€Õ»Õ¥Ö€Õ½ Õ¡Õ¯Õ¿Õ«Ö‚", "embed.instructions": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Ö„Õ¸ Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´ Õ¶Õ¥Ö€Õ¤Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ ÕºÕ¡Õ¿Õ³Õ§Õ¶Õ¥Õ¬ Õ¶Õ¥Ö€Ö„Õ«Õ¶Õ¡Õ¶Õ¡Õ¬ Õ¯Õ¸Õ¤Õ¨Ö‰", - "embed.preview": "Ô±Õ°Õ¡, Õ©Õ¥ Õ«Õ¶Õ¹ Õ¿Õ¥Õ½Ö„ Õ¯Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡ Õ¡ÕµÕ¶Õ", + "embed.preview": "Ô±Õ°Õ¡Õµ, Õ©Õ§ Õ«Õ¶Õ¹ Õ¿Õ¥Õ½Ö„ Õ¯Õ¨ Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡Õµ Õ¡ÕµÕ¶Õ", "emoji_button.activity": "Ô¶Õ¢Õ¡Õ²Õ´Õ¸Ö‚Õ¶Ö„Õ¶Õ¥Ö€", - "emoji_button.custom": "Õ€Õ¡Õ¿Õ¸Ö‚Õ¯", - "emoji_button.flags": "Ô´Ö€Õ¸Õ·Õ¶Õ¥Ö€", + "emoji_button.custom": "Õ…Õ¡Õ¿Õ¸Ö‚Õ¯", + "emoji_button.flags": "Ô´Ö€Ö…Õ·Õ¶Õ¥Ö€", "emoji_button.food": "Ô¿Õ¥Ö€Õ¸Ö‚ÕÕ¸Ö‚Õ´", - "emoji_button.label": "Ô·Õ´Õ¸Õ»Õ« Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬", + "emoji_button.label": "Ô·Õ´Õ¸Õ»Õ« Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬", "emoji_button.nature": "Ô²Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶", - "emoji_button.not_found": "Õ†Õ´Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€ Õ¤Õ¥Õ¼ Õ¹Õ¥Õ¶ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¾Õ¥Õ¬Ö‰ (╯°□°)╯︵ â”»â”â”»", + "emoji_button.not_found": "Õ†Õ´Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€ Õ¤Õ¥Õ¼ Õ¹Õ¥Õ¶ ÕµÕ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¸Ö‚Õ¥Õ¬Ö‰ (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "Ô±Õ¼Õ¡Ö€Õ¯Õ¡Õ¶Õ¥Ö€", "emoji_button.people": "Õ„Õ¡Ö€Õ¤Õ«Õ¯", - "emoji_button.recent": "Õ€Õ¡Õ³Õ¡Õ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ²", + "emoji_button.recent": "Õ…Õ¡Õ³Õ¡Õ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Õ²", "emoji_button.search": "Որոնել…", "emoji_button.search_results": "ÕˆÖ€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¡Ö€Õ¤Õ«Ö‚Õ¶Ö„Õ¶Õ¥Ö€", "emoji_button.symbols": "Õ†Õ·Õ¡Õ¶Õ¶Õ¥Ö€", "emoji_button.travel": "ÕˆÖ‚Õ²Õ¥Ö‚Õ¸Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¥Ö‚ Õ¿Õ¥Õ²Õ¡Õ¶Ö„Õ¶Õ¥Ö€", + "empty_column.account_suspended": "Õ€Õ¡Õ·Õ«Ö‚Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ§", "empty_column.account_timeline": "Ô±ÕµÕ½Õ¿Õ¥Õ² Õ©Õ©Õ¥Ö€ Õ¹Õ¯Õ¡Õ›Õ¶Ö‰", "empty_column.account_unavailable": "Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ«", "empty_column.blocks": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¸Õ¹ Õ´Õ§Õ¯Õ« Õ¹Õ¥Õ½ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬Ö‰", - "empty_column.bookmarked_statuses": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¸Ö€Õ¥Ö‚Õ§ Õ§Õ»Õ¡Õ¶Õ·Ö‚Õ¡Õ® Õ©Õ¸Ö‚Õ©Ö‰ ÔµÖ€Õ¢ Õ§Õ»Õ¡Õ¶Õ·Õ¥Õ½, Õ¤Ö€Õ¡Õ¶Ö„ Õ¯Õ¥Ö€Õ¥Ö‚Õ¡Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", - "empty_column.community": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¨ Õ¤Õ¡Õ¿Õ¡Õ›Ö€Õ¯ Õ§Ö‰ Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ´Õ« Õ¢Õ¡Õ¶ Õ£Ö€Õ«Ö€ Õ·Õ¡Ö€ÕªÕ«Õ¹Õ¨ ÕÕ¸Õ¤ Õ¿Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", + "empty_column.bookmarked_statuses": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¸Ö€Õ¥Ö‚Õ§ Õ§Õ»Õ¡Õ¶Õ·Ö‚Õ¡Õ® Õ©Õ¸Ö‚Õ©Ö‰ ÔµÖ€Õ¢ Õ§Õ»Õ¡Õ¶Õ·Õ¥Õ½, Õ¤Ö€Õ¡Õ¶Ö„ Õ¯Õ¨ Õ¥Ö€Õ¥Ö‚Õ¡Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", + "empty_column.community": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¨ Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ Õ§Ö‰ Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ´Õ« Õ¢Õ¡Õ¶ Õ£Ö€Õ«Õ›Ö€ Õ·Õ¡Ö€ÕªÕ«Õ¹Õ¨ Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", "empty_column.direct": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¸Õ¹ Õ´Õ« Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Ö‰ ÔµÖ€Õ¢ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ½ Õ¯Õ¡Õ´ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ¸Ö€Õ¥Ö‚Õ§ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¶Õ¡Õ´Õ¡Õ¯, Õ¡ÕµÕ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ² Õ¯Õ¥Ö€Õ¥Ö‚Õ¡ÕµÖ‰", "empty_column.domain_blocks": "Ô¹Õ¡Ö„ÖÕ¸Ö‚Õ¡Õ® Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¶Õ¥Ö€ Õ¤Õ¥Õ¼ Õ¹Õ¯Õ¡Õ¶Ö‰", "empty_column.favourited_statuses": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¸Ö€Õ¥Ö‚Õ§ Õ°Õ¡Ö‚Õ¡Õ¶Õ¡Õ® Õ©Õ¸Ö‚Õ©Ö‰ ÔµÖ€Õ¢ Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Õ½, Õ¤Ö€Õ¡Õ¶Ö„ Õ¯Õ¥Ö€Õ¥Ö‚Õ¡Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", "empty_column.favourites": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¸Õ¹ Õ´Õ§Õ¯ Õ¤Õ¥Õ¼ Õ¹Õ« Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Õ¬Ö‰ Õ€Õ¡Ö‚Õ¡Õ¶Õ¸Õ²Õ¶Õ¥Ö€Õ¨ Õ¯Õ¥Ö€Õ¥Ö‚Õ¡Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ², Õ¥Ö€Õ¢ Õ¶Õ·Õ¥Õ¶ Õ©Õ¸Ö‚Õ©Õ¨ Õ°Õ¡Ö‚Õ¡Õ¶Õ¡Õ®Ö‰", "empty_column.follow_requests": "Ô´Õ¸Ö‚ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¸Ö€Õ¥Ö‚Õ§ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ ÕµÕ¡ÕµÕ¿Ö‰ Ô²Õ¸Õ¬Õ¸Ö€ Õ¶Õ´Õ¡Õ¶ ÕµÕ¡ÕµÕ¿Õ¥Ö€Õ¨ Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ¥Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", - "empty_column.hashtag": "Ô±ÕµÕ½ ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ¤Õ¥Õ¼ Õ¸Õ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡Ö‰", - "empty_column.home": "Õ”Õ¸ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¨ Õ¤Õ¡Õ¿Õ¡Õ›Ö€Õ¯ Õ§Ö‰ Ô±ÕµÖÕ¥Õ¬Õ«Õ›Ö€ {public}Õ¨ Õ¯Õ¡Õ´ Ö…Õ£Õ¿Õ¾Õ«Ö€ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ«ÖÕ Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ°Õ¡Õ¶Õ¤Õ«ÕºÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", + "empty_column.hashtag": "Ô±ÕµÕ½ ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ¤Õ¥Õ¼ Õ¸Õ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡ÕµÖ‰", + "empty_column.home": "Õ”Õ¸ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¨ Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ Õ§Ö‰ Ô±ÕµÖÕ¥Õ¬Õ«Õ›Ö€ {public}Õ¨ Õ¯Õ¡Õ´ Ö…Õ£Õ¿Õ¸Ö‚Õ«Ö€ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ«ÖÕ Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ°Õ¡Õ¶Õ¤Õ«ÕºÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", "empty_column.home.public_timeline": "Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„", - "empty_column.list": "Ô±ÕµÕ½ ÖÕ¡Õ¶Õ¯Õ¸Ö‚Õ´ Õ¤Õ¥Õ¼ Õ¸Õ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡Ö‰ ÔµÖ€Õ¢ ÖÕ¡Õ¶Õ¯Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ¶Õ¥Ö€Õ«Ö Õ¸Ö€Õ¥Ö‚Õ§ Õ´Õ¥Õ¯Õ¨ Õ¶Õ¸Ö€ Õ©Õ¸Ö‚Õ© Õ£Ö€Õ«, Õ¡ÕµÕ¶ Õ¯Õ°Õ¡ÕµÕ¿Õ¶Õ¾Õ« Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", - "empty_column.lists": "Ô´Õ¸Ö‚Ö„ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Ö„ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® ÖÕ¡Õ¶Õ¯Ö‰ Õ‘Õ¡Õ¶Õ¯ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬Õ¸Ö‚Õ¶ ÕºÕ¥Õ½ Õ¡ÕµÕ¶ Õ¯Õ°Õ¡ÕµÕ¿Õ¶Õ¾Õ« Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", - "empty_column.mutes": "Ô±Õ¼Õ¡ÕµÕªÕ´ Õ¸Õ¹ Õ¸Ö„Õ« Õ¹Õ¥Ö„ Õ¬Õ¼Õ¥ÖÖ€Õ¥Õ¬Ö‰", + "empty_column.list": "Ô±ÕµÕ½ ÖÕ¡Õ¶Õ¯Õ¸Ö‚Õ´ Õ¤Õ¥Õ¼ Õ¸Õ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡ÕµÖ‰ ÔµÖ€Õ¢ ÖÕ¡Õ¶Õ¯Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ¶Õ¥Ö€Õ«Ö Õ¸Ö€Õ¥Ö‚Õ§ Õ´Õ¥Õ¯Õ¨ Õ¶Õ¸Ö€ Õ©Õ¸Ö‚Õ© Õ£Ö€Õ«, Õ¡ÕµÕ¶ Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ« Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", + "empty_column.lists": "Ô´Õ¸Ö‚Ö„ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ§Ö„ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® ÖÕ¡Õ¶Õ¯Ö‰ Õ‘Õ¡Õ¶Õ¯ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬Õ¸Ö‚Õ¶ ÕºÕ§Õ½ Õ¡ÕµÕ¶ Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ« Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰", + "empty_column.mutes": "Ô±Õ¼Õ¡ÕµÕªÕ´ Õ¸Õ¹ Õ¸Ö„Õ« Õ¹Õ§Ö„ Õ¬Õ¼Õ¥ÖÖ€Õ¥Õ¬Ö‰", "empty_column.notifications": "ÕˆÕ¹ Õ´Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´ Õ¤Õ¥Õ¼ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½Ö‰ Ô²Õ¦Õ«Ö€ Õ´Õ«Ö‚Õ½Õ¶Õ¥Ö€Õ«Õ¶Õ ÕÖ…Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ½Õ¯Õ½Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", "empty_column.public": "Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¢Õ¡Õ¶ Õ¹Õ¯Õ¡Õ›ÕµÖ‰ Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ´Õ« Õ¢Õ¡Õ¶ Õ£Ö€Õ«Ö€ Õ¯Õ¡Õ´ Õ°Õ¥Õ¿Õ¥Ö‚Õ«Ö€ Õ¡ÕµÕ¬ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¶Õ¥Ö€Õ«Ö Õ§Õ¡Õ¯Õ¶Õ¥Ö€Õ«Õ Õ¡ÕµÕ¶ Õ¬ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰", "error.unexpected_crash.explanation": "Õ„Õ¥Ö€ Õ®Ö€Õ¡Õ£Ö€Õ¡Õ¯Õ¡Õ¦Õ´Õ¸Ö‚Õ´ Õ¾Ö€Õ«ÕºÕ¡Õ¯Õ« Õ¯Õ¡Õ´ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ« Õ¡Õ¶Õ°Õ¡Õ´Õ¡Õ¿Õ¥Õ²Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾ Õ¡ÕµÕ½ Õ§Õ»Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¬Õ«Õ¡Ö€ÕªÕ§Ö„ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¸Ö‚Õ¥Õ¬Ö‰", - "error.unexpected_crash.next_steps": "Õ“Õ¸Ö€Õ±Õ«Ö€ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ§Õ»Õ¨Ö‰ ÔµÕ©Õ¥ Õ¤Õ¡ Õ¹Ö…Õ£Õ¶Õ« Õ¡ÕºÕ¡ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¾Õ¥Õ¬ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ«Ö Õ¸Ö‚Ö€Õ«Õ· Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Õ¾ Õ¯Õ¡Õ´ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¸Õ¾Ö‰", + "error.unexpected_crash.explanation_addons": "Ô±ÕµÕ½ Õ§Õ»Õ« Õ³Õ«Õ·Õ¿ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¸Ö‚Õ´Õ¨ Õ¹Õ« Õ½Õ¿Õ¡ÖÕ¸Ö‚Õ´Ö‰ Ô½Õ¡ÖƒÕ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ°Õ¡Ö‚Õ¡Õ¶Õ¡Õ¢Õ¡Ö€ Õ¡Õ¼Õ¡Õ»Õ¡ÖÕ¥Õ¬ Õ§ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ« ÕµÕ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«Ö Õ¯Õ¡Õ´ Õ¡Õ¼ÖÕ¡Õ¶Ö Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ«Õ¹Õ«ÖÖ‰", + "error.unexpected_crash.next_steps": "Õ“Õ¸Ö€Õ±Õ«Ö€ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ§Õ»Õ¨Ö‰ ÔµÕ©Õ§ Õ¤Õ¡ Õ¹Ö…Õ£Õ¶Õ« Õ¡ÕºÕ¡ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¸Ö‚Õ¥Õ¬ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ«Ö Õ¸Ö‚Ö€Õ«Õ· Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Õ¾ Õ¯Õ¡Õ´ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¸Õ¾Ö‰", + "error.unexpected_crash.next_steps_addons": "Õ“Õ¸Ö€Õ±Õ«Ö€ Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ§Õ»Õ¨Ö‰ ÔµÕ©Õ¥ Õ¤Õ¡ Õ¹Ö…Õ£Õ¶Õ«, Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¸Ö‚Õ¥Õ¬ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ«Ö Õ¡ÕµÕ¬ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Õ¾ Õ¯Õ¡Õ´ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¸Õ¾Ö‰", "errors.unexpected_crash.copy_stacktrace": "ÕŠÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Õ¬ Õ½Õ©Õ¡Ö„Õ©Ö€Õ¥ÕµÕ½Õ¨ Õ½Õ¥Õ²Õ´Õ¡Õ¿Õ¡ÕÕ¿Õ¡Õ¯Õ«Õ¶", "errors.unexpected_crash.report_issue": "Ô¶Õ¥Õ¯Õ¸Ö‚ÖÕ¥Õ¬ ÕÕ¶Õ¤Ö€Õ« Õ´Õ¡Õ½Õ«Õ¶", - "follow_request.authorize": "ÕŽÕ¡Õ¾Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬", + "follow_request.authorize": "ÕŽÕ¡Ö‚Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬", "follow_request.reject": "Õ„Õ¥Ö€ÕªÕ¥Õ¬", - "follow_requests.unlocked_explanation": "Ô±ÕµÕ½ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ® Õ§ Õ°Õ¡Õ·Õ¾Õ«Ö, Õ¸Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€ {domain}-Õ« Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ¨ Õ´Õ«Õ¡ÖÖ€Õ¥Õ¬ Õ§ Õ±Õ¥Õ¼Ö„Õ¸Õ¾ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´Ö‰", - "generic.saved": "ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¾Õ¡Õ® Õ§", + "follow_requests.unlocked_explanation": "Ô±ÕµÕ½ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® Õ§ Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö, Õ¸Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€ {domain}-Õ« Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ¨ Õ´Õ«Õ¡ÖÖ€Õ¥Õ¬ Õ§ Õ±Õ¥Õ¼Ö„Õ¸Õ¾ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´Ö‰", + "generic.saved": "ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¸Ö‚Õ¡Õ® Õ§", "getting_started.developers": "Õ„Õ·Õ¡Õ¯Õ¸Õ²Õ¶Õ¥Ö€", "getting_started.directory": "Õ•Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ·Õ¿Õ¥Õ´Õ¡Ö€Õ¡Õ¶", "getting_started.documentation": "Õ“Õ¡Õ½Õ¿Õ¡Õ©Õ²Õ©Õ¥Ö€", - "getting_started.heading": "Ô»Õ¶Õ¹ÕºÕ¥Õ½ Õ½Õ¯Õ½Õ¥Õ¬", + "getting_started.heading": "Ô»Õ¶Õ¹ÕºÕ§Õ½ Õ½Õ¯Õ½Õ¥Õ¬", "getting_started.invite": "Õ€Ö€Õ¡Ö‚Õ«Ö€Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö", - "getting_started.open_source_notice": "Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ Õ¢Õ¡Ö Õ¥Õ¬Õ¡Õ¿Õ¥Ö„Õ½Õ¿Õ¸Õ¾ Õ®Ö€Õ¡Õ£Ö€Õ¡Õ¯Õ¡Õ¦Õ´ Õ§Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¶Õ¥Ö€Õ¤Ö€Õ¸Ö‚Õ´ Õ¡Õ¶Õ¥Õ¬ Õ¯Õ¡Õ´ Õ¾Ö€Õ¥ÕºÕ¶Õ¥Ö€ Õ¦Õ¥Õ¯Õ¸Ö‚ÖÕ¥Õ¬ Ô³Õ«Õ©Õ€Õ¡Õ¢Õ¸Ö‚Õ´Õ {github}Ö‰", + "getting_started.open_source_notice": "Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ Õ¢Õ¡Ö Õ¥Õ¬Õ¡Õ¿Õ¥Ö„Õ½Õ¿Õ¸Õ¾ Õ®Ö€Õ¡Õ£Ö€Õ¡Õ¯Õ¡Õ¦Õ´ Õ§Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¶Õ¥Ö€Õ¤Ö€Õ¸Ö‚Õ´ Õ¡Õ¶Õ¥Õ¬ Õ¯Õ¡Õ´ Õ¾Ö€Õ§ÕºÕ¶Õ¥Ö€ Õ¦Õ¥Õ¯Õ¸Ö‚ÖÕ¥Õ¬ Ô³Õ«Õ©Õ€Õ¡Õ¢Õ¸Ö‚Õ´Õ {github}Ö‰", "getting_started.security": "Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€", "getting_started.terms": "Ô¾Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨", "hashtag.column_header.tag_mode.all": "Õ¥Ö‚ {additional}", "hashtag.column_header.tag_mode.any": "Õ¯Õ¡Õ´ {additional}", "hashtag.column_header.tag_mode.none": "Õ¡Õ¼Õ¡Õ¶Ö {additional}", "hashtag.column_settings.select.no_options_message": "Ô±Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¶Õ¥Ö€ Õ¹Õ¯Õ¡Õ¶", - "hashtag.column_settings.select.placeholder": "Ô±Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¸Ö‚ հեշթեգեր…", + "hashtag.column_settings.select.placeholder": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÖ€Õ¸Ö‚ պիտկներ…", "hashtag.column_settings.tag_mode.all": "Ô²Õ¸Õ¬Õ¸Ö€Õ¨", "hashtag.column_settings.tag_mode.any": "Õ‘Õ¡Õ¶Õ¯Õ¡ÖÕ¡Õ®Õ¨", "hashtag.column_settings.tag_mode.none": "ÕˆÕ¹ Õ´Õ¥Õ¯Õ¨", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "Õ†Õ¥Ö€Õ¡Õ¼Õ¥Õ¬ Õ¬Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ Õ¡ÕµÕ½ Õ½Õ«Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ ", "home.column_settings.basic": "Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶", "home.column_settings.show_reblogs": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¿Õ¡Ö€Õ¡Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ¨", "home.column_settings.show_replies": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¶Õ¥Ö€Õ¨", @@ -197,17 +202,17 @@ "home.show_announcements": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨", "intervals.full.days": "{number, plural, one {# Ö…Ö€} other {# Ö…Ö€}}", "intervals.full.hours": "{number, plural, one {# ÕªÕ¡Õ´} other {# ÕªÕ¡Õ´}}", - "intervals.full.minutes": "{number, plural, one {# Ö€Õ¸ÕºÕ¥} other {# Ö€Õ¸ÕºÕ¥}}", - "introduction.federation.action": "Õ€Õ¡Õ»Õ¸Ö€Õ¤", + "intervals.full.minutes": "{number, plural, one {# Ö€Õ¸ÕºÕ§} other {# Ö€Õ¸ÕºÕ§}}", + "introduction.federation.action": "Õ…Õ¡Õ»Õ¸Ö€Õ¤", "introduction.federation.federated.headline": "Ô´Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶", "introduction.federation.federated.text": "Ô´Õ¡Õ·Õ¶Õ¥Õ¦Õ¥Ö€Ö„Õ« Õ°Õ¡Ö€Õ¥Ö‚Õ¡Õ¶ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¶Õ¥Ö€Õ« Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ¥Õ¶ Õ¤Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´Ö‰", "introduction.federation.home.headline": "Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶", "introduction.federation.home.text": "Ô±ÕµÕ¶ Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ©Õ©Õ¥Ö€Õ¨ Õ¸Ö‚Õ´ Õ°Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ Õ¥Õ½, Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ¥Õ¶ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´Ö‰ Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ¡Õ¶Õ±Õ« ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ«ÖÖ‰", "introduction.federation.local.headline": "ÕÕ¥Õ²Õ¡ÕµÕ«Õ¶", "introduction.federation.local.text": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Ö„Õ¸ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", - "introduction.interactions.action": "Finish toot-orial!", + "introduction.interactions.action": "Ô±Ö‚Õ¡Ö€Õ¿Õ¥Õ¬ Õ©Õ©Õ« Õ¤Õ¡Õ½Õ¨Õ¶Õ©Õ¡ÖÕ¨", "introduction.interactions.favourite.headline": "Õ†Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¥Õ¬Õ«", - "introduction.interactions.favourite.text": "Õ“Õ¸ÕÕ¡Õ¶ÖÕ«Ö€ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ«Õ¶ Õ¸Ö€ Ö„Õ¥Õ¦ Õ¤Õ¸Ö‚Ö€ Õ§ Õ¥Õ¯Õ¥Õ¬ Õ«Ö€ Õ©Õ¸Ö‚Õ©Õ¨ Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬Õ¸Õ¾ Õ¡ÕµÕ¶Ö‰", + "introduction.interactions.favourite.text": "Õ“Õ¸ÕÕ¡Õ¶ÖÕ«Ö€ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ«Õ¶ Õ¸Ö€ Ö„Õ¥Õ¦ Õ¤Õ¸Ö‚Ö€ Õ§ Õ¥Õ¯Õ¥Õ¬ Õ«Ö€ Õ©Õ¸Ö‚Õ©Õ¨ Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Õ¬Õ¸Õ¾ Õ¡ÕµÕ¶Ö‰", "introduction.interactions.reblog.headline": "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬", "introduction.interactions.reblog.text": "Ô¿Õ«Õ½Õ«Ö€ Õ¡ÕµÕ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ©Õ¸Ö‚Õ©Õ¥Ö€Õ¨ Ö„Õ¸ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿ Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬Õ¸Õ¾ Õ¤Ö€Õ¡Õ¶Ö„ Ö„Õ¸ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¸Ö‚Õ´Ö‰", "introduction.interactions.reply.headline": "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬", @@ -215,25 +220,25 @@ "introduction.welcome.action": "Ô³Õ¶Õ¡Öի՜նք։", "introduction.welcome.headline": "Ô±Õ¼Õ¡Õ»Õ«Õ¶ Ö„Õ¡ÕµÕ¬Õ¥Ö€", "introduction.welcome.text": "Ô´Õ¡Õ·Õ¶Õ¥Õ¦Õ¥Ö€Ö„Õ¨ Õ¸Õ²Õ»Õ¸Ö‚Õ¶Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Õ¦Ö‰ Õ‡Õ¸Ö‚Õ¿Õ¸Õ¾ Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Õ½ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¶Õ¡Õ´Õ¡Õ¯Õ¶Õ¥Ö€ Õ¸Ö‚ Õ·ÖƒÕ¸Ö‚Õ¥Õ¬ Õ¿Õ¡Ö€Õ¢Õ¥Ö€ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¶Õ¥Ö€Õ« Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤ Õ°Õ¥Õ¿Ö‰ Ô²Õ¡ÕµÖ Õ´Õ¿Õ¡ÕºÕ¡Õ°Õ«Ö€ {domain} Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¨, Õ¡ÕµÕ¶ Õ«Ö‚Ö€Õ¡ÕµÕ¡Õ¿Õ¸Ö‚Õ¯ Õ§, Õ¡ÕµÕ½Õ¿Õ¥Õ² Õ§ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Ö„Õ¸ Õ°Õ¡Õ·Õ«Ö‚Õ¨Ö‰", - "keyboard_shortcuts.back": "Õ¥Õ¿ Õ¶Õ¡Õ¾Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.blocked": "Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.back": "Õ¥Õ¿ Õ¶Õ¡Ö‚Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.blocked": "Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.boost": "Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.column": "Õ½Õ«Ö‚Õ¶Õ¥Ö€Õ«Ö Õ´Õ§Õ¯Õ« Õ¾Ö€Õ¡Õµ Õ½Õ¥Ö‚Õ¥Õ¼Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.compose": "Õ·Õ¡Ö€Õ¡Õ¤Ö€Õ´Õ¡Õ¶ Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ«Õ¶ Õ½Õ¥Ö‚Õ¥Õ¼Õ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.compose": "Õ·Õ¡Ö€Õ¡Õ¤Ö€Õ´Õ¡Õ¶ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ«Õ¶ Õ½Õ¥Ö‚Õ¥Õ¼Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.description": "Õ†Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶", - "keyboard_shortcuts.direct": "Õ°Õ¡Õ½ÖÕ¥Õ¡Õ£Ö€Õ¾Õ¡Õ® Õ£Ö€Õ¾Õ¡Õ®Ö„Õ¶Õ¥Ö€Õ« Õ°Õ¸Õ½Ö„Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.down": "ÖÕ¡Õ¶Õ¯Õ¸Õ¾ Õ¶Õ¥Ö€Ö„Õ¥Ö‚ Õ·Õ¡Ö€ÕªÕ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.direct": "Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ£Ö€Õ¸Ö‚Õ¡Õ®Ö„Õ¶Õ¥Ö€Õ« Õ°Õ¸Õ½Ö„Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.down": "ÖÕ¡Õ¶Õ¯Õ¸Õ¾ Õ¶Õ¥Ö€Ö„Õ¥Ö‚ Õ·Õ¡Ö€ÕªÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.enter": "Õ©Õ¸Ö‚Õ©Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.favourite": "Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.favourite": "Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.favourites": "Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.federated": "Õ¤Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ«Õ¶ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.heading": "ÕÕ¿Õ¥Õ²Õ¶Õ¡Õ·Õ¡Ö€Õ« Õ¯Õ¡Ö€Õ³Õ¡Õ¿Õ¶Õ¥Ö€", "keyboard_shortcuts.home": "Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ«Õ¶ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.hotkey": "Õ€Õ¡Õ¿Õ¸Ö‚Õ¯ Õ½Õ¿Õ¥Õ²Õ¶", + "keyboard_shortcuts.hotkey": "Õ…Õ¡Õ¿Õ¸Ö‚Õ¯ Õ½Õ¿Õ¥Õ²Õ¶", "keyboard_shortcuts.legend": "Õ¡ÕµÕ½ Õ±Õ¥Õ¼Õ¶Õ¡Ö€Õ¯Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.local": "Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ«Õ¶ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.mention": "Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ«Õ¶ Õ¶Õ·Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.muted": "Õ¬Õ¼Õ¥ÖÕ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.muted": "Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.my_profile": "Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ«Õ¶ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.notifications": "Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ½Õ«Ö‚Õ¶Õ¡Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.open_media": "ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡Õ¶", @@ -242,34 +247,41 @@ "keyboard_shortcuts.reply": "ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.requests": "Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖÕ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ¨ Õ¤Õ«Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.search": "Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¤Õ¡Õ·Õ¿Õ«Õ¶ Õ½Õ¥Ö‚Õ¥Õ¼Õ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "Õ¸Ö€ÕºÕ§Õ½Õ¦Õ« ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ«/Õ©Õ¡Ö„ÖÕ¸Ö‚Õ« CW Õ¤Õ¡Õ·Õ¿Õ¨", "keyboard_shortcuts.start": "«սկսել» Õ½Õ«Ö‚Õ¶Õ¡Õ¯Õ¨ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.toggle_hidden": "CWÖŠÕ« Õ¥Õ¿Õ¥Ö‚Õ« Õ¿Õ¥Ö„Õ½Õ¿Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ÖŠÕ©Õ¡Ö„ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.toggle_sensitivity": "Õ´Õ¥Õ¤Õ«Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ÖŠÕ©Õ¡Ö„ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "keyboard_shortcuts.toot": "Õ©Õ¡Ö€Õ´ Õ©Õ¸Ö‚Õ© Õ½Õ¯Õ½Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.unfocus": "Õ¿Õ¥Ö„Õ½Õ¿Õ«/Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ«Ö Õ¡ÕºÕ¡Õ½Õ¥Ö‚Õ¥Õ¼Õ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "keyboard_shortcuts.up": "ÖÕ¡Õ¶Õ¯Õ¸Õ¾ Õ¾Õ¥Ö€Õ¥Ö‚ Õ·Õ¡Ö€ÕªÕ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.unfocus": "Õ¿Õ¥Ö„Õ½Õ¿Õ«/Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ«Ö Õ¡ÕºÕ¡Õ½Õ¥Ö‚Õ¥Õ¼Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", + "keyboard_shortcuts.up": "ÖÕ¡Õ¶Õ¯Õ¸Õ¾ Õ¾Õ¥Ö€Õ¥Ö‚ Õ·Õ¡Ö€ÕªÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", "lightbox.close": "Õ“Õ¡Õ¯Õ¥Õ¬", - "lightbox.next": "Õ€Õ¡Õ»Õ¸Ö€Õ¤", + "lightbox.compress": "Õ“Õ¡Õ¯Õ¥Õ¬ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ« Õ¤Õ«Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨", + "lightbox.expand": "Ô²Õ¡ÖÕ¥Õ¬ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ« Õ¤Õ«Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨", + "lightbox.next": "Õ…Õ¡Õ»Õ¸Ö€Õ¤", "lightbox.previous": "Õ†Õ¡ÕÕ¸Ö€Õ¤", - "lightbox.view_context": "ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ¥Õ¶Õ©Õ¡Õ¿Õ¥Ö„Õ½Õ¿Õ¨", - "lists.account.add": "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ«Õ¶", + "lists.account.add": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ«Õ¶", "lists.account.remove": "Õ€Õ¡Õ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ«Ö", "lists.delete": "Õ‹Õ¶Õ»Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¨", "lists.edit": "Õ“Õ¸ÖƒÕ¸ÕÕ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¨", "lists.edit.submit": "Õ“Õ¸ÕÕ¥Õ¬ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€Õ¨", - "lists.new.create": "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯", + "lists.new.create": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯", "lists.new.title_placeholder": "Õ†Õ¸Ö€ ÖÕ¡Õ¶Õ¯Õ« Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€", - "lists.search": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Õ¥Ö‚Õ¡Õ® Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ´Õ¥Õ»", + "lists.replies_policy.followed": "Õ‘Õ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ² Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€", + "lists.replies_policy.list": "Õ‘Õ¡Õ¶Õ¯Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ¶Õ¥Ö€", + "lists.replies_policy.none": "ÕˆÕ¹ Õ¸Ö„", + "lists.replies_policy.title": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¶Õ¥Ö€Õ¨Õ", + "lists.search": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Õ¥Ö‚Õ¡Õ® Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ´Õ§Õ»", "lists.subheading": "Õ”Õ¸ ÖÕ¡Õ¶Õ¯Õ¥Ö€Õ¨", "load_pending": "{count, plural, one {# Õ¶Õ¸Ö€ Õ¶Õ«Ö‚Õ©} other {# Õ¶Õ¸Ö€ Õ¶Õ«Ö‚Õ©}}", - "loading_indicator.label": "Ô²Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ է…", + "loading_indicator.label": "Ô²Õ¥Õ¼Õ¶Ö‚Õ¸Ö‚Õ´ է…", "media_gallery.toggle_visible": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬/Õ©Õ¡Ö„ÖÕ¶Õ¥Õ¬", - "missing_indicator.label": "Õ‰Õ£Õ¿Õ¶Õ¾Õ¥Ö", + "missing_indicator.label": "Õ‰Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Ö", "missing_indicator.sublabel": "ÕŠÕ¡Õ·Õ¡Ö€Õ¨ Õ¹Õ« Õ£Õ¿Õ¶Ö‚Õ¸Ö‚Õ´", + "mute_modal.duration": "ÕÕ¥Ö‚Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶", "mute_modal.hide_notifications": "Ô¹Õ¡Ö„ÖÕ¶Õ¥ÕžÕ¬ ÖÕ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶ Õ¡ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ«ÖÖ‰", + "mute_modal.indefinite": "Ô±Õ¶ÕªÕ¡Õ´Õ¯Õ§Õ¿", "navigation_bar.apps": "Ô´Õ«Ö‚Ö€Õ¡Õ¯Õ«Ö€ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€", - "navigation_bar.blocks": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€", + "navigation_bar.blocks": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€", "navigation_bar.bookmarks": "Ô·Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€", "navigation_bar.community_timeline": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„", "navigation_bar.compose": "Ô³Ö€Õ¥Õ¬ Õ¶Õ¸Ö€ Õ©Õ¸Ö‚Õ©", @@ -285,22 +297,23 @@ "navigation_bar.keyboard_shortcuts": "ÕÕ¿Õ¥Õ²Õ¶Õ¡Õ·Õ¡Ö€Õ« Õ¯Õ¡Ö€Õ³Õ¡Õ¿Õ¶Õ¥Ö€", "navigation_bar.lists": "Õ‘Õ¡Õ¶Õ¯Õ¥Ö€", "navigation_bar.logout": "Ô´Õ¸Ö‚Ö€Õ½ Õ£Õ¡Õ¬", - "navigation_bar.mutes": "Ô¼Õ¼Õ¥ÖÖ€Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€", + "navigation_bar.mutes": "Ô¼Õ¼Õ¥ÖÖ€Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€", "navigation_bar.personal": "Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶", - "navigation_bar.pins": "Ô±Õ´Ö€Õ¡ÖÕ¾Õ¡Õ® Õ©Õ©Õ¥Ö€", + "navigation_bar.pins": "Ô±Õ´Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ©Õ©Õ¥Ö€", "navigation_bar.preferences": "Õ†Õ¡ÕÕ¡ÕºÕ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€", "navigation_bar.public_timeline": "Ô´Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„", "navigation_bar.security": "Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ«Ö‚Õ¶", - "notification.favourite": "{name} Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Ö Õ©Õ¸Ö‚Õ©Õ¤", + "notification.favourite": "{name} Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Ö Õ©Õ¸Ö‚Õ©Õ¤", "notification.follow": "{name} Õ½Õ¯Õ½Õ¥Ö Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Ö„Õ¥Õ¦", "notification.follow_request": "{name} Ö„Õ¥Õ¦ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬", "notification.mention": "{name} Õ¶Õ·Õ¥Ö Ö„Õ¥Õ¦", "notification.own_poll": "Õ€Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¤ Õ¡Ö‚Õ¡Ö€Õ¿Õ¸Ö‚Õ¥Ö", "notification.poll": "Õ€Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨, Õ¸Ö‚Ö€ Õ¤Õ¸Ö‚ Ö„Õ¸Ö‚Õ§Õ¡Ö€Õ¯Õ¥Õ¬ Õ¥Õ½, Õ¡Ö‚Õ¡Ö€Õ¿Õ¸Ö‚Õ¥ÖÖ‰", "notification.reblog": "{name} Õ¿Õ¡Ö€Õ¡Õ®Õ¥Ö Õ©Õ¸Ö‚Õ©Õ¤", + "notification.status": "{name} Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ©Õ©Õ¥Ö", "notifications.clear": "Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", - "notifications.clear_confirmation": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ´Õ·Õ¿Õ¡ÕºÕ¥Õ½ Õ´Õ¡Ö„Ö€Õ¥Õ¬ Ö„Õ¸ Õ¢Õ¸Õ¬Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", - "notifications.column_settings.alert": "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€", + "notifications.clear_confirmation": "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ´Õ·Õ¿Õ¡ÕºÕ§Õ½ Õ´Õ¡Ö„Ö€Õ¥Õ¬ Ö„Õ¸ Õ¢Õ¸Õ¬Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰", + "notifications.column_settings.alert": "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€", "notifications.column_settings.favourite": "Õ€Õ¡Ö‚Õ¡Õ¶Õ¡Õ®Õ¶Õ¥Ö€Õ«ÖÕ", "notifications.column_settings.filter_bar.advanced": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¯Õ¡Õ¿Õ¥Õ£Õ¸Ö€Õ«Õ¡Õ¶Õ¥Ö€Õ¨", "notifications.column_settings.filter_bar.category": "Ô±Ö€Õ¡Õ£ Õ¦Õ¿Õ´Õ¡Õ¶ Õ¾Õ¡Õ°Õ¡Õ¶Õ¡Õ¯", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "ÕÕ¡Ö€Õ¡Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ«ÖÕ", "notifications.column_settings.show": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ½Õ«Ö‚Õ¶Õ¸Ö‚Õ´", "notifications.column_settings.sound": "ÕÕ¡ÕµÕ¶ Õ°Õ¡Õ¶Õ¥Õ¬", + "notifications.column_settings.status": "Õ†Õ¸Ö€ Õ©Õ©Õ¥Ö€Ö‰", "notifications.filter.all": "Ô²Õ¸Õ¬Õ¸Ö€Õ¨", "notifications.filter.boosts": "ÕÕ¡Ö€Õ¡Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ¨", "notifications.filter.favourites": "Õ€Õ¡Ö‚Õ¡Õ¶Õ¡Õ®Õ¶Õ¥Ö€Õ¨", "notifications.filter.follows": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¡Õ®Õ¶Õ¥Ö€Õ¨", "notifications.filter.mentions": "Õ†Õ·Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", "notifications.filter.polls": "Õ€Õ¡Ö€ÖÕ´Õ¡Õ¶ Õ¡Ö€Õ¤Õ«Ö‚Õ¶Ö„Õ¶Õ¥Ö€Õ¨", + "notifications.filter.statuses": "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Ö", + "notifications.grant_permission": "Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬Ö‰", "notifications.group": "{count} Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´", + "notifications.mark_as_read": "Õ€Õ¡Õ´Õ¡Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¨Õ¶Õ©Õ¥Ö€ÖÕ¡Õ®", + "notifications.permission_denied": "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶ Õ¡Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶Õ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ« Õ¶Õ¡ÕÕ¯Õ«Õ¶Õ¸Ö‚Õ´ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¡Õ® Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ°Õ¡ÕµÖÕ´Õ¡Õ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¡Õ¶Ö„Õ¸Õ¾", + "notifications.permission_denied_alert": "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¥Õ¬, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ« Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¶Õ¡ÕÕ¯Õ«Õ¶Õ¸Ö‚Õ´ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¥Õ¬ Õ¥Õ¶", + "notifications.permission_required": "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶ Õ¡Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´ Õ¥Õ¶Ö‰", + "notifications_permission_banner.enable": "Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ«Ö Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", + "notifications_permission_banner.how_to_control": "Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€, Õ¥Ö€Õ¢ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ Õ¢Õ¡Ö Õ¹Õ§Õ Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÖ€Õ¸Ö‚ Õ¡Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ³Õ·Õ£Ö€Õ¿Ö…Ö€Õ§Õ¶ Õ¾Õ¥Ö€Õ¡Õ°Õ½Õ¯Õ¥Õ¬ Õ©Õ§ Õ«Õ¶Õ¹ÕºÕ«Õ½Õ« ÖƒÕ¸ÕÕ£Õ¸Ö€Õ®Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ Õ¡Õ¼Õ¡Õ»Õ¡Õ¶Õ¡Õ¶ Õ¡Õ·ÕÕ¡Õ¿Õ¡Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«ÖÕ {icon}Õ« Õ¯Õ¸Õ³Õ¡Õ¯Õ¸Õ¾Õ Õ¡ÕµÕ¶ Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚Ö ÕµÕ¥Õ¿Õ¸ÕµÖ‰", + "notifications_permission_banner.title": "ÕˆÕ¹Õ«Õ¶Õ¹ Õ¢Õ¡Ö Õ´Õ« Õ©Õ¸Õ²", + "picture_in_picture.restore": "Õ…Õ¥Õ¿ Õ¢Õ¥Ö€Õ¥Õ¬", "poll.closed": "Õ“Õ¡Õ¯", "poll.refresh": "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬", "poll.total_people": "{count, plural, one {# Õ°Õ¸Õ£Õ«} other {# Õ°Õ¸Õ£Õ«}}", @@ -329,8 +353,8 @@ "poll_button.add_poll": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´", "poll_button.remove_poll": "Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨", "privacy.change": "Ô¿Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ Õ©Õ©Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", - "privacy.direct.long": "Ô¹Õ©Õ¥Õ¬ Õ´Õ«Õ¡ÕµÕ¶ Õ¶Õ·Õ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€", - "privacy.direct.short": "Õ€Õ¡Õ½ÖÕ¥Õ¡Õ£Ö€Õ¾Õ¡Õ®", + "privacy.direct.long": "Ô¹Õ©Õ¥Õ¬ Õ´Õ«Õ¡ÕµÕ¶ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€", + "privacy.direct.short": "Õ€Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ®", "privacy.private.long": "Ô¹Õ©Õ¥Õ¬ Õ´Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€", "privacy.private.short": "Õ„Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ«Õ¶", "privacy.public.long": "Ô¹Õ©Õ¥Õ¬ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¥Ö€Õ¸Ö‚Õ´", @@ -349,17 +373,17 @@ "reply_indicator.cancel": "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬", "report.forward": "Õ“Õ¸ÕÕ¡Õ¶ÖÕ¥Õ¬ {target}ÖŠÕ«Õ¶", "report.forward_hint": "Ô±ÕµÕ½ Õ°Õ¡Õ·Õ«Ö‚ Õ¡ÕµÕ¬ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ«Ö Õ§Ö‰ ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥ÕžÕ´ Õ¡ÕµÕ¶Õ¿Õ¥Õ² Õ§Õ¬ Õ¡ÕµÕ½ Õ¢Õ¸Õ²Õ¸Ö„Õ« Õ¡Õ¶Õ¸Õ¶Õ«Õ´ ÕºÕ¡Õ¿Õ³Õ§Õ¶Õ¨Ö‰", - "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "report.hint": "Ô±ÕµÕ½ Õ¦Õ¥Õ¯Õ¸ÕµÖÕ¨ Õ¯Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ« Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ´Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€Õ¶Õ¥Ö€Õ«Õ¶Ö‰ Õ†Õ¥Ö€Ö„Õ¥Ö‚Õ¸Ö‚Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¥Õ¬ Õ¢Õ¡ÖÕ¡Õ¿Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶, Õ©Õ§ Õ«Õ¶Õ¹Õ¸Ö‚ Õ¥Õ½ Õ¦Õ¥Õ¯Õ¸Ö‚ÖÕ¸Ö‚Õ´ Õ¡ÕµÕ½ Õ°Õ¡Õ·Õ¸Ö‚Õ« մասին․", "report.placeholder": "Ô¼Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€", "report.submit": "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬", "report.target": "Ô²Õ¸Õ²Õ¸Ö„Õ¥Õ¬ {target}ÖŠÕ« Õ´Õ¡Õ½Õ«Õ¶", "search.placeholder": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬", - "search_popout.search_format": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬Õ¸Ö‚ Õ¡Õ¼Õ¡Õ»Õ¡Õ¤Õ¥Õ´ Õ±Õ¥Ö‚", + "search_popout.search_format": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬Õ¸Ö‚ Õ¡Õ¼Õ¡Õ»Õ¡Õ¤Õ§Õ´ Õ±Õ¥Ö‚", "search_popout.tips.full_text": "ÕŠÕ¡Ö€Õ¦ Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¶Õ¸Ö‚Õ´ Õ§ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¤, Õ°Õ¡Ö‚Õ¡Õ¶Õ¡Õ®Õ¶Õ¥Ö€Õ¤, Õ¿Õ¡Ö€Õ¡Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ¤, Õ¸Ö€Õ¿Õ¥Õ² Õ¥Õ½ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Õ¥Õ²Õ¥Õ¬, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Õ¥Ö‚ Õ¶Õ´Õ¡Õ¶ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€, Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¥Ö‚ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Ö‰", "search_popout.tips.hashtag": "ÕºÕ«Õ¿Õ¡Õ¯", "search_popout.tips.status": "Õ©Õ¸Ö‚Õ©", - "search_popout.tips.text": "Õ€Õ¡Õ½Õ¡Ö€Õ¡Õ¯ Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Õ¯Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¶Õ« Õ°Õ¡Õ´Õ¨Õ¶Õ¯Õ¶Õ¸Õ² Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€, Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¸Ö‚ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€", - "search_popout.tips.user": "Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€", + "search_popout.tips.text": "Õ€Õ¡Õ½Õ¡Ö€Õ¡Õ¯ Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Õ¯Õ¨ Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¶Õ« Õ°Õ¡Õ´Õ¨Õ¶Õ¯Õ¶Õ¸Õ² Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€, Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¸Ö‚ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€", + "search_popout.tips.user": "Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€", "search_results.accounts": "Õ„Õ¡Ö€Õ¤Õ«Õ¯", "search_results.hashtags": "ÕŠÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€", "search_results.statuses": "Ô¹Õ©Õ¥Ö€", @@ -370,24 +394,24 @@ "status.block": "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ @{name}ÖŠÕ«Õ¶", "status.bookmark": "Ô·Õ»Õ¡Õ¶Õ«Õ·", "status.cancel_reblog_private": "Ô±ÕºÕ¡Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬", - "status.cannot_reblog": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¿Õ¡Ö€Õ¡Õ®Õ¾Õ¥Õ¬", - "status.copy": "ÕŠÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ°Õ²Õ¸Ö‚Õ´Õ¨", + "status.cannot_reblog": "Ô±ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ¥Õ¬", + "status.copy": "ÕŠÕ¡Õ¿Õ³Õ§Õ¶Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ ÕµÕ²Õ¸Ö‚Õ´Õ¨", "status.delete": "Õ‹Õ¶Õ»Õ¥Õ¬", - "status.detailed_status": "Õ‡Õ²Õ©Õ¡ÕµÕ« Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¾Õ¡Õ® Õ¤Õ«Õ¿Õ¸Ö‚Õ´", + "status.detailed_status": "Õ‡Õ²Õ©Õ¡ÕµÕ« Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¸Ö‚Õ¡Õ® Õ¤Õ«Õ¿Õ¸Ö‚Õ´", "status.direct": "Õ†Õ¡Õ´Õ¡Õ¯ Õ£Ö€Õ¥Õ¬ {name} -Õ«Õ¶", "status.embed": "Õ†Õ¥Ö€Õ¤Õ¶Õ¥Õ¬", - "status.favourite": "Õ€Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬", - "status.filtered": "Ô¶Õ¿Õ¾Õ¡Õ®", - "status.load_more": "Ô²Õ¥Õ¼Õ¶Õ¥Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶", + "status.favourite": "Õ€Õ¡Ö‚Õ¡Õ¶Õ¥Õ¬", + "status.filtered": "Ô¶Õ¿Õ¸Ö‚Õ¡Õ®", + "status.load_more": "Ô²Õ¥Õ¼Õ¶Õ¥Õ¬ Õ¡Ö‚Õ¥Õ¬Õ«Õ¶", "status.media_hidden": "Õ´Õ¥Õ¤Õ«Õ¡Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ©Õ¡Ö„ÖÕ¸Ö‚Õ¡Õ® Õ§", "status.mention": "Õ†Õ·Õ¥Õ¬ @{name}ÖŠÕ«Õ¶", - "status.more": "Ô±Õ¾Õ¥Õ¬Õ«Õ¶", + "status.more": "Ô±Ö‚Õ¥Õ¬Õ«Õ¶", "status.mute": "Ô¼Õ¼Õ¥ÖÕ¶Õ¥Õ¬ @{name}ÖŠÕ«Õ¶", "status.mute_conversation": "Ô¼Õ¼Õ¥ÖÕ¶Õ¥Õ¬ ÕÖ…Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "status.open": "Ô¸Õ¶Õ¤Õ¡Ö€Õ±Õ¡Õ¯Õ¥Õ¬ Õ¡ÕµÕ½ Õ©Õ¸Ö‚Õ©Õ¨", "status.pin": "Ô±Õ´Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¸Ö‚Õ´", - "status.pinned": "Ô±Õ´Ö€Õ¡ÖÕ¾Õ¡Õ® Õ©Õ¸Ö‚Õ©", - "status.read_more": "Ô¿Õ¡Ö€Õ¤Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶", + "status.pinned": "Ô±Õ´Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ©Õ¸Ö‚Õ©", + "status.read_more": "Ô¿Õ¡Ö€Õ¤Õ¡Õ¬ Õ¡Ö‚Õ¥Õ¬Õ«Õ¶", "status.reblog": "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬", "status.reblog_private": "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ¬Õ½Õ¡Ö€Õ¡Õ¶Õ«Õ¶", "status.reblogged_by": "{name} Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ§", @@ -395,20 +419,20 @@ "status.redraft": "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¥Ö‚ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¦Õ´Õ¥Õ¬", "status.remove_bookmark": "Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€Õ«Ö", "status.reply": "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬", - "status.replyAll": "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬ Õ©Õ¥Õ¬Õ«Õ¶", + "status.replyAll": "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬ Õ·Õ²Õ©Õ¡ÕµÕ«Õ¶", "status.report": "Ô²Õ¸Õ²Õ¸Ö„Õ¥Õ¬ @{name}ÖŠÕ«Ö", "status.sensitive_warning": "Ô¿Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶", - "status.share": "Ô¿Õ«Õ½Õ¾Õ¥Õ¬", + "status.share": "Ô¿Õ«Õ½Õ¸Ö‚Õ¥Õ¬", "status.show_less": "ÕŠÕ¡Õ¯Õ¡Õ½", "status.show_less_all": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¶Õ¡ÕÕ¡Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", - "status.show_more": "Ô±Õ¾Õ¥Õ¬Õ«Õ¶", + "status.show_more": "Ô±Ö‚Õ¥Õ¬Õ«Õ¶", "status.show_more_all": "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¶Õ¡ÕÕ¡Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨", "status.show_thread": "Ô²Õ¡ÖÕ¥Õ¬ Õ·Õ²Õ©Õ¡Õ¶", "status.uncached_media_warning": "Ô±Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«", "status.unmute_conversation": "Ô±ÕºÕ¡Õ¬Õ¼Õ¥ÖÕ¶Õ¥Õ¬ ÕÖ…Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "status.unpin": "Õ€Õ¡Õ¶Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ«Ö", "suggestions.dismiss": "Ô±Õ¶Õ¿Õ¥Õ½Õ¥Õ¬ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¨", - "suggestions.header": "Õ„Õ«Õ£Õ¸Ö‚ÖÕ¥ Ö„Õ¥Õ¦ հետաքրքրի…", + "suggestions.header": "Õ„Õ«Õ£Õ¸Ö‚ÖÕ§ Ö„Õ¥Õ¦ հետաքրքրի…", "tabs_bar.federated_timeline": "Ô´Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶", "tabs_bar.home": "Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶", "tabs_bar.local_timeline": "ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶", @@ -416,46 +440,47 @@ "tabs_bar.search": "Õ“Õ¶Õ¿Ö€Õ¥Õ¬", "time_remaining.days": "{number, plural, one {Õ´Õ¶Õ¡Ö # Ö…Ö€} other {Õ´Õ¶Õ¡Ö # Ö…Ö€}}", "time_remaining.hours": "{number, plural, one {# ÕªÕ¡Õ´} other {# ÕªÕ¡Õ´}} Õ¡Õ¶Ö", - "time_remaining.minutes": "{number, plural, one {# Ö€Õ¸ÕºÕ¥} other {# Ö€Õ¸ÕºÕ¥}} Õ¡Õ¶Ö", + "time_remaining.minutes": "{number, plural, one {# Ö€Õ¸ÕºÕ§} other {# Ö€Õ¸ÕºÕ§}} Õ¡Õ¶Ö", "time_remaining.moments": "Õ„Õ¶Õ¡ÖÕ¥Õ¬ Õ§ Õ´Õ« Ö„Õ¡Õ¶Õ« Õ¾Õ¡Ö€Õ¯Õ¥Õ¡Õ¶", "time_remaining.seconds": "{number, plural, one {# Õ¾Õ¡Ö€Õ¯Õ¥Õ¡Õ¶} other {# Õ¾Õ¡Ö€Õ¯Õ¥Õ¡Õ¶}} Õ¡Õ¶Ö", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", + "timeline_hint.remote_resource_not_displayed": "{resource} Õ¡ÕµÕ¬ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶Õ¥Ö€Õ«Ö Õ¹Õ¥Õ¶ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¥Õ¬:", "timeline_hint.resources.followers": "Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€", - "timeline_hint.resources.follows": "Õ€Õ¥Õ¿Ö‡Õ¥Õ¬", + "timeline_hint.resources.follows": "Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬", "timeline_hint.resources.statuses": "Õ€Õ«Õ¶ Õ©Õ¸Ö‚Õ©Õ¥Ö€", - "trends.counter_by_accounts": "{count, plural, one {{counter} Õ´Õ¡Ö€Õ¤} other {{counter} Õ´Õ¡Ö€Õ¤Õ«Õ¯}} ÕÕ¸Õ½Õ¸Ö‚Õ´ Õ¥Õ¶", + "trends.counter_by_accounts": "{count, plural, one {{counter} Õ´Õ¡Ö€Õ¤} other {{counter} Õ´Õ¡Ö€Õ¤Õ«Õ¯}} ÕÖ…Õ½Õ¸Ö‚Õ´ Õ¥Õ¶", "trends.trending_now": "Ô±ÕµÕªÕ´ Õ¡Ö€Õ¤Õ«Õ¡Õ¯Õ¡Õ¶", - "ui.beforeunload": "Õ”Õ¸ Õ½Õ¥Ö‚Õ¡Õ£Õ«Ö€Õ¨ Õ¯Õ¯Õ¸Ö€Õ«, Õ¥Õ©Õ¥ Õ¬Ö„Õ¥Õ½ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨Ö‰", + "ui.beforeunload": "Õ”Õ¸ Õ½Õ¥Ö‚Õ¡Õ£Õ«Ö€Õ¨ Õ¯Õ¨ Õ¯Õ¸Ö€Õ«, Õ¥Õ©Õ§ Õ¬Ö„Õ¥Õ½ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨Ö‰", "units.short.billion": "{count}Õ´Õ¬Ö€Õ¤", "units.short.million": "{count}Õ´Õ¬Õ¶", "units.short.thousand": "{count}Õ€Õ¡Õ¦.", "upload_area.title": "Õ”Õ¡Õ·Õ«Ö€ Õ¸Ö‚ Õ¶Õ¥Õ¿Õ«Ö€Õ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€", - "upload_button.label": "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡", - "upload_error.limit": "Õ–Õ¡ÕµÕ¬Õ« Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ´Õ¡Õ¶ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡Õ¹Õ¡ÖƒÕ¨ Õ£Õ¥Ö€Õ¡Õ¦Õ¡Õ¶ÖÕ¾Õ¡Õ® Õ§Ö‰", + "upload_button.label": "Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡", + "upload_error.limit": "Õ†Õ«Õ·Ö„Õ« Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ´Õ¡Õ¶ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡Õ¹Õ¡ÖƒÕ¨ Õ£Õ¥Ö€Õ¡Õ¦Õ¡Õ¶ÖÕ¸Ö‚Õ¡Õ® Õ§Ö‰", "upload_error.poll": "Õ€Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿ Õ¶Õ«Õ·Ö„ Õ¯ÖÕ¥Õ¬ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ¹Õ§Ö‰", "upload_form.audio_description": "Õ†Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ«Ö€ Õ±Õ¡ÕµÕ¶Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¬Õ½Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ ÕÕ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¸Õ¾ Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€", "upload_form.description": "Õ†Õ¯Õ¡Ö€Õ¡Õ£Õ«Ö€Õ Õ¿Õ¥Õ½Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ ÕÕ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€ Õ¸Ö‚Õ¶Õ¥ÖÕ¸Õ²Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€", "upload_form.edit": "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬", - "upload_form.thumbnail": "Change thumbnail", - "upload_form.undo": "Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬", + "upload_form.thumbnail": "Õ“Õ¸ÕÕ¥Õ¬ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯Õ¨", + "upload_form.undo": "Õ…Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬", "upload_form.video_description": "Õ†Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ«Ö€ Õ¿Õ¥Õ½Õ¡Õ¶Õ«Ö‚Õ©Õ¨ Õ¬Õ½Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ Õ¯Õ¡Õ´ Õ¿Õ¥Õ½Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ ÕÕ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¸Õ¾ Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€", "upload_modal.analyzing_picture": "Ô¼Õ¸Ö‚Õ½Õ¡Õ¶Õ¯Õ¡Ö€Õ« վերլուծում…", "upload_modal.apply": "Ô¿Õ«Ö€Õ¡Õ¼Õ¥Õ¬", "upload_modal.choose_image": "Ô¸Õ¶Õ¿Ö€Õ¥Õ¬ Õ¶Õ¯Õ¡Ö€", - "upload_modal.description_placeholder": "Ô²Õ¥Õ¬ Õ¤Õ²ÕµÕ¡Õ¯Õ« Õ±Õ¡Õ ÕªÕ¡Õ´Õ¶ Ö…Ö† Õ¡Õ¦Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶Õ¨ ÖÕºÕ¡Õ°Õ¡Õ¶Õ» Õ¹Õ³Õ·Õ¿Õ¡Õ® Õ¾Õ¶Õ¡Õ½ Õ§Ö€ Õ¥Ö‚ ÖƒÕ¡Õ¼Ö„Ö‰", - "upload_modal.detect_text": "Õ€Õ¡ÕµÕ¿Õ¶Õ¢Õ¥Ö€Õ¥Õ¬ Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Õ¶Õ¯Õ¡Ö€Õ«Ö", + "upload_modal.description_placeholder": "Ô²Õ¥Õ¬ Õ¤Õ²Õ¥Õ¡Õ¯Õ« Õ±Õ¡Õ ÕªÕ¡Õ´Õ¶ Ö…Ö† Õ¡Õ¦Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶Õ¨ ÖÕºÕ¡Õ°Õ¡Õ¶Õ» Õ¹Õ³Õ·Õ¿Õ¡Õ® Õ¾Õ¶Õ¡Õ½ Õ§Ö€ Õ¥Ö‚ ÖƒÕ¡Õ¼Ö„Ö‰", + "upload_modal.detect_text": "Õ…Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬ Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Õ¶Õ¯Õ¡Ö€Õ«Ö", "upload_modal.edit_media": "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡Õ¶", "upload_modal.hint": "ÕÕ¥Õ²Õ´Õ§Ö„ Õ¥Ö‚ Õ¿Õ¥Õ²Õ¡Õ·Õ¡Ö€ÕªÕ§Ö„ Õ¶Õ¡ÕÕ¡Õ¤Õ«Õ¿Õ´Õ¡Õ¶ Õ·Ö€Õ»Õ¡Õ¶Õ¡Õ¯Õ¨Õ Õ¸Ö€ Õ¨Õ¶Õ¿Ö€Õ§Ö„ Õ´Õ¡Õ¶Ö€Õ¡ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¸Ö‚Õ´ Õ´Õ«Õ·Õ¿ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ§Õ¿Õ¨Ö‰", + "upload_modal.preparing_ocr": "Ô³Ö€Õ¡Õ³Õ¡Õ¶Õ¡Õ¹Õ´Õ¡Õ¶ Õ¶Õ¡Õապատրաստում…", "upload_modal.preview_label": "Õ†Õ¡ÕÕ¡Õ¤Õ«Õ¿Õ¸Ö‚Õ´ ({ratio})", "upload_progress.label": "ÕŽÕ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ է…", "video.close": "Õ“Õ¡Õ¯Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", - "video.download": "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨", + "video.download": "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ¶Õ«Õ·Ö„Õ¨", "video.exit_fullscreen": "Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ¬Õ«Õ¡Õ§Õ¯Ö€Õ¡Õ¶ Õ¤Õ«Õ¿Õ¸Ö‚Õ´Õ¨", "video.expand": "Ô¸Õ¶Õ¤Õ¡Ö€Õ±Õ¡Õ¯Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "video.fullscreen": "Ô¼Õ«Õ¡Õ§Õ¯Ö€Õ¡Õ¶", "video.hide": "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨", "video.mute": "Ô¼Õ¼Õ¥ÖÕ¶Õ¥Õ¬ Õ±Õ¡ÕµÕ¶Õ¨", "video.pause": "Ô´Õ¡Õ¤Õ¡Ö€ Õ¿Õ¡Õ¬", - "video.play": "Õ†Õ¾Õ¡Õ£Õ¥Õ¬", + "video.play": "Õ†Õ¸Ö‚Õ¡Õ£Õ¥Õ¬", "video.unmute": "Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¡ÕµÕ¶Õ¨" } diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 91ad76e0394761571bbfebb6775512f40ea2d8d3..24f100b6ab21b30fb91f36a7e32cae480a824480 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Catatan", "account.add_or_remove_from_list": "Tambah atau Hapus dari daftar", "account.badges.bot": "Bot", "account.badges.group": "Grup", "account.block": "Blokir @{name}", "account.block_domain": "Sembunyikan segalanya dari {domain}", "account.blocked": "Terblokir", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Lihat lebih lanjut diprofil asli", "account.cancel_follow_request": "Batalkan permintaan ikuti", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Berhenti memberitahu saya ketika @{name} memposting", "account.domain_blocked": "Domain disembunyikan", "account.edit_profile": "Ubah profil", + "account.enable_notifications": "Beritahu saya saat @{name} memposting", "account.endorse": "Tampilkan di profil", "account.follow": "Ikuti", "account.followers": "Pengikut", "account.followers.empty": "Tidak ada satupun yang mengkuti pengguna ini saat ini.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, other {{counter} Pengikut}}", + "account.following_counter": "{count, plural, other {{counter} Mengikuti}}", "account.follows.empty": "Pengguna ini belum mengikuti siapapun.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", @@ -36,14 +38,14 @@ "account.requested": "Menunggu persetujuan. Klik untuk membatalkan permintaan", "account.share": "Bagikan profil @{name}", "account.show_reblogs": "Tampilkan boost dari @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, other {{counter} Toot}}", "account.unblock": "Hapus blokir @{name}", - "account.unblock_domain": "Tampilkan {domain}", + "account.unblock_domain": "Buka blokir domain {domain}", "account.unendorse": "Jangan tampilkan di profil", "account.unfollow": "Berhenti mengikuti", "account.unmute": "Berhenti membisukan @{name}", "account.unmute_notifications": "Munculkan notifikasi dari @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Klik untuk menambah catatan", "alert.rate_limited.message": "Tolong ulangi setelah {retry_time, time, medium}.", "alert.rate_limited.title": "Batasan tingkat", "alert.unexpected.message": "Terjadi kesalahan yang tidak terduga.", @@ -79,9 +81,9 @@ "column_header.show_settings": "Tampilkan pengaturan", "column_header.unpin": "Lepaskan", "column_subheading.settings": "Pengaturan", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "Hanya lokal", "community.column_settings.media_only": "Hanya media", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "Hanya jarak jauh", "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", "compose_form.direct_message_warning_learn_more": "Pelajari selengkapnya", "compose_form.hashtag_warning": "Toot ini tidak akan ada dalam daftar tagar manapun karena telah di set sebagai tidak terdaftar. Hanya postingan publik yang bisa dicari dengan tagar.", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Ubah japat menjadi pilihan tunggal", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Tandai sebagai media sensitif", - "compose_form.sensitive.marked": "Sumber ini telah ditandai sebagai sumber sensitif.", - "compose_form.sensitive.unmarked": "Sumber ini tidak ditandai sebagai sumber sensitif", + "compose_form.sensitive.hide": "{count, plural, other {Tandai media sebagai sensitif}}", + "compose_form.sensitive.marked": "{count, plural, other {Media ini ditandai sebagai sensitif}}", + "compose_form.sensitive.unmarked": "{count, plural, other {Media ini tidak ditandai sebagai sensitif}}", "compose_form.spoiler.marked": "Teks disembunyikan dibalik peringatan", "compose_form.spoiler.unmarked": "Teks tidak tersembunyi", "compose_form.spoiler_placeholder": "Peringatan konten", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Hasil pencarian", "emoji_button.symbols": "Simbol", "emoji_button.travel": "Tempat Wisata", + "empty_column.account_suspended": "Akun ditangguhkan", "empty_column.account_timeline": "Tidak ada toot di sini!", "empty_column.account_unavailable": "Profil tidak tersedia", "empty_column.blocks": "Anda belum memblokir siapapun.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Anda tidak memiliki notifikasi apapun. Berinteraksi dengan orang lain untuk memulai percakapan.", "empty_column.public": "Tidak ada apapun disini! Tulis sesuatu, atau ikuti pengguna lain dari server lain untuk mengisi ini", "error.unexpected_crash.explanation": "Karena kutu pada kode kami atau isu kompatibilitas peramban, halaman tak dapat ditampilkan dengan benar.", + "error.unexpected_crash.explanation_addons": "Halaman ini tidak dapat ditampilkan dengan benar. Kesalahan ini mungkin disebabkan pengaya peramban atau alat terjemahan otomatis.", "error.unexpected_crash.next_steps": "Coba segarkan halaman. Jika tak membantu, Anda masih bisa memakai Mastodon dengan peramban berbeda atau aplikasi native.", + "error.unexpected_crash.next_steps_addons": "Coba nonaktifkan mereka lalu segarkan halaman. Jika tak membantu, Anda masih bisa memakai Mastodon dengan peramban berbeda atau aplikasi murni.", "errors.unexpected_crash.copy_stacktrace": "Salin stacktrace ke papan klip", "errors.unexpected_crash.report_issue": "Laporkan masalah", "follow_request.authorize": "Izinkan", "follow_request.reject": "Tolak", "follow_requests.unlocked_explanation": "Meskipun akun Anda tidak dikunci, staf {domain} menyarankan Anda untuk meninjau permintaan mengikuti dari akun-akun ini secara manual.", - "generic.saved": "Saved", + "generic.saved": "Disimpan", "getting_started.developers": "Pengembang", "getting_started.directory": "Direktori profil", "getting_started.documentation": "Dokumentasi", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "balas", "keyboard_shortcuts.requests": "buka daftar permintaan ikuti", "keyboard_shortcuts.search": "untuk fokus mencari", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "untuk menampilkan/menyembunyikan bidang CW", "keyboard_shortcuts.start": "buka kolom \"memulai\"", "keyboard_shortcuts.toggle_hidden": "tampilkan/sembunyikan teks di belakang CW", "keyboard_shortcuts.toggle_sensitivity": "tampilkan/sembunyikan media", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "untuk tidak fokus pada area teks/pencarian", "keyboard_shortcuts.up": "untuk memindah ke atas pada daftar", "lightbox.close": "Tutup", + "lightbox.compress": "Kompres kotak tampilan gambar", + "lightbox.expand": "Besarkan kotak tampilan gambar", "lightbox.next": "Selanjutnya", "lightbox.previous": "Sebelumnya", - "lightbox.view_context": "Lihat konteks", "lists.account.add": "Tambah ke daftar", "lists.account.remove": "Hapus dari daftar", "lists.delete": "Hapus daftar", @@ -260,6 +266,10 @@ "lists.edit.submit": "Ubah judul", "lists.new.create": "Tambah daftar", "lists.new.title_placeholder": "Judul daftar baru", + "lists.replies_policy.followed": "Siapapun pengguna yang diikuti", + "lists.replies_policy.list": "Anggota di daftar tersebut", + "lists.replies_policy.none": "Tidak ada satu pun", + "lists.replies_policy.title": "Tampilkan balasan ke:", "lists.search": "Cari di antara orang yang Anda ikuti", "lists.subheading": "Daftar Anda", "load_pending": "{count, plural, other {# item baru}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Tampil/Sembunyikan", "missing_indicator.label": "Tidak ditemukan", "missing_indicator.sublabel": "Sumber daya tak bisa ditemukan", + "mute_modal.duration": "Durasi", "mute_modal.hide_notifications": "Sembunyikan notifikasi dari pengguna ini?", + "mute_modal.indefinite": "Tak terbatas", "navigation_bar.apps": "Aplikasi mobile", "navigation_bar.blocks": "Pengguna diblokir", "navigation_bar.bookmarks": "Markah", @@ -298,6 +310,7 @@ "notification.own_poll": "Japat Anda telah berakhir", "notification.poll": "Japat yang Anda ikuti telah berakhir", "notification.reblog": "{name} mem-boost status anda", + "notification.status": "{name} baru saja memposting", "notifications.clear": "Hapus notifikasi", "notifications.clear_confirmation": "Apa anda yakin hendak menghapus semua notifikasi anda?", "notifications.column_settings.alert": "Notifikasi desktop", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boost:", "notifications.column_settings.show": "Tampilkan dalam kolom", "notifications.column_settings.sound": "Mainkan suara", + "notifications.column_settings.status": "Toot baru:", "notifications.filter.all": "Semua", "notifications.filter.boosts": "Boost", "notifications.filter.favourites": "Favorit", "notifications.filter.follows": "Diikuti", "notifications.filter.mentions": "Sebutan", "notifications.filter.polls": "Hasil japat", + "notifications.filter.statuses": "Pembaruan dari orang yang Anda ikuti", + "notifications.grant_permission": "Setujui izin.", "notifications.group": "{count} notifikasi", + "notifications.mark_as_read": "Tandai setiap notifikasi sebagai sudah dibaca", + "notifications.permission_denied": "Tidak dapat mengaktifkan notifikasi desktop karena izin ditolak.", + "notifications.permission_denied_alert": "Notifikasi desktop tidak dapat diaktifkan karena izin peramban telah ditolak sebelumnya", + "notifications.permission_required": "Notifikasi desktop tidak tersedia karena izin yang dibutuhkan belum disetujui.", + "notifications_permission_banner.enable": "Aktifkan notifikasi desktop", + "notifications_permission_banner.how_to_control": "Untuk menerima notifikasi saat Mastodon terbuka, aktifkan notifikasi desktop. Anda dapat mengendalikan tipe interaksi mana yang ditampilkan notifikasi desktop melalui tombol {icon} di atas saat sudah aktif.", + "notifications_permission_banner.title": "Jangan lewatkan apapun", + "picture_in_picture.restore": "Taruh kembali", "poll.closed": "Ditutup", "poll.refresh": "Segarkan", "poll.total_people": "{count, plural, other {# orang}}", @@ -343,7 +367,7 @@ "relative_time.days": "{number}h", "relative_time.hours": "{number}j", "relative_time.just_now": "sekarang", - "relative_time.minutes": "{number}b", + "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}d", "relative_time.today": "hari ini", "reply_indicator.cancel": "Batal", @@ -419,16 +443,16 @@ "time_remaining.minutes": "{number, plural, other {# menit}} tersisa", "time_remaining.moments": "Momen tersisa", "time_remaining.seconds": "{number, plural, other {# detik}} tersisa", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "{resource} dari server lain tidak ditampilkan.", + "timeline_hint.resources.followers": "Pengikut", + "timeline_hint.resources.follows": "Ikuti", + "timeline_hint.resources.statuses": "Toot lama", + "trends.counter_by_accounts": "{count, plural, other {{counter} orang}} berbicara", "trends.trending_now": "Sedang tren sekarang", "ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count}M", + "units.short.million": "{count}Jt", + "units.short.thousand": "{count}Rb", "upload_area.title": "Seret & lepaskan untuk mengunggah", "upload_button.label": "Tambahkan media", "upload_error.limit": "Batas unggah berkas terlampaui.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Penjelasan untuk orang dengan gangguan pendengaran", "upload_form.description": "Deskripsikan untuk mereka yang tidak bisa melihat dengan jelas", "upload_form.edit": "Sunting", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Ubah gambar kecil", "upload_form.undo": "Undo", "upload_form.video_description": "Penjelasan untuk orang dengan gangguan pendengaran atau penglihatan", "upload_modal.analyzing_picture": "Analisis gambar…", "upload_modal.apply": "Terapkan", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Pilih gambar", "upload_modal.description_placeholder": "Muharjo seorang xenofobia universal yang takut pada warga jazirah, contohnya Qatar", "upload_modal.detect_text": "Deteksi teks pada gambar", "upload_modal.edit_media": "Sunting media", "upload_modal.hint": "Klik atau seret lingkaran pada pratinjau untuk memilih titik fokus yang akan ditampilkan pada semua gambar kecil.", + "upload_modal.preparing_ocr": "Menyiapkan OCR…", "upload_modal.preview_label": "Pratinjau ({ratio})", "upload_progress.label": "Mengunggah...", "video.close": "Tutup video", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index e79bee21da7e5d50e4281b7f54621f9f0976131c..998799b9faa1fb8a91e39143f063cccf7c1d9472 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Modifikar profilo", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Sequar", "account.followers": "Sequanti", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Siflar", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Averto di kontenajo", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Tu havas ankore nula savigo. Komunikez kun altri por debutar la konverso.", "empty_column.public": "Esas nulo hike! Skribez ulo publike, o manuale sequez uzeri de altra instaluri por plenigar ol.", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Yurizar", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Klozar", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Chanjar videbleso", "missing_indicator.label": "Ne trovita", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blokusita uzeri", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} repetis tua mesajo", + "notification.status": "{name} just posted", "notifications.clear": "Efacar savigi", "notifications.clear_confirmation": "Ka tu esas certa, ke tu volas efacar omna tua savigi?", "notifications.column_settings.alert": "Surtabla savigi", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Repeti:", "notifications.column_settings.show": "Montrar en kolumno", "notifications.column_settings.sound": "Plear sono", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Repetar", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} repetita", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Kargante...", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 72d8fefaf611980101691b057a1edf2c27b45747..d90156835f9683eb7045076cddb88945b9dc68ba 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Skoða nánari upplýsingar á notandasniðinu", "account.cancel_follow_request": "Hætta við beiðni um að fylgjast með", "account.direct": "Bein skilaboð til @{name}", + "account.disable_notifications": "Hætta að láta mig vita þegar @{name} sendir inn", "account.domain_blocked": "Lén falið", "account.edit_profile": "Breyta notandasniði", + "account.enable_notifications": "Láta mig vita þegar @{name} sendir inn", "account.endorse": "Birta á notandasniði", "account.follow": "Fylgjast með", "account.followers": "Fylgjendur", "account.followers.empty": "Ennþá fylgist enginn með þessum notanda.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} fylgjandi} other {{counter} fylgjendur}}", + "account.following_counter": "{count, plural, one {{counter} fylgist með} other {{counter} fylgjast með}}", "account.follows.empty": "Þessi notandi fylgist ennþá ekki með neinum.", "account.follows_you": "Fylgir þér", "account.hide_reblogs": "Fela endurbirtingar fyrir @{name}", @@ -36,7 +38,7 @@ "account.requested": "BÃður eftir samþykki. Smelltu til að hætta við beiðni um að fylgjast með", "account.share": "Deila notandasniði fyrir @{name}", "account.show_reblogs": "Sýna endurbirtingar frá @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} tÃst} other {{counter} tÃst}}", "account.unblock": "Aflétta útilokun af @{name}", "account.unblock_domain": "Hætta að fela {domain}", "account.unendorse": "Ekki birta á notandasniði", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Leitarniðurstöður", "emoji_button.symbols": "Tákn", "emoji_button.travel": "Ferðalög og staðir", + "empty_column.account_suspended": "Notandaaðgangur à bið", "empty_column.account_timeline": "Engin tÃst hér!", "empty_column.account_unavailable": "Notandasnið ekki tiltækt", "empty_column.blocks": "Þú hefur ekki ennþá útilokað neina notendur.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Þú ert ekki ennþá með neinar tilkynningar. Vertu à samskiptum við aðra til að umræður fari af stað.", "empty_column.public": "Það er ekkert hér! Skrifaðu eitthvað opinberlega, eða fylgstu með notendum á öðrum netþjónum til að fylla upp à þetta", "error.unexpected_crash.explanation": "Vegna villu à kóðanum okkar eða samhæfnivandamála à vafra er ekki hægt að birta þessa sÃðu svo vel sé.", + "error.unexpected_crash.explanation_addons": "Ekki er hægt að birta þessa sÃðu rétt. Þetta er lÃklega af völdum forritsviðbótar à vafranum eða sjálfvirkra þýðainaverkfæra.", "error.unexpected_crash.next_steps": "Prófaðu að endurlesa sÃðuna. Ef það hjálpar ekki til, má samt vera að þú getir notað Mastodon à gegnum annan vafra eða forrit.", + "error.unexpected_crash.next_steps_addons": "Prófaðu að gera þau óvirk og svo endurlesa sÃðuna. Ef það hjálpar ekki til, má samt vera að þú getir notað Mastodon à gegnum annan vafra eða forrit.", "errors.unexpected_crash.copy_stacktrace": "Afrita rakningarupplýsingar (stacktrace) á klippispjald", "errors.unexpected_crash.report_issue": "Tilkynna vandamál", "follow_request.authorize": "Heimila", "follow_request.reject": "Hafna", "follow_requests.unlocked_explanation": "Jafnvel þótt aðgangurinn þinn sé ekki læstur, hafa umsjónarmenn {domain} Ãmyndað sér að þú gætir viljað yfirfara handvirkt fylgjendabeiðnir frá þessum notendum.", - "generic.saved": "Saved", + "generic.saved": "Vistað", "getting_started.developers": "Forritarar", "getting_started.directory": "Notandasniðamappa", "getting_started.documentation": "Hjálparskjöl", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "að taka virkni úr textainnsetningarreit eða leit", "keyboard_shortcuts.up": "að fara ofar à listanum", "lightbox.close": "Loka", + "lightbox.compress": "Þjappa myndskoðunarreit", + "lightbox.expand": "Fletta út myndskoðunarreit", "lightbox.next": "Næsta", "lightbox.previous": "Fyrra", - "lightbox.view_context": "Skoða samhengi", "lists.account.add": "Bæta á lista", "lists.account.remove": "Fjarlægja af lista", "lists.delete": "Eyða lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Breyta titli", "lists.new.create": "Bæta við lista", "lists.new.title_placeholder": "Titill á nýjum lista", + "lists.replies_policy.followed": "Allra notenda sem fylgst er með", + "lists.replies_policy.list": "Meðlima listans", + "lists.replies_policy.none": "Engra", + "lists.replies_policy.title": "Sýna svör til:", "lists.search": "Leita meðal þeirra sem þú fylgist með", "lists.subheading": "Listarnir þÃnir", "load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "VÃxla sýnileika", "missing_indicator.label": "Fannst ekki", "missing_indicator.sublabel": "Tilfangið fannst ekki", + "mute_modal.duration": "Lengd", "mute_modal.hide_notifications": "Fela tilkynningar frá þessum notanda?", + "mute_modal.indefinite": "Óendanlegt", "navigation_bar.apps": "FarsÃmaforrit", "navigation_bar.blocks": "Útilokaðir notendur", "navigation_bar.bookmarks": "Bókamerki", @@ -298,6 +310,7 @@ "notification.own_poll": "Könnuninni þinni er lokið", "notification.poll": "Könnun sem þú tókst þátt à er lokið", "notification.reblog": "{name} endurbirti stöðufærsluna þÃna", + "notification.status": "{name} sendi inn rétt à þessu", "notifications.clear": "Hreinsa tilkynningar", "notifications.clear_confirmation": "Ertu viss um að þú viljir endanlega eyða öllum tilkynningunum þÃnum?", "notifications.column_settings.alert": "Tilkynningar á skjáborði", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Endurbirtingar:", "notifications.column_settings.show": "Sýna à dálki", "notifications.column_settings.sound": "Spila hljóð", + "notifications.column_settings.status": "Ný tÃst:", "notifications.filter.all": "Allt", "notifications.filter.boosts": "Endurbirtingar", "notifications.filter.favourites": "Eftirlæti", "notifications.filter.follows": "Fylgist með", "notifications.filter.mentions": "TilvÃsanir", "notifications.filter.polls": "Niðurstöður könnunar", + "notifications.filter.statuses": "Uppfærslur frá fólki sem þú fylgist með", + "notifications.grant_permission": "Veita heimild.", "notifications.group": "{count} tilkynningar", + "notifications.mark_as_read": "Merkja allar tilkynningar sem lesnar", + "notifications.permission_denied": "Tilkynningar á skjáborði eru ekki aðgengilegar megna áður hafnaðra beiðna fyrir vafra", + "notifications.permission_denied_alert": "Ekki var hægt að virkja tilkynningar á skjáborði, þar sem heimildum fyrir vafra var áður hafnað", + "notifications.permission_required": "Tilkynningar á skjáborði eru ekki aðgengilegar þar sem nauðsynlegar heimildir hafa ekki verið veittar.", + "notifications_permission_banner.enable": "Virkja tilkynningar á skjáborði", + "notifications_permission_banner.how_to_control": "Til að taka á móti tilkynningum þegar Mastodon er ekki opið, skaltu virkja tilkynningar á skjáborði. Þegar þær eru orðnar virkar geturðu stýrt nákvæmlega hverskonar atvik framleiða tilkynningar með þvà að nota {icon}-hnappinn hér fyrir ofan.", + "notifications_permission_banner.title": "Aldrei missa af neinu", + "picture_in_picture.restore": "Setja til baka", "poll.closed": "Lokað", "poll.refresh": "Endurlesa", "poll.total_people": "{count, plural, one {# aðili} other {# aðilar}}", @@ -423,29 +447,30 @@ "timeline_hint.resources.followers": "Fylgjendur", "timeline_hint.resources.follows": "Fylgist með", "timeline_hint.resources.statuses": "Eldri tÃst", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, one {{counter} aðili} other {{counter} aðilar}} tala", "trends.trending_now": "à umræðunni núna", "ui.beforeunload": "Drögin tapast ef þú ferð út úr Mastodon.", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Dragðu-og-slepptu hér til að senda inn", - "upload_button.label": "Bæta við ({formats}) myndskrá", + "upload_button.label": "Bæta við myndum, myndskeiði eða hljóðskrá", "upload_error.limit": "Fór yfir takmörk á innsendingum skráa.", "upload_error.poll": "Innsending skráa er ekki leyfð à könnunum.", "upload_form.audio_description": "Lýstu þessu fyrir heyrnarskerta", "upload_form.description": "Lýstu þessu fyrir sjónskerta", "upload_form.edit": "Breyta", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Skipta um smámynd", "upload_form.undo": "Eyða", "upload_form.video_description": "Lýstu þessu fyrir fólk sem heyrir illa eða er með skerta sjón", "upload_modal.analyzing_picture": "Greini mynd…", "upload_modal.apply": "Virkja", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Veldu mynd", "upload_modal.description_placeholder": "Öllum dýrunum à skóginum þætti bezt að vera vinir", "upload_modal.detect_text": "Skynja texta úr mynd", "upload_modal.edit_media": "Breyta myndskrá", "upload_modal.hint": "Smelltu eða dragðu til hringinn á forskoðuninni til að velja miðpunktinn sem verður alltaf sýnilegastur á öllum smámyndum.", + "upload_modal.preparing_ocr": "Undirbý OCR-ljóslestur…", "upload_modal.preview_label": "Forskoðun ({ratio})", "upload_progress.label": "Er að senda inn...", "video.close": "Loka myndskeiði", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 077f61e4802f862ec8c9a6b55c214fc59ce97894..b63b231aeac842ac49b79ab48d0e10db4c5ce9e8 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -1,16 +1,18 @@ { - "account.account_note_header": "La tua nota per @{name}", - "account.add_or_remove_from_list": "Aggiungi o Rimuovi dagli elenchi", + "account.account_note_header": "Le tue note sull'utente", + "account.add_or_remove_from_list": "Aggiungi o togli dalle liste", "account.badges.bot": "Bot", "account.badges.group": "Gruppo", "account.block": "Blocca @{name}", "account.block_domain": "Blocca dominio {domain}", - "account.blocked": "Bloccato", - "account.browse_more_on_origin_server": "Naviga di più sul profilo originale", + "account.blocked": "Bloccat*", + "account.browse_more_on_origin_server": "Sfoglia ulteriormente sul profilo originale", "account.cancel_follow_request": "Annulla richiesta di seguirti", "account.direct": "Messaggio diretto a @{name}", + "account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post", "account.domain_blocked": "Dominio bloccato", "account.edit_profile": "Modifica profilo", + "account.enable_notifications": "Avvisami quando @{name} pubblica un post", "account.endorse": "Mostra sul profilo", "account.follow": "Segui", "account.followers": "Seguaci", @@ -19,7 +21,7 @@ "account.following_counter": "{count, plural, other {{counter} Seguiti}}", "account.follows.empty": "Questo utente non segue ancora nessuno.", "account.follows_you": "Ti segue", - "account.hide_reblogs": "Nascondi incrementi da @{name}", + "account.hide_reblogs": "Nascondi condivisioni da @{name}", "account.last_status": "Ultima attività ", "account.link_verified_on": "La proprietà di questo link è stata controllata il {date}", "account.locked_info": "Lo stato di privacy del profilo è impostato a bloccato. Il proprietario revisiona manualmente chi lo può seguire.", @@ -28,14 +30,14 @@ "account.moved_to": "{name} si è trasferito su:", "account.mute": "Silenzia @{name}", "account.mute_notifications": "Silenzia notifiche da @{name}", - "account.muted": "Silenziato", + "account.muted": "Silenziat*", "account.never_active": "Mai", "account.posts": "Toot", "account.posts_with_replies": "Toot e risposte", "account.report": "Segnala @{name}", "account.requested": "In attesa di approvazione. Clicca per annullare la richiesta di seguire", "account.share": "Condividi il profilo di @{name}", - "account.show_reblogs": "Mostra incrementi da @{name}", + "account.show_reblogs": "Mostra condivisioni da @{name}", "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toot}}", "account.unblock": "Sblocca @{name}", "account.unblock_domain": "Sblocca il dominio {domain}", @@ -43,9 +45,9 @@ "account.unfollow": "Smetti di seguire", "account.unmute": "Non silenziare @{name}", "account.unmute_notifications": "Non silenziare le notifiche da @{name}", - "account_note.placeholder": "Nessun commento fornito", + "account_note.placeholder": "Clicca per aggiungere una nota", "alert.rate_limited.message": "Sei pregato di riprovare tra {retry_time, time, medium}.", - "alert.rate_limited.title": "Intervallo limitato", + "alert.rate_limited.title": "Limitazione per eccesso di richieste", "alert.unexpected.message": "Si è verificato un errore inatteso.", "alert.unexpected.title": "Oops!", "announcement.announcement": "Annuncio", @@ -59,9 +61,9 @@ "bundle_modal_error.retry": "Riprova", "column.blocks": "Utenti bloccati", "column.bookmarks": "Segnalibri", - "column.community": "Fuso orario locale", + "column.community": "Timeline locale", "column.direct": "Messaggi diretti", - "column.directory": "Naviga profili", + "column.directory": "Sfoglia profili", "column.domain_blocks": "Domini bloccati", "column.favourites": "Preferiti", "column.follow_requests": "Richieste di seguirti", @@ -70,7 +72,7 @@ "column.mutes": "Utenti silenziati", "column.notifications": "Notifiche", "column.pins": "Toot in evidenza", - "column.public": "Fuso orario federato", + "column.public": "Timeline federata", "column_back_button.label": "Indietro", "column_header.hide_settings": "Nascondi impostazioni", "column_header.moveLeft_settings": "Sposta colonna a sinistra", @@ -111,13 +113,13 @@ "confirmations.delete_list.confirm": "Cancella", "confirmations.delete_list.message": "Sei sicuro di voler cancellare definitivamente questa lista?", "confirmations.domain_block.confirm": "Blocca l'intero dominio", - "confirmations.domain_block.message": "Sei davvero, davvero sicuro di voler bloccare l'intero {domain}? In molti casi pochi blocchi di destinazione o muti sono sufficienti e preferibili. Non vedrai il contenuto da quel dominio in alcuna linea temporale pubblica o nelle tue notifiche. i tuoi seguaci saranno rimossi da quel dominio.", + "confirmations.domain_block.message": "Sei davvero, davvero sicuro di voler bloccare l'intero {domain}? In molti casi pochi blocchi di destinazione o muti sono sufficienti e preferibili. Non vedrai il contenuto da quel dominio in alcuna timeline pubblica o nelle tue notifiche. i tuoi seguaci saranno rimossi da quel dominio.", "confirmations.logout.confirm": "Disconnettiti", "confirmations.logout.message": "Sei sicuro di volerti disconnettere?", "confirmations.mute.confirm": "Silenzia", "confirmations.mute.explanation": "Questo nasconderà i post da loro ed i post che li menzionano, ma consentirà ancora loro di vedere i tuoi post e di seguirti.", "confirmations.mute.message": "Sei sicuro di voler silenziare {name}?", - "confirmations.redraft.confirm": "Cancella e rivali", + "confirmations.redraft.confirm": "Cancella e riscrivi", "confirmations.redraft.message": "Sei sicuro di voler eliminare questo toot e riscriverlo? I preferiti e gli incrementi saranno persi e le risposte al post originale saranno perse.", "confirmations.reply.confirm": "Rispondi", "confirmations.reply.message": "Rispondere ora sovrascriverà il messaggio che stai correntemente componendo. Sei sicuro di voler procedere?", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Risultati della ricerca", "emoji_button.symbols": "Simboli", "emoji_button.travel": "Viaggi & Luoghi", + "empty_column.account_suspended": "Account sospeso", "empty_column.account_timeline": "Nessun toot qui!", "empty_column.account_unavailable": "Profilo non disponibile", "empty_column.blocks": "Non hai ancora bloccato alcun utente.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.", "empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio", "error.unexpected_crash.explanation": "A causa di un bug nel nostro codice o di un problema di compatibilità del browser, questa pagina non può essere visualizzata correttamente.", + "error.unexpected_crash.explanation_addons": "Questa pagina non può essere visualizzata correttamente. Questo errore è probabilmente causato da un componente aggiuntivo del browser o da strumenti di traduzione automatica.", "error.unexpected_crash.next_steps": "Prova ad aggiornare la pagina. Se non funziona, potresti ancora essere in grado di utilizzare Mastodon attraverso un browser diverso o un'app nativa.", + "error.unexpected_crash.next_steps_addons": "Prova a disabilitarli e ad aggiornare la pagina. Se questo non funziona, potresti ancora essere in grado di utilizzare Mastodon attraverso un browser o un'app diversi.", "errors.unexpected_crash.copy_stacktrace": "Copia stacktrace negli appunti", "errors.unexpected_crash.report_issue": "Segnala il problema", "follow_request.authorize": "Autorizza", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "per uscire dall'area di composizione o dalla ricerca", "keyboard_shortcuts.up": "per spostarsi in alto nella lista", "lightbox.close": "Chiudi", + "lightbox.compress": "Comprimi casella di visualizzazione immagine", + "lightbox.expand": "Espandi casella di visualizzazione immagine", "lightbox.next": "Successivo", "lightbox.previous": "Precedente", - "lightbox.view_context": "Mostra contesto", "lists.account.add": "Aggiungi alla lista", "lists.account.remove": "Togli dalla lista", "lists.delete": "Elimina lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Cambia titolo", "lists.new.create": "Aggiungi lista", "lists.new.title_placeholder": "Titolo della nuova lista", + "lists.replies_policy.followed": "Qualsiasi utente seguito", + "lists.replies_policy.list": "Iscritti alla lista", + "lists.replies_policy.none": "Nessuno", + "lists.replies_policy.title": "Mostra risposte a:", "lists.search": "Cerca tra le persone che segui", "lists.subheading": "Le tue liste", "load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Imposta visibilità ", "missing_indicator.label": "Non trovato", "missing_indicator.sublabel": "Risorsa non trovata", + "mute_modal.duration": "Durata", "mute_modal.hide_notifications": "Nascondere le notifiche da quest'utente?", + "mute_modal.indefinite": "Per sempre", "navigation_bar.apps": "App per dispositivi mobili", "navigation_bar.blocks": "Utenti bloccati", "navigation_bar.bookmarks": "Segnalibri", @@ -298,6 +310,7 @@ "notification.own_poll": "Il tuo sondaggio è terminato", "notification.poll": "Un sondaggio in cui hai votato è terminato", "notification.reblog": "{name} ha condiviso il tuo post", + "notification.status": "{name} ha appena pubblicato un post", "notifications.clear": "Cancella notifiche", "notifications.clear_confirmation": "Vuoi davvero cancellare tutte le notifiche?", "notifications.column_settings.alert": "Notifiche desktop", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Post condivisi:", "notifications.column_settings.show": "Mostra in colonna", "notifications.column_settings.sound": "Riproduci suono", + "notifications.column_settings.status": "Nuovi toot:", "notifications.filter.all": "Tutti", "notifications.filter.boosts": "Condivisioni", "notifications.filter.favourites": "Apprezzati", "notifications.filter.follows": "Seguaci", "notifications.filter.mentions": "Menzioni", "notifications.filter.polls": "Risultati del sondaggio", + "notifications.filter.statuses": "Aggiornamenti dalle persone che segui", + "notifications.grant_permission": "Dai il permesso.", "notifications.group": "{count} notifiche", + "notifications.mark_as_read": "Segna tutte le notifiche come lette", + "notifications.permission_denied": "Impossibile abilitare le notifiche sul desktop perché il permesso è stato negato.", + "notifications.permission_denied_alert": "Le notifiche sul desktop non possono essere abilitate, poiché il permesso nel browser è stato negato in precedenza", + "notifications.permission_required": "Le notifiche desktop non sono disponibili perché l'autorizzazione richiesta non è stata concessa.", + "notifications_permission_banner.enable": "Abilita le notifiche sul desktop", + "notifications_permission_banner.how_to_control": "Per ricevere notifiche quando Mastodon non è aperto, abilita le notifiche desktop. Puoi controllare con precisione quali tipi di interazioni generano notifiche desktop tramite il pulsante {icon} qui sopra, dopo averle abilitate.", + "notifications_permission_banner.title": "Non perderti mai nulla", + "picture_in_picture.restore": "Riportalo indietro", "poll.closed": "Chiuso", "poll.refresh": "Aggiorna", "poll.total_people": "{count, plural, one {# persona} other {# persone}}", @@ -426,7 +450,7 @@ "trends.counter_by_accounts": "{count, plural, one {{counter} persona} other {{counter} persone}} ne parla·no", "trends.trending_now": "Di tendenza ora", "ui.beforeunload": "La bozza andrà persa se esci da Mastodon.", - "units.short.billion": "{count}B", + "units.short.billion": "{count}G", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Trascina per caricare", @@ -446,8 +470,9 @@ "upload_modal.detect_text": "Rileva testo dall'immagine", "upload_modal.edit_media": "Modifica media", "upload_modal.hint": "Clicca o trascina il cerchio sull'anteprima per scegliere il punto focale che sarà sempre visualizzato su tutte le miniature.", + "upload_modal.preparing_ocr": "Preparazione OCR…", "upload_modal.preview_label": "Anteprima ({ratio})", - "upload_progress.label": "Sto caricando...", + "upload_progress.label": "Invio in corso...", "video.close": "Chiudi video", "video.download": "Scarica file", "video.exit_fullscreen": "Esci da modalità a schermo intero", @@ -456,6 +481,6 @@ "video.hide": "Nascondi video", "video.mute": "Silenzia suono", "video.pause": "Pausa", - "video.play": "Avvia", + "video.play": "Riproduci", "video.unmute": "Riattiva suono" } diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 7c0ac99d13d478d818fb4c943bfacd5c1f8a07c3..012f88a6836e102dbd74c629e598b2c6b79c9417 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "リモートã§è¡¨ç¤º", "account.cancel_follow_request": "フォãƒãƒ¼ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å–り消ã™", "account.direct": "@{name}ã•ã‚“ã«ãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸", + "account.disable_notifications": "@{name} ã®æŠ•ç¨¿æ™‚ã®é€šçŸ¥ã‚’åœæ¢", "account.domain_blocked": "ドメインブãƒãƒƒã‚¯ä¸", "account.edit_profile": "プãƒãƒ•ィール編集", + "account.enable_notifications": "@{name} ã®æŠ•ç¨¿æ™‚ã«é€šçŸ¥", "account.endorse": "プãƒãƒ•ィールã§ç´¹ä»‹ã™ã‚‹", "account.follow": "フォãƒãƒ¼", "account.followers": "フォãƒãƒ¯ãƒ¼", @@ -36,7 +38,7 @@ "account.requested": "フォãƒãƒ¼æ‰¿èªå¾…ã¡ã§ã™ã€‚クリックã—ã¦ã‚ャンセル", "account.share": "@{name}ã•ã‚“ã®ãƒ—ãƒãƒ•ィールを共有ã™ã‚‹", "account.show_reblogs": "@{name}ã•ã‚“ã‹ã‚‰ã®ãƒ–ーストを表示", - "account.statuses_counter": "{counter} トゥート", + "account.statuses_counter": "{counter} 投稿", "account.unblock": "@{name}ã•ã‚“ã®ãƒ–ãƒãƒƒã‚¯ã‚’解除", "account.unblock_domain": "{domain}ã®ãƒ–ãƒãƒƒã‚¯ã‚’解除", "account.unendorse": "プãƒãƒ•ィールã‹ã‚‰å¤–ã™", @@ -99,8 +101,8 @@ "compose_form.sensitive.hide": "メディアを閲覧注æ„ã«ã™ã‚‹", "compose_form.sensitive.marked": "メディアã«é–²è¦§æ³¨æ„ãŒè¨å®šã•れã¦ã„ã¾ã™", "compose_form.sensitive.unmarked": "メディアã«é–²è¦§æ³¨æ„ãŒè¨å®šã•れã¦ã„ã¾ã›ã‚“", - "compose_form.spoiler.marked": "閲覧注æ„ãŒè¨å®šã•れã¦ã„ã¾ã™", - "compose_form.spoiler.unmarked": "閲覧注æ„ãŒè¨å®šã•れã¦ã„ã¾ã›ã‚“", + "compose_form.spoiler.marked": "本文ã¯è¦å‘Šã®å¾Œã‚ã«éš ã•れã¾ã™", + "compose_form.spoiler.unmarked": "本文ã¯éš ã•れã¦ã„ã¾ã›ã‚“", "compose_form.spoiler_placeholder": "ã“ã“ã«è¦å‘Šã‚’書ã„ã¦ãã ã•ã„", "confirmation_modal.cancel": "ã‚ャンセル", "confirmations.block.block_and_report": "ブãƒãƒƒã‚¯ã—é€šå ±", @@ -147,6 +149,7 @@ "emoji_button.search_results": "æ¤œç´¢çµæžœ", "emoji_button.symbols": "記å·", "emoji_button.travel": "旅行ã¨å ´æ‰€", + "empty_column.account_suspended": "アカウントã¯åœæ¢ã•れã¦ã„ã¾ã™", "empty_column.account_timeline": "トゥートãŒã‚りã¾ã›ã‚“ï¼", "empty_column.account_unavailable": "プãƒãƒ•ィールã¯åˆ©ç”¨ã§ãã¾ã›ã‚“", "empty_column.blocks": "ã¾ã 誰もブãƒãƒƒã‚¯ã—ã¦ã„ã¾ã›ã‚“。", @@ -166,7 +169,9 @@ "empty_column.notifications": "ã¾ã 通知ãŒã‚りã¾ã›ã‚“。他ã®äººã¨ãµã‚Œåˆã£ã¦ä¼šè©±ã‚’å§‹ã‚ã¾ã—ょã†ã€‚", "empty_column.public": "ã“ã“ã«ã¯ã¾ã 何もã‚りã¾ã›ã‚“ï¼ å…¬é–‹ã§ä½•ã‹ã‚’投稿ã—ãŸã‚Šã€ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’フォãƒãƒ¼ã—ãŸã‚Šã—ã¦ã„ã£ã±ã„ã«ã—ã¾ã—ょã†", "error.unexpected_crash.explanation": "ä¸å…·åˆã‹ãƒ–ラウザã®äº’æ›æ€§å•題ã®ãŸã‚ã€ã“ã®ãƒšãƒ¼ã‚¸ã‚’æ£ã—ã表示ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚", + "error.unexpected_crash.explanation_addons": "ã“ã®ãƒšãƒ¼ã‚¸ã¯æ£ã—ã表示ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚¨ãƒ©ãƒ¼ã¯ãƒ–ラウザã®ã‚¢ãƒ‰ã‚ªãƒ³ã‚„自動翻訳ツールã«ã‚ˆã£ã¦å¼•ãèµ·ã“ã•れるã“ã¨ãŒã‚りã¾ã™ã€‚", "error.unexpected_crash.next_steps": "ページã®å†èªã¿è¾¼ã¿ã‚’ãŠè©¦ã—ãã ã•ã„。ãれã§ã‚‚解決ã—ãªã„å ´åˆã€åˆ¥ã®ãƒ–ラウザã‹ã‚¢ãƒ—リを使ãˆã°ä½¿ç”¨ã§ãã‚‹ã“ã¨ãŒã‚りã¾ã™ã€‚", + "error.unexpected_crash.next_steps_addons": "ãれらを無効化ã—ã¦ã‹ã‚‰ãƒªãƒãƒ¼ãƒ‰ã‚’ãŠè©¦ã—ãã ã•ã„。ãれã§ã‚‚解決ã—ãªã„å ´åˆã€ä»–ã®ãƒ–ラウザやアプリ㧠Mastodon ã‚’ãŠè©¦ã—ãã ã•ã„。", "errors.unexpected_crash.copy_stacktrace": "スタックトレースをクリップボードã«ã‚³ãƒ”ー", "errors.unexpected_crash.report_issue": "å•é¡Œã‚’å ±å‘Š", "follow_request.authorize": "許å¯", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "トゥート入力欄・検索欄ã‹ã‚‰é›¢ã‚Œã‚‹", "keyboard_shortcuts.up": "カラム内一ã¤ä¸Šã«ç§»å‹•", "lightbox.close": "é–‰ã˜ã‚‹", + "lightbox.compress": "ç”»åƒãƒ“ューボックスを閉ã˜ã‚‹", + "lightbox.expand": "ç”»åƒãƒ“ューボックスを開ã", "lightbox.next": "次", "lightbox.previous": "å‰", - "lightbox.view_context": "トゥートを表示", "lists.account.add": "リストã«è¿½åŠ ", "lists.account.remove": "リストã‹ã‚‰å¤–ã™", "lists.delete": "リストを削除", @@ -260,6 +266,10 @@ "lists.edit.submit": "タイトルを変更", "lists.new.create": "リストを作æˆ", "lists.new.title_placeholder": "æ–°è¦ãƒªã‚¹ãƒˆå", + "lists.replies_policy.followed": "フォãƒãƒ¼ä¸ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å…¨å“¡", + "lists.replies_policy.list": "リストã®ãƒ¡ãƒ³ãƒãƒ¼", + "lists.replies_policy.none": "表示ã—ãªã„", + "lists.replies_policy.title": "リプライを表示:", "lists.search": "フォãƒãƒ¼ã—ã¦ã„る人ã®ä¸ã‹ã‚‰æ¤œç´¢", "lists.subheading": "ã‚ãªãŸã®ãƒªã‚¹ãƒˆ", "load_pending": "{count} ä»¶ã®æ–°ç€", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’éš ã™", "missing_indicator.label": "見ã¤ã‹ã‚Šã¾ã›ã‚“", "missing_indicator.sublabel": "見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ", + "mute_modal.duration": "ミュートã™ã‚‹æœŸé–“", "mute_modal.hide_notifications": "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰ã®é€šçŸ¥ã‚’éš ã—ã¾ã™ã‹ï¼Ÿ", + "mute_modal.indefinite": "無期é™", "navigation_bar.apps": "アプリ", "navigation_bar.blocks": "ブãƒãƒƒã‚¯ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼", "navigation_bar.bookmarks": "ブックマーク", @@ -298,6 +310,7 @@ "notification.own_poll": "アンケートãŒçµ‚了ã—ã¾ã—ãŸ", "notification.poll": "アンケートãŒçµ‚了ã—ã¾ã—ãŸ", "notification.reblog": "{name}ã•ã‚“ãŒã‚ãªãŸã®ãƒˆã‚¥ãƒ¼ãƒˆã‚’ブーストã—ã¾ã—ãŸ", + "notification.status": "{name}ã•ã‚“ãŒãƒˆã‚¥ãƒ¼ãƒˆã—ã¾ã—ãŸ", "notifications.clear": "通知を消去", "notifications.clear_confirmation": "本当ã«é€šçŸ¥ã‚’消去ã—ã¾ã™ã‹ï¼Ÿ", "notifications.column_settings.alert": "デスクトップ通知", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "ブースト:", "notifications.column_settings.show": "カラムã«è¡¨ç¤º", "notifications.column_settings.sound": "通知音をå†ç”Ÿ", + "notifications.column_settings.status": "æ–°ã—ã„トゥート:", "notifications.filter.all": "ã™ã¹ã¦", "notifications.filter.boosts": "ブースト", "notifications.filter.favourites": "ãŠæ°—ã«å…¥ã‚Š", "notifications.filter.follows": "フォãƒãƒ¼", "notifications.filter.mentions": "返信", "notifications.filter.polls": "ã‚¢ãƒ³ã‚±ãƒ¼ãƒˆçµæžœ", + "notifications.filter.statuses": "フォãƒãƒ¼ã—ã¦ã„ã‚‹äººã®æ–°ç€æƒ…å ±", + "notifications.grant_permission": "権é™ã®ä»˜ä¸Ž", "notifications.group": "{count} ä»¶ã®é€šçŸ¥", + "notifications.mark_as_read": "ã™ã¹ã¦æ—¢èªã«ã™ã‚‹", + "notifications.permission_denied": "ブラウザã®é€šçŸ¥ãŒæ‹’å¦ã•れã¦ã„ã‚‹ãŸã‚デスクトップ通知ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“", + "notifications.permission_denied_alert": "ブラウザã®é€šçŸ¥ãŒæ‹’å¦ã•れã¦ã„ã‚‹ãŸã‚デスクトップ通知を有効ã«ã§ãã¾ã›ã‚“", + "notifications.permission_required": "å¿…è¦ãªæ¨©é™ãŒä»˜ä¸Žã•れã¦ã„ãªã„ãŸã‚ã€ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—通知ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。", + "notifications_permission_banner.enable": "デスクトップ通知を有効ã«ã™ã‚‹", + "notifications_permission_banner.how_to_control": "Mastodon ã‚’é–‰ã˜ã¦ã„ã‚‹é–“ã§ã‚‚通知をå—ä¿¡ã™ã‚‹ã«ã¯ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—通知を有効ã«ã—ã¦ãã ã•ã„。有効ã«ã™ã‚‹ã¨ä¸Šã® {icon} ボタンã‹ã‚‰é€šçŸ¥ã®å†…容を細ã‹ãカスタマイズã§ãã¾ã™ã€‚", + "notifications_permission_banner.title": "ãŠè¦‹é€ƒã—ãªã", + "picture_in_picture.restore": "å…ƒã«æˆ»ã™", "poll.closed": "終了", "poll.refresh": "æ›´æ–°", "poll.total_people": "{count}人", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "ç”»åƒã‹ã‚‰ãƒ†ã‚ストを検出", "upload_modal.edit_media": "メディアを編集", "upload_modal.hint": "サムãƒã‚¤ãƒ«ã®ç„¦ç‚¹ã«ã—ãŸã„å ´æ‰€ã‚’ã‚¯ãƒªãƒƒã‚¯ã™ã‚‹ã‹å††å½¢ã®æž ã‚’ãã®å ´æ‰€ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ãã ã•ã„。", + "upload_modal.preparing_ocr": "OCR ã®æº–å‚™ä¸â€¦", "upload_modal.preview_label": "プレビュー ({ratio})", "upload_progress.label": "アップãƒãƒ¼ãƒ‰ä¸...", "video.close": "動画を閉ã˜ã‚‹", diff --git a/app/javascript/mastodon/locales/ka.json b/app/javascript/mastodon/locales/ka.json index 0051fee1fed6a863bc1d30c066b3af5e2e7da322..ad3b1b033d303ec882c4250080ffffa2c431dc6e 100644 --- a/app/javascript/mastodon/locales/ka.json +++ b/app/javascript/mastodon/locales/ka.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "პირდáƒáƒžáƒ˜áƒ ი წერილი @{name}-ს", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "დáƒáƒ›áƒ”ნი დáƒáƒ›áƒáƒšáƒ£áƒšáƒ˜áƒ", "account.edit_profile": "პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ ცვლილებáƒ", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "გáƒáƒ›áƒáƒ ჩევრპრáƒáƒ¤áƒ˜áƒšáƒ–ე", "account.follow": "გáƒáƒ§áƒáƒšáƒ", "account.followers": "მიმდევრები", @@ -96,7 +98,7 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "ტუტი", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", "compose_form.sensitive.marked": "მედირმáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜áƒ მგრძნáƒáƒ‘იáƒáƒ ედ", "compose_form.sensitive.unmarked": "მედირáƒáƒ áƒáƒ მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ მგრძნáƒáƒ‘იáƒáƒ ედ", "compose_form.spoiler.marked": "გáƒáƒ¤áƒ თხილების უკáƒáƒœ ტექსტი დáƒáƒ›áƒáƒšáƒ£áƒšáƒ˜áƒ", @@ -147,6 +149,7 @@ "emoji_button.search_results": "ძებნის შედეგები", "emoji_button.symbols": "სიმბáƒáƒšáƒáƒ”ბი", "emoji_button.travel": "მáƒáƒ’ზáƒáƒ£áƒ áƒáƒ‘რდრáƒáƒ“გილები", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "ჯერშეტყáƒáƒ‘ინებები áƒáƒ გáƒáƒ¥áƒ•თ. სáƒáƒ£áƒ‘რის დáƒáƒ¡áƒáƒ¬áƒ§áƒ”ბáƒáƒ“ იურთიერთქმედეთ სხვებთáƒáƒœ.", "empty_column.public": "áƒáƒ¥ áƒáƒ áƒáƒ¤áƒ”რიáƒ! შესáƒáƒ•სებáƒáƒ“, დáƒáƒ¬áƒ”რეთ რáƒáƒ˜áƒ›áƒ” ღიáƒáƒ“ áƒáƒœ ხელით გáƒáƒ°áƒ§áƒ”ვით მáƒáƒ›áƒ®áƒ›áƒáƒ ებლებს სხვრინსტáƒáƒœáƒªáƒ˜áƒ”ბისგáƒáƒœ", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "áƒáƒ•ტáƒáƒ იზáƒáƒªáƒ˜áƒ", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "შედგენის ტექსტ-áƒáƒ ეáƒáƒ–ე ფáƒáƒ™áƒ£áƒ¡áƒ˜áƒ¡ მáƒáƒ¡áƒáƒ¨áƒáƒ ებლáƒáƒ“", "keyboard_shortcuts.up": "სიáƒáƒ¨áƒ˜ ზემáƒáƒ— გáƒáƒ“áƒáƒ¡áƒáƒáƒ“გილებლáƒáƒ“", "lightbox.close": "დáƒáƒ®áƒ£áƒ ვáƒ", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "შემდეგი", "lightbox.previous": "წინáƒ", - "lightbox.view_context": "View context", "lists.account.add": "სიáƒáƒ¨áƒ˜ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ", "lists.account.remove": "სიიდáƒáƒœ áƒáƒ›áƒáƒ¨áƒšáƒ", "lists.delete": "სიის წáƒáƒ¨áƒšáƒ", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "სიის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ", "lists.new.title_placeholder": "áƒáƒ®áƒáƒšáƒ˜ სიის სáƒáƒ—áƒáƒ£áƒ ი", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "ძებნრáƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ”ბს შáƒáƒ ის რáƒáƒ›áƒ”ლთáƒáƒª მიჰყვებით", "lists.subheading": "თქვენი სიები", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "ხილვáƒáƒ“áƒáƒ‘ის ჩáƒáƒ თვáƒ", "missing_indicator.label": "áƒáƒ áƒáƒ ნáƒáƒžáƒáƒ•ნი", "missing_indicator.sublabel": "áƒáƒ› რესურსის პáƒáƒ•ნრვერმáƒáƒ®áƒ”რხდáƒ", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "დáƒáƒ•მáƒáƒšáƒáƒ— შეტყáƒáƒ‘ინებები áƒáƒ› მáƒáƒ›áƒ®áƒ›áƒáƒ ებლისგáƒáƒœ?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜ მáƒáƒ›áƒ®áƒ›áƒáƒ ებლები", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name}-მრდáƒáƒ‘უსტრთქვენი სტáƒáƒ¢áƒ£áƒ¡áƒ˜", + "notification.status": "{name} just posted", "notifications.clear": "შეტყáƒáƒ‘ინებების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•ებáƒ", "notifications.clear_confirmation": "დáƒáƒ წმუნებული ხáƒáƒ თ, გსურთ სáƒáƒ›áƒ£áƒ“áƒáƒ›áƒáƒ“ წáƒáƒ¨áƒáƒšáƒáƒ— ყველრთქვენი შეტყáƒáƒ‘ინებáƒ?", "notifications.column_settings.alert": "დესკტáƒáƒž შეტყáƒáƒ‘ინებები", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "ბუსტები:", "notifications.column_settings.show": "გáƒáƒ›áƒáƒ©áƒœáƒ“ეს სვეტში", "notifications.column_settings.sound": "ხმის დáƒáƒ™áƒ•რáƒ", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} შეტყáƒáƒ‘ინებáƒ", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "იტვირთებáƒ...", "video.close": "ვიდეáƒáƒ¡ დáƒáƒ®áƒ£áƒ ვáƒ", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 05f72596b53758b7ef9bc145d8384679b8e2c085..cf9860f1e1698ca27b996cd5d1119e7fc04744d8 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "Tazmilt-ik·im i @{name}", + "account.account_note_header": "Tazmilt", "account.add_or_remove_from_list": "Rnu neÉ£ kkes seg tebdarin", "account.badges.bot": "Aá¹›ubut", "account.badges.group": "Agraw", @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Snirem ugar deg umeÉ£nu aneẓli", "account.cancel_follow_request": "Sefsex asuter n uá¸far", "account.direct": "Izen usrid i @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "TaÉ£ult yeffren", "account.edit_profile": "Ẓreg amaÉ£nu", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Welleh fell-as deg umaÉ£nu-inek", "account.follow": "Ḍfer", "account.followers": "Imeá¸faren", "account.followers.empty": "Ar tura, ulac yiwen i yeá¹á¹afaá¹›en amseqdac-agi.", "account.followers_counter": "{count, plural, one {{count} n umeá¸far} other {{count} n imeá¸faren}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.following_counter": "{count, plural, one {{counter} yeá¹á¹afaren} aá¸far {{counter} wayeá¸}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeá¹á¹afaá¹› yiwen.", "account.follows_you": "Yeá¹á¹afaá¹›-ik", "account.hide_reblogs": "Ffer ayen i ibeá¹á¹u @{name}", @@ -36,7 +38,7 @@ "account.requested": "Di laÉ›á¸il ad yettwaqbel. Ssit i wakken ad yefsex usuter n uá¸far", "account.share": "Bá¸u amaÉ£nu n @{name}", "account.show_reblogs": "Ssken-d inebá¸a n @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} ajewwaq} other {{counter} ijewwaqen}}", "account.unblock": "Serreḥ i @{name}", "account.unblock_domain": "Ssken-d {domain}", "account.unendorse": "Ur ttwellih ara fell-as deg umaÉ£nu-inek", @@ -147,6 +149,7 @@ "emoji_button.search_results": "IgemmaḠn unadi", "emoji_button.symbols": "Izamulen", "emoji_button.travel": "Imeá¸qan d Yinigen", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ulac tijewwaqin dagi!", "empty_column.account_unavailable": "Ur nufi ara amaÉ£nu-ayi", "empty_column.blocks": "Ur tesḥebseḠula yiwen n umseqdac ar tura.", @@ -166,8 +169,10 @@ "empty_column.notifications": "Ulac É£ur-k tilÉ£a. Sedmer akked yemdanen-nniá¸en akken ad tebduḠadiwenni.", "empty_column.public": "Ulac kra da! Aru kra, neÉ£ á¸feá¹› imdanen i yellan deg yiqeddacen-nniá¸en akken ad d-teÄÄar tsuddemt tazayezt", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Smiren asebter-a, ma ur yekkis ara wugur, ẓer d akken tzemreḠad tesqedceḠMaá¹£á¹udun deg yiminig-nniá¸en neÉ£ deg usnas anaá¹£li.", - "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "NÉ£el stacktrace É£ef wafus", "errors.unexpected_crash.report_issue": "Mmel ugur", "follow_request.authorize": "Ssireg", "follow_request.reject": "Agi", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "i tulin É£er d asawen n tebdart", "lightbox.close": "Mdel", + "lightbox.compress": "Ḥemmeẓ tamnaá¸t n uskan n tugna", + "lightbox.expand": "SimeÉ£er tamnaá¸t n uskan n tugna", "lightbox.next": "Γer zdat", "lightbox.previous": "Γer deffir", - "lightbox.view_context": "Ẓer amnaá¸", "lists.account.add": "Rnu É£er tebdart", "lists.account.remove": "Kkes seg tebdart", "lists.delete": "Kkes tabdart", @@ -260,6 +266,10 @@ "lists.edit.submit": "Beddel azwel", "lists.new.create": "Rnu tabdart", "lists.new.title_placeholder": "Azwel amaynut n tebdart", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Ssken-d tiririyin i:", "lists.search": "Nadi gar yemdanen i teá¹á¹afaá¹›eá¸", "lists.subheading": "Tibdarin-ik·im", "load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Ffer {number, plural, one {tugna} other {tugniwin}}", "missing_indicator.label": "Ulac-it", "missing_indicator.sublabel": "Ur nufi ara aÉ£balu-a", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "TebÉ£iḠad teffreḠtalÉ£utin n umseqdac-a?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Isnasen izirazen", "navigation_bar.blocks": "Imseqdacen yettusḥebsen", "navigation_bar.bookmarks": "Ticraá¸", @@ -295,9 +307,10 @@ "notification.follow": "{name} yeá¹á¹afaá¹›-ik", "notification.follow_request": "{name} yessuter-d ad k-yeá¸feá¹›", "notification.mention": "{name} yebder-ik-id", - "notification.own_poll": "Your poll has ended", + "notification.own_poll": "Tafrant-ik·im tfuk", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} yebá¸a tajewwiqt-ik i tikelt-nniá¸en", + "notification.status": "{name} just posted", "notifications.clear": "SfeḠtilÉ£a", "notifications.clear_confirmation": "TebÉ£iḠs tidet ad tekkseḠakk tilÉ£a-inek·em i lebda?", "notifications.column_settings.alert": "TilÉ£a n tnarit", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Seǧhed:", "notifications.column_settings.show": "Ssken-d tilÉ£a deg ujgu", "notifications.column_settings.sound": "Rmed imesli", + "notifications.column_settings.status": "Tiẓenẓunin timaynutin:", "notifications.filter.all": "Akk", "notifications.filter.boosts": "Seǧhed", "notifications.filter.favourites": "Ismenyifen", "notifications.filter.follows": "Yeá¹afaá¹›", "notifications.filter.mentions": "Abdar", "notifications.filter.polls": "IgemmaḠn usenqed", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} n tilÉ£a", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "D awezÉ£i ad yili wermad n yilÉ£a n tnarit axateá¹› turagt tettwagdel.", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Ifukk", "poll.refresh": "Smiren", "poll.total_people": "{count, plural, one {# n wemdan} other {# n yemdanen}}", @@ -328,7 +352,7 @@ "poll.voted": "TdeɣṛeḠɣef tririt-ayi", "poll_button.add_poll": "Rnu asenqed", "poll_button.remove_poll": "Kkes asenqed", - "privacy.change": "Adjust status privacy", + "privacy.change": "Seggem tabaá¸nit n yizen", "privacy.direct.long": "Bá¸u gar yimseqdacen i tbedreḠkan", "privacy.direct.short": "Usrid", "privacy.private.long": "Bá¸u i yimeá¸faá¹›en-ik kan", @@ -389,8 +413,8 @@ "status.pinned": "Tijewwiqin yettwasentá¸en", "status.read_more": "Issin ugar", "status.reblog": "Bá¸u", - "status.reblog_private": "Boost to original audience", - "status.reblogged_by": "{name} boosted", + "status.reblog_private": "Boost with original visibility", + "status.reblogged_by": "Yebá¸a-tt {name}", "status.reblogs.empty": "Ula yiwen ur yebá¸i tajewwiqt-agi ar tura. Ticki yebá¸a-tt yiwen, ad d-iban da.", "status.redraft": "Kkes tÉ›iwdeḠtira", "status.remove_bookmark": "Kkes tacreá¸t", @@ -417,20 +441,20 @@ "time_remaining.days": "Mazal {number, plural, one {# n wass} other {# n wussan}}", "time_remaining.hours": "Mazal {number, plural, one {# n usrag} other {# n yesragen}}", "time_remaining.minutes": "Mazal {number, plural, one {# n tesdat} other {# n tesdatin}}", - "time_remaining.moments": "Moments remaining", + "time_remaining.moments": "Akuden i d-yeqqimen", "time_remaining.seconds": "Mazal {number, plural, one {# n tasint} other {# n tsinin}} id yugran", "timeline_hint.remote_resource_not_displayed": "{resource} seg yiqeddacen-nniá¸en ur d-ttwaskanent ara.", "timeline_hint.resources.followers": "Imeá¸faá¹›en", "timeline_hint.resources.follows": "T·Yeá¹afaá¹›", "timeline_hint.resources.statuses": "Tijewwaqin tiqdimin", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, one {{counter} amdan} imdanen {{counter} wiyaá¸}} yettmeslayen", "trends.trending_now": "Trending now", "ui.beforeunload": "Arewway-ik·im ad iruḥ ma yella tefeÉ£-d deg Maá¹£á¹udun.", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Zuḥeb rnu sers i tasalyt", - "upload_button.label": "Rnu taÉ£walt ({formats})", + "upload_button.label": "Rnu taÉ£walt", "upload_error.limit": "Asali n ufaylu iεedda talast.", "upload_error.poll": "Ur ittusireg ara usali n ufaylu s tefranin.", "upload_form.audio_description": "Glem-d i yemdanen i yesÉ›an ugur deg tmesliwt", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Sefru-d aá¸ris seg tugna", "upload_modal.edit_media": "Ẓreg taÉ£walt", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Aheyyi n OCR…", "upload_modal.preview_label": "Taskant ({ratio})", "upload_progress.label": "Asali iteddu...", "video.close": "Mdel tabidyutt", diff --git a/app/javascript/mastodon/locales/kk.json b/app/javascript/mastodon/locales/kk.json index 322c15fff69dcc89506497b778b57319bbfd1417..04a0f9140ec0c7533fca4a90c3b5ebeb49371022 100644 --- a/app/javascript/mastodon/locales/kk.json +++ b/app/javascript/mastodon/locales/kk.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Жазба", "account.add_or_remove_from_list": "Тізімге қоÑу немеÑе жою", "account.badges.bot": "Бот", - "account.badges.group": "Group", + "account.badges.group": "Топ", "account.block": "Бұғаттау @{name}", "account.block_domain": "Домендегі барлығын бұғатта {domain}", "account.blocked": "Бұғатталды", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Толығырақ оригинал профилінде қара", "account.cancel_follow_request": "Жазылуға Ñұранымды қайтару", "account.direct": "Жеке хат @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Домен жабық", "account.edit_profile": "Профильді өңдеу", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Профильде рекомендеу", "account.follow": "Жазылу", "account.followers": "Оқырмандар", "account.followers.empty": "Әлі ешкім жазылмаған.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Оқырман} other {{counter} Оқырман}}", + "account.following_counter": "{count, plural, one {{counter} Жазылым} other {{counter} Жазылым}}", "account.follows.empty": "Ешкімге жазылмапты.", "account.follows_you": "Сізге жазылыпты", "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жаÑыру", @@ -36,19 +38,19 @@ "account.requested": "РаÑтауын күтіңіз. Жазылудан Ð±Ð°Ñ Ñ‚Ð°Ñ€Ñ‚Ñƒ үшін баÑыңыз", "account.share": "@{name} профилін бөліÑу\"", "account.show_reblogs": "@{name} бөліÑкендерін көрÑету", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} ПоÑÑ‚} other {{counter} ПоÑÑ‚}}", "account.unblock": "Бұғаттан шығару @{name}", "account.unblock_domain": "Бұғаттан шығару {domain}", "account.unendorse": "Профильде рекомендемеу", "account.unfollow": "Оқымау", "account.unmute": "@{name} еÑкертпелерін қоÑу", "account.unmute_notifications": "@{name} еÑкертпелерін көрÑету", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Жазба қалдыру үшін баÑ", "alert.rate_limited.message": "Қайтадан көріңіз {retry_time, time, medium} кейін.", "alert.rate_limited.title": "Бағалау шектеулі", "alert.unexpected.message": "Бір нәрÑе Ð´Ò±Ñ€Ñ‹Ñ Ð±Ð¾Ð»Ð¼Ð°Ð´Ñ‹.", "alert.unexpected.title": "Өй!", - "announcement.announcement": "Announcement", + "announcement.announcement": "Хабарландыру", "autosuggest_hashtag.per_week": "{count} аптаÑына", "boost_modal.combo": "КелеÑіде өткізіп жіберу үшін баÑыңыз {combo}", "bundle_column_error.body": "Бұл компонентті жүктеген кезде бір қате пайда болды.", @@ -79,9 +81,9 @@ "column_header.show_settings": "Баптауларды көрÑет", "column_header.unpin": "Ðлып таÑтау", "column_subheading.settings": "Баптаулар", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "Тек жергілікті", "community.column_settings.media_only": "Тек медиа", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "Тек Ñыртқы", "compose_form.direct_message_warning": "Тек аталған қолданушыларға.", "compose_form.direct_message_warning_learn_more": "Көбірек білу", "compose_form.hashtag_warning": "Бұл поÑÑ‚ іздеуде Ñ…Ñштегпен шықпайды, өйткені ол бәріне ашық емеÑ. Тек ашық жазбаларды ғана Ñ…Ñштег арқылы іздеп табуға болады.", @@ -92,8 +94,8 @@ "compose_form.poll.duration": "Сауалнама мерзімі", "compose_form.poll.option_placeholder": "Жауап {number}", "compose_form.poll.remove_option": "Бұл жауапты өшір", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.poll.switch_to_multiple": "Бірнеше жауап таңдайтындай қылу", + "compose_form.poll.switch_to_single": "Тек бір жауап таңдайтындай қылу", "compose_form.publish": "Түрт", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.hide": "Сезімтал ретінде белгіле", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Іздеу нәтижелері", "emoji_button.symbols": "Таңбалар", "emoji_button.travel": "СаÑхат", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Жазба жоқ ешқандай!", "empty_column.account_unavailable": "Профиль қолжетімді емеÑ", "empty_column.blocks": "Ешкімді бұғаттамағанÑыз.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Әзірше ешқандай еÑкертпе жоқ. БаÑқалармен аралаÑуды баÑтаңыз және пікірталаÑтарға қатыÑыңыз.", "empty_column.public": "Ештеңе жоқ бұл жерде! Өзіңіз баÑтап жазып көріңіз немеÑе баÑқаларға жазылыңыз", "error.unexpected_crash.explanation": "Кодтағы баг немеÑе браузердегі қатеден, бұл бет Ð´Ò±Ñ€Ñ‹Ñ Ð°ÑˆÑ‹Ð»Ð¼Ð°Ð¹ тұр.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Бетті жаңартып көріңіз. Егер бұл көмектеÑпеÑе, Mastodon желіÑін баÑқа браузерден немеÑе мобиль қоÑымшадан ашып көріңіз.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Жиынтықты көшіріп ал клипбордқа", "errors.unexpected_crash.report_issue": "МәÑелені хабарла", "follow_request.authorize": "ÐвторизациÑ", "follow_request.reject": "Қабылдамау", "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", + "generic.saved": "Сақталды", "getting_started.developers": "ЖаÑаушылар тобы", "getting_started.directory": "Профильдер каталогы", "getting_started.documentation": "Құжаттама", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "жауап жазу", "keyboard_shortcuts.requests": "жазылу Ñұранымдарын қарау", "keyboard_shortcuts.search": "іздеу", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "CW көрÑету/жабу", "keyboard_shortcuts.start": "баÑтапқы бағанға бару", "keyboard_shortcuts.toggle_hidden": "жабық мәтінді CW ашу/жабу", "keyboard_shortcuts.toggle_sensitivity": "көрÑет/жап", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "жазба қалдыру алаңынан шығу", "keyboard_shortcuts.up": "тізімде жоғары шығу", "lightbox.close": "Жабу", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "КелеÑÑ–", "lightbox.previous": "Ðлдыңғы", - "lightbox.view_context": "КонтекÑті көрÑет", "lists.account.add": "Тізімге қоÑу", "lists.account.remove": "Тізімнен шығару", "lists.delete": "Тізімді өшіру", @@ -260,6 +266,10 @@ "lists.edit.submit": "Тақырыбын өзгерту", "lists.new.create": "Тізім құру", "lists.new.title_placeholder": "Жаңа тізім аты", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Сіз іздеген адамдар араÑында іздеу", "lists.subheading": "Тізімдеріңіз", "load_pending": "{count, plural, one {# жаңа нәрÑе} other {# жаңа нәрÑе}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Көрінуді қоÑу", "missing_indicator.label": "Табылмады", "missing_indicator.sublabel": "Бұл реÑÑƒÑ€Ñ Ñ‚Ð°Ð±Ñ‹Ð»Ð¼Ð°Ð´Ñ‹", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Бұл қолданушы еÑкертпелерін жаÑырамыз ба?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Мобиль қоÑымшалар", "navigation_bar.blocks": "Бұғатталғандар", "navigation_bar.bookmarks": "Бетбелгілер", @@ -298,6 +310,7 @@ "notification.own_poll": "Сауалнама аÑқталды", "notification.poll": "Бұл Ñауалнаманың мерзімі аÑқталыпты", "notification.reblog": "{name} жазбаңызды бөліÑті", + "notification.status": "{name} just posted", "notifications.clear": "ЕÑкертпелерді тазарт", "notifications.clear_confirmation": "Шынымен барлық еÑкертпелерді өшіреÑіз бе?", "notifications.column_settings.alert": "Ò®Ñтел еÑкертпелері", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "БөліÑулер:", "notifications.column_settings.show": "Бағанда көрÑет", "notifications.column_settings.sound": "ДыбыÑын қоÑ", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Барлығы", "notifications.filter.boosts": "БөліÑулер", "notifications.filter.favourites": "Таңдаулылар", "notifications.filter.follows": "Жазылулар", "notifications.filter.mentions": "Ðталымдар", "notifications.filter.polls": "Сауалнама нәтижелері", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} еÑкертпе", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Жабық", "poll.refresh": "Жаңарту", "poll.total_people": "{count, plural, one {# адам} other {# адам}}", @@ -419,11 +443,11 @@ "time_remaining.minutes": "{number, plural, one {# минут} other {# минут}}", "time_remaining.moments": "Қалған уақыт", "time_remaining.seconds": "{number, plural, one {# Ñекунд} other {# Ñекунд}}", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "{resource} баÑқа Ñерверлерде көрÑетілмейді.", + "timeline_hint.resources.followers": "Оқырман", + "timeline_hint.resources.follows": "Жазылым", + "timeline_hint.resources.statuses": "ЕÑкі поÑттары", + "trends.counter_by_accounts": "{count, plural, one {{counter} адам} other {{counter} адам}} айтып жатыр", "trends.trending_now": "Тренд тақырыптар", "ui.beforeunload": "Mastodon желіÑінен шықÑаңыз, нобайыңыз Ñақталмайды.", "units.short.billion": "{count}B", @@ -436,16 +460,17 @@ "upload_form.audio_description": "ЕÑту қабілеті нашар адамдарға Ñипаттама беріңіз", "upload_form.description": "Көру қабілеті нашар адамдар үшін Ñипаттаңыз", "upload_form.edit": "Түзету", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Суретті өзгерту", "upload_form.undo": "Өшіру", "upload_form.video_description": "ЕÑту немеÑе көру қабілеті нашар адамдарға Ñипаттама беріңіз", "upload_modal.analyzing_picture": "Суретті анализ жаÑау…", "upload_modal.apply": "Қолдану", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Сурет таңдау", "upload_modal.description_placeholder": "ЩучинÑк Ñъезіндегі өрт пе? Вагон-үй, аÑромобиль һәм ұшақ фюзелÑжы цехінен ғой", "upload_modal.detect_text": "Суреттен мәтін анықтау", "upload_modal.edit_media": "Медиафайлды өңдеу", "upload_modal.hint": "Ðлдын-ала қарау шеңберін баÑыңыз немеÑе Ñүйреңіз, барлық нобайларда көрінетін фокуÑты таңдау үшін.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Превью ({ratio})", "upload_progress.label": "Жүктеп жатыр...", "video.close": "Видеоны жабу", diff --git a/app/javascript/mastodon/locales/kn.json b/app/javascript/mastodon/locales/kn.json index e9618e0f2e91cae8ed9bdc402197b2d04f0f9176..a5025bb72cbf6c795aa9dbdade9bd881629a89fb 100644 --- a/app/javascript/mastodon/locales/kn.json +++ b/app/javascript/mastodon/locales/kn.json @@ -1,19 +1,21 @@ { - "account.account_note_header": "Note", - "account.add_or_remove_from_list": "Add or Remove from lists", + "account.account_note_header": "ಟಿಪà³à²ªà²£à²¿", + "account.add_or_remove_from_list": "ಪಟà³à²Ÿà²¿à²—ೆ ಸೇರಿಸೠಅಥವ ಪಟà³à²Ÿà²¿à²¯à²¿à²‚ದ ತೆಗೆದà³à²¹à²¾à²•à³", "account.badges.bot": "Bot", - "account.badges.group": "Group", + "account.badges.group": "ಗà³à²‚ಪà³", "account.block": "Block @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", - "account.follow": "Follow", - "account.followers": "Followers", + "account.follow": "ಹಿಂಬಾಲಿಸಿ", + "account.followers": "ಹಿಂಬಾಲಕರà³", "account.followers.empty": "No one follows this user yet.", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", @@ -30,7 +32,7 @@ "account.mute_notifications": "Mute notifications from @{name}", "account.muted": "Muted", "account.never_active": "Never", - "account.posts": "Toots", + "account.posts": "ಟೂಟà³â€Œà²—ಳà³", "account.posts_with_replies": "Toots and replies", "account.report": "Report @{name}", "account.requested": "Awaiting approval", @@ -47,12 +49,12 @@ "alert.rate_limited.message": "Please retry after {retry_time, time, medium}.", "alert.rate_limited.title": "Rate limited", "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", + "alert.unexpected.title": "ಅಯà³à²¯à³‹!", "announcement.announcement": "Announcement", "autosuggest_hashtag.per_week": "{count} per week", "boost_modal.combo": "You can press {combo} to skip this next time", "bundle_column_error.body": "Something went wrong while loading this component.", - "bundle_column_error.retry": "Try again", + "bundle_column_error.retry": "ಮರಳಿ ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿", "bundle_column_error.title": "Network error", "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 78209fb0e8334e110580bfb86612504cf401f3a3..10f7eabcf89d6c4765c9e23e6174697dfb2985f3 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "@{name} ì— ëŒ€í•œ 노트", + "account.account_note_header": "노트", "account.add_or_remove_from_list": "ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€ í˜¹ì€ ì‚ì œ", "account.badges.bot": "ë´‡", "account.badges.group": "그룹", @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "ì›ë³¸ 프로필ì—서 ë” íƒìƒ‰í•˜ê¸°", "account.cancel_follow_request": "팔로우 ìš”ì² ì·¨ì†Œ", "account.direct": "@{name}ì˜ ë‹¤ì´ë ‰íЏ 메시지", + "account.disable_notifications": "@{name} ì˜ ê²Œì‹œë¬¼ 알림 ë„기", "account.domain_blocked": "ë„ë©”ì¸ ìˆ¨ê²¨ì§", "account.edit_profile": "프로필 편집", + "account.enable_notifications": "@{name} ì˜ ê²Œì‹œë¬¼ 알림 켜기", "account.endorse": "í”„ë¡œí•„ì— ë³´ì´ê¸°", "account.follow": "팔로우", "account.followers": "팔로워", @@ -43,7 +45,7 @@ "account.unfollow": "팔로우 í•´ì œ", "account.unmute": "뮤트 í•´ì œ", "account.unmute_notifications": "@{name}ì˜ ì•Œë¦¼ 뮤트 í•´ì œ", - "account_note.placeholder": "ìž‘ì„±ëœ ëŒ“ê¸€ì´ ì—†ìŒ", + "account_note.placeholder": "í´ë¦í•´ì„œ 노트 추가", "alert.rate_limited.message": "{retry_time, time, medium}ì— ë‹¤ì‹œ 시ë„í•´ 주세요.", "alert.rate_limited.title": "ë¹ˆë„ ì œí•œ", "alert.unexpected.message": "예측하지 못한 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "검색 ê²°ê³¼", "emoji_button.symbols": "기호", "emoji_button.travel": "여행과 장소", + "empty_column.account_suspended": "ê³„ì • ì •ì§€ë¨", "empty_column.account_timeline": "여긴 íˆ¿ì´ ì—†ì–´ìš”!", "empty_column.account_unavailable": "프로필 사용 불가", "empty_column.blocks": "ì•„ì§ ì•„ë¬´ë„ ì°¨ë‹¨í•˜ì§€ 않았습니다.", @@ -166,7 +169,9 @@ "empty_column.notifications": "ì•„ì§ ì•Œë¦¼ì´ ì—†ìŠµë‹ˆë‹¤. 다른 사람과 대화를 시작해 보세요.", "empty_column.public": "여기엔 ì•„ì§ ì•„ë¬´ ê²ƒë„ ì—†ìŠµë‹ˆë‹¤! 공개ì 으로 무언가 í¬ìŠ¤íŒ…í•˜ê±°ë‚˜, 다른 ì„œë²„ì˜ ìœ ì €ë¥¼ 팔로우 해서 채워보세요", "error.unexpected_crash.explanation": "버그 í˜¹ì€ ë¸Œë¼ìš°ì € 호환성 ë¬¸ì œë¡œ ì´ íŽ˜ì´ì§€ë¥¼ 올바르게 í‘œì‹œí• ìˆ˜ 없습니다.", + "error.unexpected_crash.explanation_addons": "ì´ íŽ˜ì´ì§€ëŠ” 올바르게 보여질 수 없습니다. 브ë¼ìš°ì € ì• ë“œì˜¨ì´ë‚˜ ìžë™ ë²ˆì— ë„구 등으로 ì¸í•´ ë°œìƒëœ ì—ëŸ¬ì¼ ìˆ˜ 있습니다.", "error.unexpected_crash.next_steps": "페ì´ì§€ë¥¼ ìƒˆë¡œê³ ì¹¨ 해보세요. ê·¸ëž˜ë„ í•´ê²°ë˜ì§€ 않는 경우, 다른 브ë¼ìš°ì €ë‚˜ 네ì´í‹°ë¸Œ ì•±ìœ¼ë¡œë„ ë§ˆìŠ¤í† ëˆì„ ì´ìš©í•˜ì‹¤ 수 있습니다.", + "error.unexpected_crash.next_steps_addons": "ê·¸ê²ƒë“¤ì„ ë„ê³ íŽ˜ì´ì§€ë¥¼ ìƒˆë¡œê³ ì¹¨ 해보세요. ê·¸ëž˜ë„ í•´ê²°ë˜ì§€ 않는 경우, 다른 브ë¼ìš°ì €ë‚˜ 네ì´í‹°ë¸Œ ì•±ìœ¼ë¡œë„ ë§ˆìŠ¤í† ëˆì„ ì´ìš©í•˜ì‹¤ 수 있습니다.", "errors.unexpected_crash.copy_stacktrace": "ì—러 ë‚´ìš©ì„ í´ë¦½ë³´ë“œì— 복사", "errors.unexpected_crash.report_issue": "ë¬¸ì œ ì‹ ê³ ", "follow_request.authorize": "허가", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "작성창ì—서 í¬ì»¤ìФ í•´ì œ", "keyboard_shortcuts.up": "리스트ì—서 위로 ì´ë™", "lightbox.close": "닫기", + "lightbox.compress": "ì´ë¯¸ì§€ 박스 ì••ì¶•", + "lightbox.expand": "ì´ë¯¸ì§€ 박스 확장", "lightbox.next": "다ìŒ", "lightbox.previous": "ì´ì „", - "lightbox.view_context": "게시물 보기", "lists.account.add": "ë¦¬ìŠ¤íŠ¸ì— ì¶”ê°€", "lists.account.remove": "리스트ì—서 ì œê±°", "lists.delete": "리스트 ì‚ì œ", @@ -260,6 +266,10 @@ "lists.edit.submit": "ì œëª© ìˆ˜ì •", "lists.new.create": "리스트 추가", "lists.new.title_placeholder": "새 ë¦¬ìŠ¤íŠ¸ì˜ ì´ë¦„", + "lists.replies_policy.followed": "팔로우 한 ì‚¬ìš©ìž ëˆ„êµ¬ë‚˜", + "lists.replies_policy.list": "ë¦¬ìŠ¤íŠ¸ì˜ êµ¬ì„±ì›ë“¤", + "lists.replies_policy.none": "ì•„ë¬´ë„ ì—†ìŒ", + "lists.replies_policy.title": "답글 표시:", "lists.search": "팔로우 ì¤‘ì¸ ì‚¬ëžŒë“¤ 중ì—서 찾기", "lists.subheading": "ë‹¹ì‹ ì˜ ë¦¬ìŠ¤íŠ¸", "load_pending": "{count}ê°œì˜ ìƒˆ í•목", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "표시 ì „í™˜", "missing_indicator.label": "ì°¾ì„ ìˆ˜ 없습니다", "missing_indicator.sublabel": "ì´ ë¦¬ì†ŒìŠ¤ë¥¼ ì°¾ì„ ìˆ˜ 없었습니다", + "mute_modal.duration": "기간", "mute_modal.hide_notifications": "ì´ ì‚¬ìš©ìžë¡œë¶€í„°ì˜ ì•Œë¦¼ì„ ìˆ¨ê¸°ì‹œê² ìŠµë‹ˆê¹Œ?", + "mute_modal.indefinite": "무기한", "navigation_bar.apps": "ëª¨ë°”ì¼ ì•±", "navigation_bar.blocks": "차단한 사용ìž", "navigation_bar.bookmarks": "보관함", @@ -291,13 +303,14 @@ "navigation_bar.preferences": "ì‚¬ìš©ìž ì„¤ì •", "navigation_bar.public_timeline": "ì—°í•© 타임ë¼ì¸", "navigation_bar.security": "보안", - "notification.favourite": "{name}ë‹˜ì´ ì¦ê²¨ì°¾ê¸° 했습니다", - "notification.follow": "{name}ë‹˜ì´ ë‚˜ë¥¼ 팔로우 했습니다", - "notification.follow_request": "{name}ë‹˜ì´ íŒ”ë¡œìš° ìš”ì²ì„ 보냈습니다", - "notification.mention": "{name}ë‹˜ì´ ë‹µê¸€ì„ ë³´ëƒˆìŠµë‹ˆë‹¤", + "notification.favourite": "{name} ë‹˜ì´ ì¦ê²¨ì°¾ê¸° 했습니다", + "notification.follow": "{name} ë‹˜ì´ ë‚˜ë¥¼ 팔로우 했습니다", + "notification.follow_request": "{name} ë‹˜ì´ íŒ”ë¡œìš° ìš”ì²ì„ 보냈습니다", + "notification.mention": "{name} ë‹˜ì´ ë‹µê¸€ì„ ë³´ëƒˆìŠµë‹ˆë‹¤", "notification.own_poll": "ë‚´ 투표가 ë났습니다", "notification.poll": "ë‹¹ì‹ ì´ ì°¸ì—¬ 한 투표가 종료ë˜ì—ˆìŠµë‹ˆë‹¤", - "notification.reblog": "{name}ë‹˜ì´ ë¶€ìŠ¤íŠ¸ 했습니다", + "notification.reblog": "{name} ë‹˜ì´ ë¶€ìŠ¤íŠ¸ 했습니다", + "notification.status": "{name} ë‹˜ì´ ë°©ê¸ˆ ê²Œì‹œë¬¼ì„ ì˜¬ë ¸ìŠµë‹ˆë‹¤", "notifications.clear": "알림 지우기", "notifications.clear_confirmation": "ì •ë§ë¡œ ì•Œë¦¼ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?", "notifications.column_settings.alert": "ë°ìФí¬íƒ‘ 알림", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "부스트:", "notifications.column_settings.show": "ì»¬ëŸ¼ì— í‘œì‹œ", "notifications.column_settings.sound": "íš¨ê³¼ìŒ ìž¬ìƒ", + "notifications.column_settings.status": "새 툿:", "notifications.filter.all": "모ë‘", "notifications.filter.boosts": "부스트", "notifications.filter.favourites": "ì¦ê²¨ì°¾ê¸°", "notifications.filter.follows": "팔로우", "notifications.filter.mentions": "멘션", "notifications.filter.polls": "투표 ê²°ê³¼", + "notifications.filter.statuses": "팔로우 하는 ì‚¬ëžŒë“¤ì˜ ìµœì‹ ê²Œì‹œë¬¼", + "notifications.grant_permission": "권한 부여.", "notifications.group": "{count} ê°œì˜ ì•Œë¦¼", + "notifications.mark_as_read": "ëª¨ë“ ì•Œë¦¼ì„ ì½ì€ ìƒíƒœë¡œ 표시", + "notifications.permission_denied": "ê¶Œí•œì´ ê±°ë¶€ë˜ì—ˆê¸° ë•Œë¬¸ì— ë°ìФí¬íƒ‘ ì•Œë¦¼ì„ í™œì„±í™”í• ìˆ˜ ì—†ìŒ", + "notifications.permission_denied_alert": "ì´ì „ì— ë¸Œë¼ìš°ì € ê¶Œí•œì´ ê±°ë¶€ë˜ì—ˆê¸° 때문ì—, ë°ìФí¬íƒ‘ ì•Œë¦¼ì´ í™œì„±í™” ë 수 없습니다.", + "notifications.permission_required": "필요한 ê¶Œí•œì´ ìŠ¹ì¸ë˜ì§€ 않아 ë°ìФí¬íƒ‘ ì•Œë¦¼ì„ ì‚¬ìš©í• ìˆ˜ 없습니다.", + "notifications_permission_banner.enable": "ë°ìФí¬íƒ‘ 알림 활성화", + "notifications_permission_banner.how_to_control": "ë§ˆìŠ¤í† ëˆì´ ì—´ë ¤ 있지 ì•Šì„ ë•Œì—ë„ ì•Œë¦¼ì„ ë°›ìœ¼ë ¤ë©´, ë°ìФí¬íƒ‘ ì•Œë¦¼ì„ í™œì„±í™” 하세요. ë‹¹ì‹ ì€ ì–´ë–¤ ì¢…ë¥˜ì˜ ë°˜ì‘ì´ ë°ìФí¬íƒ‘ ì•Œë¦¼ì„ ë°œìƒí• 지를 {icon} ë²„íŠ¼ì„ í†µí•´ 세세하게 ì„¤ì •í• ìˆ˜ 있습니다.", + "notifications_permission_banner.title": "ì•„ë¬´ê²ƒë„ ë†“ì¹˜ì§€ 마세요", + "picture_in_picture.restore": "다시 넣기", "poll.closed": "마ê°ë¨", "poll.refresh": "ìƒˆë¡œê³ ì¹¨", "poll.total_people": "{count}명", @@ -390,7 +414,7 @@ "status.read_more": "ë” ë³´ê¸°", "status.reblog": "부스트", "status.reblog_private": "ì›ëž˜ì˜ ìˆ˜ì‹ ìžë“¤ì—게 부스트", - "status.reblogged_by": "{name}ë‹˜ì´ ë¶€ìŠ¤íŠ¸ 했습니다", + "status.reblogged_by": "{name} ë‹˜ì´ ë¶€ìŠ¤íŠ¸ 했습니다", "status.reblogs.empty": "ì•„ì§ ì•„ë¬´ë„ ì´ íˆ¿ì„ ë¶€ìŠ¤íŠ¸í•˜ì§€ 않았습니다. 부스트 한 ì‚¬ëžŒë“¤ì´ ì—¬ê¸°ì— í‘œì‹œ ë©ë‹ˆë‹¤.", "status.redraft": "ì§€ìš°ê³ ë‹¤ì‹œ 쓰기", "status.remove_bookmark": "보관한 툿 ì‚ì œ", @@ -419,16 +443,16 @@ "time_remaining.minutes": "{number} ë¶„ 남ìŒ", "time_remaining.moments": "ë‚¨ì€ ì‹œê°„", "time_remaining.seconds": "{number} ì´ˆ 남ìŒ", - "timeline_hint.remote_resource_not_displayed": "다른 ì„œë²„ì˜ {resource}는 보여지지 않습니다.", + "timeline_hint.remote_resource_not_displayed": "다른 ì„œë²„ì˜ {resource} 표시는 í• ìˆ˜ 없습니다.", "timeline_hint.resources.followers": "팔로워", "timeline_hint.resources.follows": "팔로우", "timeline_hint.resources.statuses": "ì´ì „ 툿", "trends.counter_by_accounts": "{counter} ëª…ì´ ë§í•˜ëŠ” 중", "trends.trending_now": "지금 ìœ í–‰ì¤‘", "ui.beforeunload": "지금 나가면 ì €ìž¥ë˜ì§€ ì•Šì€ í•ëª©ì„ ìžƒê²Œ ë©ë‹ˆë‹¤.", - "units.short.billion": "{count}ì‹ì–µ", - "units.short.million": "{count}백만", - "units.short.thousand": "{count}천", + "units.short.billion": "{count}B", + "units.short.million": "{count}B", + "units.short.thousand": "{count}K", "upload_area.title": "드래그 & 드ë¡ìœ¼ë¡œ 업로드", "upload_button.label": "미디어 추가 (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "íŒŒì¼ ì—…ë¡œë“œ ì œí•œì— ë„달했습니다.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "ì²ê° ìž¥ì• ì¸ì„ 위한 설명", "upload_form.description": "시ê°ìž¥ì• ì¸ì„ 위한 설명", "upload_form.edit": "편집", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "ì¸ë„¤ì¼ 변경", "upload_form.undo": "ì‚ì œ", "upload_form.video_description": "ì²ê°, ì‹œê° ìž¥ì• ì¸ì„ 위한 설명", "upload_modal.analyzing_picture": "ì´ë¯¸ì§€ ë¶„ì„ ì¤‘â€¦", "upload_modal.apply": "ì ìš©", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "ì´ë¯¸ì§€ ì„ íƒ", "upload_modal.description_placeholder": "ë‹¤ëžŒì¥ í—Œ 쳇바퀴 íƒ€ê³ íŒŒ", "upload_modal.detect_text": "ì´ë¯¸ì§€ì—서 í…스트 추출", "upload_modal.edit_media": "미디어 편집", "upload_modal.hint": "미리보기를 í´ë¦í•˜ê±°ë‚˜ 드래그 해서 í¬ì»¬ í¬ì¸íŠ¸ë¥¼ 맞추세요. ì´ ì ì€ ì¸ë„¤ì¼ì— í•ìƒ ë³´ì—¬ì§ˆ ë¶€ë¶„ì„ ë‚˜íƒ€ëƒ…ë‹ˆë‹¤.", + "upload_modal.preparing_ocr": "OCR 준비 중…", "upload_modal.preview_label": "미리보기 ({ratio})", "upload_progress.label": "업로드 중...", "video.close": "ë™ì˜ìƒ 닫기", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index e5d833fe87465898b1831bb4ceb749f69e1f8e65..3c359d2229d79d3d0b4e33e4a3f439519d065542 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -1,461 +1,486 @@ { - "account.account_note_header": "Note", - "account.add_or_remove_from_list": "Add or Remove from lists", - "account.badges.bot": "Bot", - "account.badges.group": "Group", - "account.block": "Block @{name}", - "account.block_domain": "Block domain {domain}", - "account.blocked": "Blocked", - "account.browse_more_on_origin_server": "Browse more on the original profile", - "account.cancel_follow_request": "Cancel follow request", - "account.direct": "Direct message @{name}", - "account.domain_blocked": "Domain blocked", - "account.edit_profile": "Edit profile", - "account.endorse": "Feature on profile", - "account.follow": "Follow", - "account.followers": "Followers", - "account.followers.empty": "No one follows this user yet.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.account_note_header": "تێبینی ", + "account.add_or_remove_from_list": "زیادکردن یان سڕینەوە Ù„Û• پێرستەکان", + "account.badges.bot": "بوت", + "account.badges.group": "گرووپ", + "account.block": "بلۆکی @{name}", + "account.block_domain": "بلۆکی هەموو شتێک Ù„Û• {domain}", + "account.blocked": "بلۆککرا", + "account.browse_more_on_origin_server": "گەڕانی ÙØ±Û•تر Ù„Û• سەر Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ سەرەکی", + "account.cancel_follow_request": "بەتاڵکردنی داوای شوێنکەوتن", + "account.direct": "پەیامی تایبەت بە @{name}", + "account.disable_notifications": "ئاگانامە مەنێرە بۆم کاتێک @{name} پۆست دەکرێت", + "account.domain_blocked": "دۆمەین قەپاتکرا", + "account.edit_profile": "دەستکاری Ù¾Ø±Û†ÙØ§ÛŒÙ„", + "account.enable_notifications": "ئاگادارم بکەوە کاتێک @{name} بابەتەکان", + "account.endorse": "ناساندن Ù„Û• Ù¾Ø±Û†ÙØ§ÛŒÙ„", + "account.follow": "شوێنکەوتن", + "account.followers": "شوێنکەوتووان", + "account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە", + "account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}", "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", - "account.follows.empty": "This user doesn't follow anyone yet.", - "account.follows_you": "Follows you", - "account.hide_reblogs": "Hide boosts from @{name}", - "account.last_status": "Last active", - "account.link_verified_on": "Ownership of this link was checked on {date}", - "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", - "account.media": "Media", - "account.mention": "Mention @{name}", - "account.moved_to": "{name} has moved to:", - "account.mute": "Mute @{name}", - "account.mute_notifications": "Mute notifications from @{name}", - "account.muted": "Muted", - "account.never_active": "Never", - "account.posts": "Toots", - "account.posts_with_replies": "Toots and replies", - "account.report": "Report @{name}", - "account.requested": "Awaiting approval", - "account.share": "Share @{name}'s profile", - "account.show_reblogs": "Show boosts from @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", - "account.unblock": "Unblock @{name}", - "account.unblock_domain": "Unblock domain {domain}", - "account.unendorse": "Don't feature on profile", - "account.unfollow": "Unfollow", - "account.unmute": "Unmute @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", - "account_note.placeholder": "Click to add a note", - "alert.rate_limited.message": "Please retry after {retry_time, time, medium}.", - "alert.rate_limited.title": "Rate limited", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", - "announcement.announcement": "Announcement", - "autosuggest_hashtag.per_week": "{count} per week", - "boost_modal.combo": "You can press {combo} to skip this next time", - "bundle_column_error.body": "Something went wrong while loading this component.", - "bundle_column_error.retry": "Try again", - "bundle_column_error.title": "Network error", - "bundle_modal_error.close": "Close", - "bundle_modal_error.message": "Something went wrong while loading this component.", - "bundle_modal_error.retry": "Try again", - "column.blocks": "Blocked users", - "column.bookmarks": "Bookmarks", - "column.community": "Local timeline", - "column.direct": "Direct messages", - "column.directory": "Browse profiles", - "column.domain_blocks": "Blocked domains", - "column.favourites": "Favourites", - "column.follow_requests": "Follow requests", - "column.home": "Home", - "column.lists": "Lists", - "column.mutes": "Muted users", - "column.notifications": "Notifications", - "column.pins": "Pinned toot", - "column.public": "Federated timeline", - "column_back_button.label": "Back", - "column_header.hide_settings": "Hide settings", - "column_header.moveLeft_settings": "Move column to the left", - "column_header.moveRight_settings": "Move column to the right", - "column_header.pin": "Pin", - "column_header.show_settings": "Show settings", - "column_header.unpin": "Unpin", - "column_subheading.settings": "Settings", - "community.column_settings.local_only": "Local only", - "community.column_settings.media_only": "Media only", - "community.column_settings.remote_only": "Remote only", - "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.", - "compose_form.direct_message_warning_learn_more": "Learn more", - "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", - "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", - "compose_form.lock_disclaimer.lock": "locked", - "compose_form.placeholder": "What is on your mind?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", - "compose_form.publish": "Toot", + "account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.", + "account.follows_you": "شوێنکەوتووەکانت", + "account.hide_reblogs": "داشاردنی بووستەکان Ù„Û• @{name}", + "account.last_status": "دوایین چالاکی", + "account.link_verified_on": "خاوەنداریەتی ئەم لینکە Ù„Û• {date} Ú†ÛŽÚ© کراوە", + "account.locked_info": "تایبەتمەندی ئەم هەژمارەیە ڕیکخراوە بۆ قوÙڵدراوە. خاوەنەکە بە دەستی پێداچوونەوە دەکات Ú©Û• Ú©ÛŽ دەتوانێت شوێنیان بکەوێت.", + "account.media": "میدیا", + "account.mention": "ئاماژە @{name}", + "account.moved_to": "{name} گواسترایەوە بۆ:", + "account.mute": "بێدەنگکردن @{name}", + "account.mute_notifications": "هۆشیارکەرەوەکان لاببە Ù„Û• @{name}", + "account.muted": "بێ دەنگ", + "account.never_active": "هەرگیز", + "account.posts": "توتس", + "account.posts_with_replies": "توتس Ùˆ وەڵامەکان", + "account.report": "گوزارشت @{name}", + "account.requested": "چاوەڕێی ڕەزامەندین. کرتە بکە بۆ هەڵوەشاندنەوەی داواکاری شوێنکەوتن", + "account.share": "Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ @{name} هاوبەش بکە", + "account.show_reblogs": "پیشاندانی بەرزکردنەوەکان Ù„Û• @{name}", + "account.statuses_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.unblock": "@{name} لاببە", + "account.unblock_domain": "کردنەوەی دۆمەینی {domain}", + "account.unendorse": "تایبەتمەندی لەسەر Ù¾Ø±Û†ÙØ§ÛŒÙ„Û•Ú©Û• نیە", + "account.unfollow": "بەدوادانەچو", + "account.unmute": "بێدەنگکردنی @{name}", + "account.unmute_notifications": "بێدەنگکردنی هۆشیارییەکان Ù„Û• @{name}", + "account_note.placeholder": "کرتەبکە بۆ زیادکردنی تێبینی", + "alert.rate_limited.message": "تکایە هەوڵبدەرەوە دوای {retry_time, time, medium}.", + "alert.rate_limited.title": "Ú•ÛŽÚ˜Û•ÛŒ سنووردار", + "alert.unexpected.message": "هەڵەیەکی چاوەڕوان نەکراو ڕوویدا.", + "alert.unexpected.title": "ØªÛ•ØØØ!", + "announcement.announcement": "بانگەواز", + "autosuggest_hashtag.per_week": "{count} Ù‡Û•Ø±Ù‡Û•ÙØªÛ•", + "boost_modal.combo": "دەتوانیت دەست بنێی بە سەر {combo} بۆ بازدان Ù„Û• جاری داهاتوو", + "bundle_column_error.body": "هەڵەیەک ڕوویدا لەکاتی بارکردنی ئەم پێکهاتەیە.", + "bundle_column_error.retry": "دووبارە هەوڵبدە", + "bundle_column_error.title": "Ù‡Û•ÚµÙŠÛŒ تۆڕ", + "bundle_modal_error.close": "داخستن", + "bundle_modal_error.message": "هەڵەیەک ڕوویدا لەکاتی بارکردنی ئەم پێکهاتەیە.", + "bundle_modal_error.retry": "دووبارە تاقی بکەوە", + "column.blocks": "بەکارهێنەرە بلۆککراوەکان", + "column.bookmarks": "نیشانەکان", + "column.community": "Ù‡ÛŽÚµÛŒ کاتی ناوخۆیی", + "column.direct": "نامە ڕاستەوخۆکان", + "column.directory": "گەڕان Ù„Û• Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکان", + "column.domain_blocks": "دۆمەینە داخراوەکان", + "column.favourites": "دڵخوازترینەکان", + "column.follow_requests": "بەدواداچوی داواکاریەکان بکە", + "column.home": "سەرەتا", + "column.lists": "پێرست", + "column.mutes": "بێدەنگکردنی بەکارهێنەران", + "column.notifications": "ئاگادارییەکان", + "column.pins": "تووتسی چەسپاو", + "column.public": "نووسراوەکانی هەمووشوێنێک", + "column_back_button.label": "دواوە", + "column_header.hide_settings": "شاردنەوەی ڕێکخستنەکان", + "column_header.moveLeft_settings": "ستوون بگوێزەرەوە بۆ لای Ú†Û•Ù¾", + "column_header.moveRight_settings": "جوولاندنی ئەستوون بۆ لای ڕاست", + "column_header.pin": "سنجاق", + "column_header.show_settings": "نیشاندانی رێکخستنەکان", + "column_header.unpin": "سنجاق نەکردن", + "column_subheading.settings": "رێکخستنەکان", + "community.column_settings.local_only": "تەنها خۆماڵی", + "community.column_settings.media_only": "تەنها میدیا", + "community.column_settings.remote_only": "تەنها بۆ دوور", + "compose_form.direct_message_warning": "ئەم توتە تەنیا بۆ بەکارهێنەرانی ناوبراو دەنێردرێت.", + "compose_form.direct_message_warning_learn_more": "زیاتر Ùێربه", + "compose_form.hashtag_warning": "ئەم توتە Ù„Û• ژێر هیچ هاشتاگییەک دا ناکرێت ÙˆÛ•Ú© ئەوەی Ù„Û• لیستەکەدا نەریزراوە. تەنها توتی گشتی دەتوانرێت بە هاشتاگی بگەڕێت.", + "compose_form.lock_disclaimer": "هەژمێرەکەی Ù„Û• ØØ§ÚµÛ•تی {locked}. هەر کەسێک دەتوانێت شوێنت بکەوێت بۆ پیشاندانی بابەتەکانی تەنها دوایخۆی.", + "compose_form.lock_disclaimer.lock": "Ù‚ÙÚµ دراوە", + "compose_form.placeholder": "Ú†ÛŒ Ù„Û• مێشکتدایە?", + "compose_form.poll.add_option": "زیادکردنی هەڵبژاردەیەک", + "compose_form.poll.duration": "ماوەی ڕاپرسی", + "compose_form.poll.option_placeholder": "هەڵبژاردن {number}", + "compose_form.poll.remove_option": "لابردنی ئەم هەڵبژاردەیە", + "compose_form.poll.switch_to_multiple": "ڕاپرسی بگۆڕە بۆ ڕێگەدان بە چەند هەڵبژاردنێک", + "compose_form.poll.switch_to_single": "گۆڕینی ڕاپرسی بۆ ڕێگەدان بە تاکە هەڵبژاردنێک", + "compose_form.publish": "توت", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", - "compose_form.spoiler_placeholder": "Write your warning here", - "confirmation_modal.cancel": "Cancel", - "confirmations.block.block_and_report": "Block & Report", - "confirmations.block.confirm": "Block", - "confirmations.block.message": "Are you sure you want to block {name}?", - "confirmations.delete.confirm": "Delete", - "confirmations.delete.message": "Are you sure you want to delete this status?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", - "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", - "confirmations.logout.confirm": "Log out", - "confirmations.logout.message": "Are you sure you want to log out?", - "confirmations.mute.confirm": "Mute", - "confirmations.mute.explanation": "This will hide posts from them and posts mentioning them, but it will still allow them to see your posts and follow you.", - "confirmations.mute.message": "Are you sure you want to mute {name}?", - "confirmations.redraft.confirm": "Delete & redraft", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.", - "confirmations.reply.confirm": "Reply", - "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", - "confirmations.unfollow.confirm": "Unfollow", - "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", - "conversation.delete": "Delete conversation", - "conversation.mark_as_read": "Mark as read", - "conversation.open": "View conversation", - "conversation.with": "With {names}", - "directory.federated": "From known fediverse", - "directory.local": "From {domain} only", - "directory.new_arrivals": "New arrivals", - "directory.recently_active": "Recently active", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", - "emoji_button.activity": "Activity", - "emoji_button.custom": "Custom", - "emoji_button.flags": "Flags", - "emoji_button.food": "Food & Drink", - "emoji_button.label": "Insert emoji", - "emoji_button.nature": "Nature", - "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ â”»â”â”»", - "emoji_button.objects": "Objects", - "emoji_button.people": "People", - "emoji_button.recent": "Frequently used", - "emoji_button.search": "Search...", - "emoji_button.search_results": "Search results", - "emoji_button.symbols": "Symbols", - "emoji_button.travel": "Travel & Places", - "empty_column.account_timeline": "No toots here!", - "empty_column.account_unavailable": "Profile unavailable", - "empty_column.blocks": "You haven't blocked any users yet.", - "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", - "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", - "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", - "empty_column.domain_blocks": "There are no blocked domains yet.", - "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", - "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", - "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", - "empty_column.hashtag": "There is nothing in this hashtag yet.", - "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", - "empty_column.home.public_timeline": "the public timeline", - "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", - "empty_column.mutes": "You haven't muted any users yet.", - "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", - "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", - "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", - "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", - "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", - "errors.unexpected_crash.report_issue": "Report issue", - "follow_request.authorize": "Authorize", - "follow_request.reject": "Reject", - "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", - "getting_started.developers": "Developers", - "getting_started.directory": "Profile directory", - "getting_started.documentation": "Documentation", - "getting_started.heading": "Getting started", - "getting_started.invite": "Invite people", - "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", - "getting_started.security": "Security", - "getting_started.terms": "Terms of service", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "hashtag.column_settings.select.no_options_message": "No suggestions found", - "hashtag.column_settings.select.placeholder": "Enter hashtags…", - "hashtag.column_settings.tag_mode.all": "All of these", - "hashtag.column_settings.tag_mode.any": "Any of these", - "hashtag.column_settings.tag_mode.none": "None of these", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", - "home.column_settings.basic": "Basic", - "home.column_settings.show_reblogs": "Show boosts", - "home.column_settings.show_replies": "Show replies", - "home.hide_announcements": "Hide announcements", - "home.show_announcements": "Show announcements", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", - "introduction.federation.federated.headline": "Federated", - "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", - "introduction.interactions.action": "Finish toot-orial!", - "introduction.interactions.favourite.headline": "Favourite", - "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", - "introduction.interactions.reblog.headline": "Boost", - "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", - "keyboard_shortcuts.back": "to navigate back", - "keyboard_shortcuts.blocked": "to open blocked users list", - "keyboard_shortcuts.boost": "to boost", - "keyboard_shortcuts.column": "to focus a status in one of the columns", - "keyboard_shortcuts.compose": "to focus the compose textarea", - "keyboard_shortcuts.description": "Description", - "keyboard_shortcuts.direct": "to open direct messages column", - "keyboard_shortcuts.down": "to move down in the list", - "keyboard_shortcuts.enter": "to open status", - "keyboard_shortcuts.favourite": "to favourite", - "keyboard_shortcuts.favourites": "to open favourites list", - "keyboard_shortcuts.federated": "to open federated timeline", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.home": "to open home timeline", - "keyboard_shortcuts.hotkey": "Hotkey", - "keyboard_shortcuts.legend": "to display this legend", - "keyboard_shortcuts.local": "to open local timeline", - "keyboard_shortcuts.mention": "to mention author", - "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", - "keyboard_shortcuts.notifications": "to open notifications column", - "keyboard_shortcuts.open_media": "to open media", - "keyboard_shortcuts.pinned": "to open pinned toots list", - "keyboard_shortcuts.profile": "to open author's profile", - "keyboard_shortcuts.reply": "to reply", - "keyboard_shortcuts.requests": "to open follow requests list", - "keyboard_shortcuts.search": "to focus search", - "keyboard_shortcuts.spoilers": "to show/hide CW field", - "keyboard_shortcuts.start": "to open \"get started\" column", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", - "keyboard_shortcuts.toot": "to start a brand new toot", - "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", - "keyboard_shortcuts.up": "to move up in the list", - "lightbox.close": "Close", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lightbox.view_context": "View context", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.delete": "Delete list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "compose_form.sensitive.hide": "نیشانکردنی میدیا ÙˆÛ•Ú© هەستیار", + "compose_form.sensitive.marked": "وادەی کۆتایی", + "compose_form.sensitive.unmarked": "میدیا ÙˆÛ•Ú© هەستیار نیشان نەکراوە", + "compose_form.spoiler.marked": "دەق Ù„Û• پشت ئاگاداریدا شاراوەتەوە", + "compose_form.spoiler.unmarked": "دەق شاراوە نییە", + "compose_form.spoiler_placeholder": "ئاگاداریەکەت لێرە بنووسە", + "confirmation_modal.cancel": "هەڵوەشاندنەوه", + "confirmations.block.block_and_report": "بلۆک & گوزارشت", + "confirmations.block.confirm": "بلۆک", + "confirmations.block.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت {name} بلۆک بکەیت?", + "confirmations.delete.confirm": "سڕینەوە", + "confirmations.delete.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت ئەم توتە بسڕیتەوە?", + "confirmations.delete_list.confirm": "سڕینەوە", + "confirmations.delete_list.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت بە هەمیشەیی ئەم لیستە بسڕیتەوە?", + "confirmations.domain_block.confirm": "بلۆککردنی هەموو دۆمەینەکە", + "confirmations.domain_block.message": "ئایا بەڕاستی، بەڕاستی تۆ دەتەوێت هەموو {domain} بلۆک بکەیت؟ Ù„Û• زۆربەی ØØ§ÚµÛ•تەکاندا چەند بلۆکێکی ئامانجدار یان بێدەنگەکان پێویست Ùˆ پەسەندن. تۆ ناوەڕۆک ÛŽÚ© نابینیت Ù„Û• دۆمەینەکە Ù„Û• هیچ Ù‡ÛŽÚµÛŒ کاتی گشتی یان ئاگانامەکانت. شوێنکەوتوانی تۆ Ù„Û•Ùˆ دۆمەینەوە لادەبرێن.", + "confirmations.logout.confirm": "چوونە دەرەوە", + "confirmations.logout.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت بچیتە دەرەوە?", + "confirmations.mute.confirm": "بێدەنگ", + "confirmations.mute.explanation": "ئەمەش دەبێتە Ù‡Û†ÛŒ شاردنەوەی پۆستەکان یان ئەو بابەتانەی Ú©Û• ئاماژەیان Ù¾ÛŽ دەکات ØŒ بەڵام هێشتا ڕێگەیان Ù¾ÛŽ دەدات Ú©Û• پۆستەکانتان ببینن Ùˆ شوێنتان بکەون.", + "confirmations.mute.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت بیلێیت {name}?", + "confirmations.redraft.confirm": "سڕینەوە & دووبارە ڕەشکردنەوە", + "confirmations.redraft.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت ئەم توتە بسڕیتەوە Ùˆ دووبارە دایبنووسیتەوە؟ دڵخوازەکان Ùˆ بەرزکردنەوەکان وون دەبن، Ùˆ وەڵامەکان بۆ پۆستە ڕەسەنەکە هەتیو دەبن.", + "confirmations.reply.confirm": "وەڵام", + "confirmations.reply.message": "وەڵامدانەوە ئێستا ئەو نامەیە ÛŒ Ú©Û• تۆ ئێستا دایڕشتووە، دەنووسێتەوە. ئایا دڵنیایت Ú©Û• دەتەوێت بەردەوام بیت?", + "confirmations.unfollow.confirm": "بەدوادانەچو", + "confirmations.unfollow.message": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت پەیڕەوی {name}?", + "conversation.delete": "سڕینەوەی Ú¯ÙØªÙˆÚ¯Û†", + "conversation.mark_as_read": "نیشانەکردن ÙˆÛ•Ú© خوێندراوە", + "conversation.open": "نیشاندان Ú¯ÙØªÙˆÚ¯Û†", + "conversation.with": "Ù„Û•Ú¯Û•Úµ{names}", + "directory.federated": "Ù„Û• ڕاژەکانی ناسراو", + "directory.local": "تەنها Ù„Û• {domain}", + "directory.new_arrivals": "تازە گەیشتنەکان", + "directory.recently_active": "بەم دواییانە چالاکە", + "embed.instructions": "ئەم توتە بنچین بکە لەسەر وێب سایتەکەت بە کۆپیکردنی کۆدەکەی خوارەوە.", + "embed.preview": "ئەمە ئەو شتەیە Ú©Û• Ù„Û• Ø´ÛŽÙˆÛ•ÛŒ خۆی دەچێت:", + "emoji_button.activity": "چالاکی", + "emoji_button.custom": "ئاسایی", + "emoji_button.flags": "ئاڵاکان", + "emoji_button.food": "خواردن& خواردنەوە", + "emoji_button.label": "ئیمۆجی بکەنێو", + "emoji_button.nature": "سروشت", + "emoji_button.not_found": "بێ ئیمۆجی! (╯°□°)╯( â”»â”â”»", + "emoji_button.objects": "ئامانجەکان", + "emoji_button.people": "خەڵک", + "emoji_button.recent": "زۆرجار بەکارهێنراوە", + "emoji_button.search": "گەڕان...", + "emoji_button.search_results": "ئەنجامەکانی گەڕان", + "emoji_button.symbols": "هێماکان", + "emoji_button.travel": "گەشت & شوێنەکان", + "empty_column.account_suspended": "Account suspended", + "empty_column.account_timeline": "لێرە هیچ توتەک نییە!", + "empty_column.account_unavailable": "Ù¾Ø±Û†ÙØ§ÛŒÙ„ بەردەست نیە", + "empty_column.blocks": "تۆ هێشتا هیچ بەکارهێنەرێکت بلۆک نەکردووە.", + "empty_column.bookmarked_statuses": "تۆ هێشتا هیچ توتێکی دیاریکراوت نیە کاتێک نیشانەیەک نیشان دەکەیت، لێرە دەرئەکەویت.", + "empty_column.community": "Ù‡ÛŽÚµÛŒ کاتی ناوخۆیی بەتاڵە. شتێک بە ئاشکرا بنووسە بۆ ئەوەی تۆپەکە بسووڕێت!", + "empty_column.direct": "تۆ هیچ نامەی ڕاستەوخۆت نیە تا ئێستا. کاتێک دانەیەک دەنێریت یان وەرت دەگرێت، لێرە پیشان دەدات.", + "empty_column.domain_blocks": "هێشتا هیچ دۆمەینێکی بلۆک کراو نییە.", + "empty_column.favourited_statuses": "تۆ هێشتا هیچ توتێکی دڵخوازت نییە، کاتێک ØÛ•زت Ù„Û• دانەیەکی باشە، لێرە دەرئەکەویت.", + "empty_column.favourites": "کەس ئەم توتەی دڵخواز نەکردووە،کاتێک کەسێک وا بکات، لێرە دەرئەکەون.", + "empty_column.follow_requests": "تۆ هێشتا هیچ داواکارییەکی بەدواداچووت نیە. کاتێک یەکێکت بۆ هات، لێرە دەرئەکەویت.", + "empty_column.hashtag": "هێشتا هیچ شتێک Ù„Û•Ù… هاشتاگەدا نییە.", + "empty_column.home": "تایم لاینی ماڵەوەت بەتاڵە! سەردانی {public} بکە یان گەڕان بەکاربێنە بۆ دەستپێکردن Ùˆ بینینی بەکارهێنەرانی تر.", + "empty_column.home.public_timeline": "Ù‡ÛŽÚµÛŒ کاتی گشتی", + "empty_column.list": "هێشتا هیچ شتێک Ù„Û•Ù… لیستەدا نییە. کاتێک ئەندامانی ئەم لیستە دەنگی نوێ بڵاودەکەن، لێرە دەردەکەون.", + "empty_column.lists": "تۆ هێشتا هیچ لیستت دروست نەکردووە، کاتێک دانەیەک دروست دەکەیت، لێرە پیشان دەدرێت.", + "empty_column.mutes": "تۆ هێشتا هیچ بەکارهێنەرێکت بێدەنگ نەکردووە.", + "empty_column.notifications": "تۆ هێشتا هیچ ئاگانامێکت نیە. چالاکی Ù„Û•Ú¯Û•Úµ کەسانی دیکە بکە بۆ دەستپێکردنی Ú¯ÙØªÙˆÚ¯Û†Ú©Û•.", + "empty_column.public": "لێرە هیچ نییە! شتێک بە ئاشکرا بنووسە(بەگشتی)ØŒ یان بە دەستی شوێن بەکارهێنەران بکەوە Ù„Û• ڕاژەکانی ترەوە بۆ پڕکردنەوەی", + "error.unexpected_crash.explanation": "بەهۆی بوونی Ú©ÛŽØ´Û• Ù„Û• کۆدەکەمان یان Ú©ÛŽØ´Û•ÛŒ گونجانی وێبگەڕەکە، ئەم لاپەڕەیە بە دروستی پیشان نادرێت.", + "error.unexpected_crash.explanation_addons": "ئەم لاپەڕەیە ناتوانرێت بە دروستی پیشان بدرێت. ئەم هەڵەیە لەوانەیە بەهۆی ئامێری وەرگێڕانی خۆکار یان زیادکراوی وێبگەڕەوە بێت.", + "error.unexpected_crash.next_steps": "هەوڵدە لاپەڕەکە تازە بکەوە. ئەگەر ئەمە یارمەتیدەر نەبوو، لەوانەیە هێشتا بتوانیت ماستۆدۆن بەکاربێنیت Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ وێبگەڕەکەیان کاربەرنامەی ڕەسەن.", + "error.unexpected_crash.next_steps_addons": "هەوڵدە لەکاریان بخەیت Ùˆ لاپەڕەکە تازە بکەوە. ئەگەر ئەمە یارمەتیدەر نەبوو، لەوانەیە هێشتا بتوانیت ماستۆدۆن بەکاربێنیت Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ وێبگەڕەکانی دیکە یان نەرمەکالاکانی ئەسڵی.", + "errors.unexpected_crash.copy_stacktrace": "کۆپیکردنی ستێکتراسی بۆ کلیپ بۆرد", + "errors.unexpected_crash.report_issue": "Ú©ÛŽØ´Û•ÛŒ گوزارشت", + "follow_request.authorize": "ده‌سه‌ڵاتپێدراو", + "follow_request.reject": "ڕەتکردنەوە", + "follow_requests.unlocked_explanation": "هەرچەندە هەژمارەکەت داخراو نییە، ستاÙÛŒ {domain} وا بیریان کردەوە Ú©Û• لەوانەیە بتانەوێت پێداچوونەوە بە داواکاریەکانی ئەم هەژمارەدا بکەن بە دەستی.", + "generic.saved": "پاشکەوتکرا", + "getting_started.developers": "پەرەپێدەران", + "getting_started.directory": "Ù¾Û•Ú•Û•ÛŒ Ù¾Ø±Û†ÙØ§ÛŒÙ„", + "getting_started.documentation": "بەڵگەنامە", + "getting_started.heading": "دەست پێکردن", + "getting_started.invite": "بانگهێشتکردنی خەڵک", + "getting_started.open_source_notice": "ماستۆدۆن نەرمەکالایەکی سەرچاوەی کراوەیە. دەتوانیت بەشداری بکەیت یان گوزارشت بکەیت لەسەر کێشەکانی Ù„Û• Ù¾Û•Ú•Û•ÛŒ گیتهاب {github}.", + "getting_started.security": "ڕێکخستنەکانی هەژمارە", + "getting_started.terms": "مەرجەکانی خزمەتگوزاری", + "hashtag.column_header.tag_mode.all": "Ùˆ {additional}", + "hashtag.column_header.tag_mode.any": "یا {additional}", + "hashtag.column_header.tag_mode.none": "بەبێ {additional}", + "hashtag.column_settings.select.no_options_message": "هیچ پێشنیارێک نەدۆزرایەوە", + "hashtag.column_settings.select.placeholder": "هاشتاگی تێبنووسە…", + "hashtag.column_settings.tag_mode.all": "هەموو ئەمانە", + "hashtag.column_settings.tag_mode.any": "هەر کام لەمانە", + "hashtag.column_settings.tag_mode.none": "هیچ کام لەمانە", + "hashtag.column_settings.tag_toggle": "تاگی زیادە ÛŒ ئەم ستوونە لەخۆ بنووسە", + "home.column_settings.basic": "بنەڕەتی", + "home.column_settings.show_reblogs": "پیشاندانی بەهێزکردن", + "home.column_settings.show_replies": "وەڵامدانەوەکان پیشان بدە", + "home.hide_announcements": "شاردنەوەی راگەیەنراوەکان", + "home.show_announcements": "پیشاندانی راگەیەنراوەکان", + "intervals.full.days": "{number, plural, one {# Ú•Û†Ú˜} other {# Ú•Û†Ú˜Û•Ú©}}", + "intervals.full.hours": "{number, plural, one {# کات} other {# کات}}", + "intervals.full.minutes": "{number, plural, one {# خولەک} other {# خولەک}}", + "introduction.federation.action": "داهاتوو", + "introduction.federation.federated.headline": "گشتی", + "introduction.federation.federated.text": "نووسراوە گشتیەکان Ù„Û• خزمەتگوزاریەکانی تری جیهانی دەرئەکەون Ù„Û• Ù‡ÛŽÚµÛŒ گشتی.", + "introduction.federation.home.headline": "سەرەتا", + "introduction.federation.home.text": "ئەو بابەتانەی Ú©Û• بەشوێنیان دەکەویت Ù„Û• Ù¾Û•Ú•Û•ÛŒ ژوورەکەت دەردەکەوێت. دەتوانیت شوێن هەموو کەسێک بکەویت لەسەر هەر ڕاژەیەک!", + "introduction.federation.local.headline": "ناوخۆیی", + "introduction.federation.local.text": "نووسراوە گشتیەکان Ù„Û• خەڵک لەسەر هەمان ڕاژە ÙˆÛ•Ú© تۆ دەردەکەون Ù„Û• Ù‡ÛŽÚµÛŒ کاتی ناوخۆیی.", + "introduction.interactions.action": "خوێندنی تەواوبکە!", + "introduction.interactions.favourite.headline": "دڵخواز", + "introduction.interactions.favourite.text": "دەتوانیت پاشترتوتێک پاشەکەوت بکەیت، با نووسەر بزانێت Ú©Û• تۆ ØÛ•زت Ù„ÛŽ بوو، بە ئارەزووی خۆت.", + "introduction.interactions.reblog.headline": "بەهێزکردن", + "introduction.interactions.reblog.text": "دەتوانیت دەنگی کەسانی تر هاوبەش بکەیت Ù„Û•Ú¯Û•Úµ شوێنکەوتوانی خۆت بە بەهێزکردنیان.", + "introduction.interactions.reply.headline": "وەڵام", + "introduction.interactions.reply.text": "دەتوانیت وەڵامی کەسانی تر Ùˆ توتەکانی خۆت بدەوە، Ú©Û• Ù„Û• Ú¯ÙØªÙˆÚ¯Û†ÛŒÛ•کدا بە یەکەوە زنجیریان دەکات.", + "introduction.welcome.action": "با بڕۆین!", + "introduction.welcome.headline": "هەنگاوی یەکەم", + "introduction.welcome.text": "بەخێربێیت بۆتۆڕەکۆمەڵەییەکانی چربووە! Ù„Û• چەند ساتێکی کەمدا دەتوانیت پەیامەکان پەخش بکەیت Ùˆ Ù„Û•Ú¯Û•Úµ هاوڕێکانت Ù„Û• ناو چەندین جۆر Ù„Û• ڕاژەکان قسە بکەیت.. بەڵام ئەم ڕاژانە، {domain}ØŒ جیاوزە Ù„Û•Ú¯Û•Úµ ئەوانی دیکە بۆ ئەوە Ú©Û• میوانداری Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت دەکان، بۆیە ناوەکەیت لەبیربێت.", + "keyboard_shortcuts.back": "بۆ گەڕانەوە", + "keyboard_shortcuts.blocked": "بۆ کردنەوەی لیستی بەکارهێنەرە بلۆککراوەکان", + "keyboard_shortcuts.boost": "بۆ بەهێزکردن", + "keyboard_shortcuts.column": "بۆ ئەوەی تیشک بخاتە سەر توتێک Ù„Û• یەکێک Ù„Û• ستوونەکان", + "keyboard_shortcuts.compose": "بۆ سەرنجدان بە نووسینی ناوچەی دەق", + "keyboard_shortcuts.description": "وه‌سÙ", + "keyboard_shortcuts.direct": "بۆ کردنەوەی ستوونی نامە ڕاستەوخۆکان", + "keyboard_shortcuts.down": "بۆ چوونە خوارەوە Ù„Û• لیستەکەدا", + "keyboard_shortcuts.enter": "بۆ کردنەوەی توت", + "keyboard_shortcuts.favourite": "بۆ دڵخواز", + "keyboard_shortcuts.favourites": "بۆ کردنەوەی لیستی دڵخوازەکان", + "keyboard_shortcuts.federated": "بۆ کردنەوەی نووسراوەکانی هەمووشوێن", + "keyboard_shortcuts.heading": "قه‌دبڕەکانی تەختەکلیل", + "keyboard_shortcuts.home": "بۆ کردنەوەی Ù‡ÛŽÚµÛŒ کاتی ماڵەوە", + "keyboard_shortcuts.hotkey": "هۆتکەی", + "keyboard_shortcuts.legend": "بۆ نیشاندانی ئەم نیشانە", + "keyboard_shortcuts.local": "بۆ کردنەوەی نووسراوەکانی خۆماڵی", + "keyboard_shortcuts.mention": "Ù†Û† ناوبردن Ù„Û• نووسەر", + "keyboard_shortcuts.muted": "بۆ کردنەوەی پێرستی بەکارهێنەرانی بێدەنگ", + "keyboard_shortcuts.my_profile": "بۆ کردنەوەی Ù¾Ø±Û†ÙØ§ÛŒÚµ", + "keyboard_shortcuts.notifications": "بۆ کردنەوەی ستوونی ئاگانامەکان", + "keyboard_shortcuts.open_media": "بۆ کردنەوەی میدیا", + "keyboard_shortcuts.pinned": "بۆ کردنەوەی لیستی توتەکانی چەسپێنراو", + "keyboard_shortcuts.profile": "بۆ کردنەوەی Ù¾Ø±Û†ÙØ§ÛŒÚµÛŒ نووسەر", + "keyboard_shortcuts.reply": "بۆ وەڵامدانەوە", + "keyboard_shortcuts.requests": "بۆ کردنەوەی لیستی داواکاریەکانی بەدوادا", + "keyboard_shortcuts.search": "بۆ جەختکردن لەسەر گەڕان", + "keyboard_shortcuts.spoilers": "بۆ پیشاندان/شاردنەوەی خانەی CW", + "keyboard_shortcuts.start": "بۆ کردنەوەی ستوونی \"دەست پێبکە\"", + "keyboard_shortcuts.toggle_hidden": "بۆ پیشاندان/شاردنەوەی دەق Ù„Û• پشت CW", + "keyboard_shortcuts.toggle_sensitivity": "بۆ پیشاندان/شاردنەوەی میدیا", + "keyboard_shortcuts.toot": "بۆ دەست کردن بە براندێکی تازە", + "keyboard_shortcuts.unfocus": "بۆ دروستکردنی ناوچەی دەق/گەڕان", + "keyboard_shortcuts.up": "بۆ ئەوەی Ù„Û• لیستەکەدا بڕۆیت", + "lightbox.close": "دابخە", + "lightbox.compress": "سندوقی نیشاندانی ÙˆÛŽÙ†Û• بپەستێنە", + "lightbox.expand": "ÙØ±Ø§ÙˆØ§Ù†Ú©Ø±Ø¯Ù†ÛŒ سندوقی بینینی ÙˆÛŽÙ†Û•", + "lightbox.next": "داهاتوو", + "lightbox.previous": "پێشوو", + "lists.account.add": "زیادکردن بۆ لیست", + "lists.account.remove": "لابردن Ù„Û• لیست", + "lists.delete": "سڕینەوەی لیست", + "lists.edit": "دەستکاری لیست", + "lists.edit.submit": "گۆڕینی ناونیشان", + "lists.new.create": "زیادکردنی لیست", + "lists.new.title_placeholder": "ناونیشانی لیستی نوێ", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "پیشاندانی وەڵامەکان بۆ:", + "lists.search": "بگەڕێ لەناو ئەو کەسانەی Ú©Û• شوێنیان کەوتویت", + "lists.subheading": "لیستەکانت", "load_pending": "{count, plural, one {# new item} other {# new items}}", - "loading_indicator.label": "Loading...", - "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", - "missing_indicator.label": "Not found", - "missing_indicator.sublabel": "This resource could not be found", - "mute_modal.hide_notifications": "Hide notifications from this user?", - "navigation_bar.apps": "Mobile apps", - "navigation_bar.blocks": "Blocked users", - "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.community_timeline": "Local timeline", - "navigation_bar.compose": "Compose new toot", - "navigation_bar.direct": "Direct messages", - "navigation_bar.discover": "Discover", - "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.edit_profile": "Edit profile", - "navigation_bar.favourites": "Favourites", - "navigation_bar.filters": "Muted words", - "navigation_bar.follow_requests": "Follow requests", - "navigation_bar.follows_and_followers": "Follows and followers", - "navigation_bar.info": "About this server", - "navigation_bar.keyboard_shortcuts": "Hotkeys", - "navigation_bar.lists": "Lists", - "navigation_bar.logout": "Logout", - "navigation_bar.mutes": "Muted users", - "navigation_bar.personal": "Personal", - "navigation_bar.pins": "Pinned toots", - "navigation_bar.preferences": "Preferences", - "navigation_bar.public_timeline": "Federated timeline", - "navigation_bar.security": "Security", - "notification.favourite": "{name} favourited your status", - "notification.follow": "{name} followed you", - "notification.follow_request": "{name} has requested to follow you", - "notification.mention": "{name} mentioned you", - "notification.own_poll": "Your poll has ended", - "notification.poll": "A poll you have voted in has ended", - "notification.reblog": "{name} boosted your status", - "notifications.clear": "Clear notifications", - "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", - "notifications.column_settings.alert": "Desktop notifications", - "notifications.column_settings.favourite": "Favourites:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", - "notifications.column_settings.follow": "New followers:", - "notifications.column_settings.follow_request": "New follow requests:", - "notifications.column_settings.mention": "Mentions:", - "notifications.column_settings.poll": "Poll results:", - "notifications.column_settings.push": "Push notifications", - "notifications.column_settings.reblog": "Boosts:", - "notifications.column_settings.show": "Show in column", - "notifications.column_settings.sound": "Play sound", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Boosts", - "notifications.filter.favourites": "Favourites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", - "notifications.filter.polls": "Poll results", - "notifications.group": "{count} notifications", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_people": "{count, plural, one {# person} other {# people}}", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll.voted": "You voted for this answer", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", - "privacy.change": "Adjust status privacy", - "privacy.direct.long": "Visible for mentioned users only", - "privacy.direct.short": "Direct", - "privacy.private.long": "Visible for followers only", - "privacy.private.short": "Followers-only", - "privacy.public.long": "Visible for all, shown in public timelines", - "privacy.public.short": "Public", - "privacy.unlisted.long": "Visible for all, but not in public timelines", - "privacy.unlisted.short": "Unlisted", - "refresh": "Refresh", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", - "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", - "relative_time.just_now": "now", - "relative_time.minutes": "{number}m", - "relative_time.seconds": "{number}s", - "relative_time.today": "today", - "reply_indicator.cancel": "Cancel", - "report.forward": "Forward to {target}", - "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", - "report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:", - "report.placeholder": "Additional comments", - "report.submit": "Submit", - "report.target": "Report {target}", - "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "status", - "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", - "search_popout.tips.user": "user", - "search_results.accounts": "People", - "search_results.hashtags": "Hashtags", - "search_results.statuses": "Toots", - "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", - "search_results.total": "{count, number} {count, plural, one {result} other {results}}", - "status.admin_account": "Open moderation interface for @{name}", - "status.admin_status": "Open this status in the moderation interface", - "status.block": "Block @{name}", - "status.bookmark": "Bookmark", - "status.cancel_reblog_private": "Unboost", - "status.cannot_reblog": "This post cannot be boosted", - "status.copy": "Copy link to status", - "status.delete": "Delete", - "status.detailed_status": "Detailed conversation view", - "status.direct": "Direct message @{name}", - "status.embed": "Embed", - "status.favourite": "Favourite", - "status.filtered": "Filtered", - "status.load_more": "Load more", - "status.media_hidden": "Media hidden", - "status.mention": "Mention @{name}", - "status.more": "More", - "status.mute": "Mute @{name}", - "status.mute_conversation": "Mute conversation", - "status.open": "Expand this status", - "status.pin": "Pin on profile", - "status.pinned": "Pinned toot", - "status.read_more": "Read more", - "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", - "status.reblogged_by": "{name} boosted", - "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.remove_bookmark": "Remove bookmark", - "status.reply": "Reply", - "status.replyAll": "Reply to thread", - "status.report": "Report @{name}", - "status.sensitive_warning": "Sensitive content", - "status.share": "Share", - "status.show_less": "Show less", - "status.show_less_all": "Show less for all", - "status.show_more": "Show more", - "status.show_more_all": "Show more for all", - "status.show_thread": "Show thread", - "status.uncached_media_warning": "Not available", - "status.unmute_conversation": "Unmute conversation", - "status.unpin": "Unpin from profile", - "suggestions.dismiss": "Dismiss suggestion", - "suggestions.header": "You might be interested in…", - "tabs_bar.federated_timeline": "Federated", - "tabs_bar.home": "Home", - "tabs_bar.local_timeline": "Local", - "tabs_bar.notifications": "Notifications", - "tabs_bar.search": "Search", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", - "trends.trending_now": "Trending now", - "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", - "upload_area.title": "Drag & drop to upload", - "upload_button.label": "Add images, a video or an audio file", - "upload_error.limit": "File upload limit exceeded.", - "upload_error.poll": "File upload not allowed with polls.", - "upload_form.audio_description": "Describe for people with hearing loss", - "upload_form.description": "Describe for the visually impaired", - "upload_form.edit": "Edit", - "upload_form.thumbnail": "Change thumbnail", - "upload_form.undo": "Delete", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", - "upload_modal.analyzing_picture": "Analyzing picture…", - "upload_modal.apply": "Apply", - "upload_modal.choose_image": "Choose image", - "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", - "upload_modal.detect_text": "Detect text from picture", - "upload_modal.edit_media": "Edit media", - "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", - "upload_modal.preview_label": "Preview ({ratio})", - "upload_progress.label": "Uploading…", - "video.close": "Close video", - "video.download": "Download file", - "video.exit_fullscreen": "Exit full screen", - "video.expand": "Expand video", - "video.fullscreen": "Full screen", - "video.hide": "Hide video", - "video.mute": "Mute sound", - "video.pause": "Pause", - "video.play": "Play", - "video.unmute": "Unmute sound" + "loading_indicator.label": "بارکردن...", + "media_gallery.toggle_visible": "شاردنەوەی {number, plural, one {image} other {images}}", + "missing_indicator.label": "نەدۆزرایەوە", + "missing_indicator.sublabel": "ئەو سەرچاوەیە نادۆزرێتەوە", + "mute_modal.duration": "ماوە", + "mute_modal.hide_notifications": "شاردنەوەی ئاگانامەکان Ù„Û•Ù… بەکارهێنەرە؟ ", + "mute_modal.indefinite": "نادیار", + "navigation_bar.apps": "بەرنامەی مۆبایل", + "navigation_bar.blocks": "بەکارهێنەرە بلۆککراوەکان", + "navigation_bar.bookmarks": "نیشانکراوەکان", + "navigation_bar.community_timeline": "دەمنامەی ناوخۆیی", + "navigation_bar.compose": "نووسینی توتی نوێ", + "navigation_bar.direct": "نامە ڕاستەوخۆکان", + "navigation_bar.discover": "دۆزینەوە", + "navigation_bar.domain_blocks": "دۆمەینە بلۆک کراوەکان", + "navigation_bar.edit_profile": "دەستکاری Ù¾Ø±Û†ÙØ§ÛŒÙ„ بکە", + "navigation_bar.favourites": "دڵخوازەکان", + "navigation_bar.filters": "وشە کپەکان", + "navigation_bar.follow_requests": "بەدواداچوی داواکاریەکان بکە", + "navigation_bar.follows_and_followers": "شوێنکەوتوو Ùˆ شوێنکەوتوان", + "navigation_bar.info": "دەربارەی ئەم ڕاژە", + "navigation_bar.keyboard_shortcuts": "هۆتکەی", + "navigation_bar.lists": "لیستەکان", + "navigation_bar.logout": "دەرچوون", + "navigation_bar.mutes": "کپکردنی بەکارهێنەران", + "navigation_bar.personal": "کەسی", + "navigation_bar.pins": "توتی چەسپاو", + "navigation_bar.preferences": "پەسەندەکان", + "navigation_bar.public_timeline": "نووسراوەکانی هەمووشوێنێک", + "navigation_bar.security": "ئاسایش", + "notification.favourite": "{name} نووسراوەکەتی پەسەند کرد", + "notification.follow": "{name} دوای تۆ کەوت", + "notification.follow_request": "{name} داوای کردووە Ú©Û• شوێنت بکەوێت", + "notification.mention": "{name} باسی ئێوەی کرد", + "notification.own_poll": "ڕاپرسیەکەت کۆتایی هات", + "notification.poll": "ڕاپرسییەک Ú©Û• دەنگی پێداویت کۆتایی هات", + "notification.reblog": "{name} نووسراوەکەتی دووبارە توتاند", + "notification.status": "{name} تازە بڵاوکرایەوە", + "notifications.clear": "ئاگانامەکان بسڕیەوە", + "notifications.clear_confirmation": "ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت بە هەمیشەیی هەموو ئاگانامەکانت بسڕیتەوە?", + "notifications.column_settings.alert": "ئاگانامەکانی پیشانگەرر ڕومێزی", + "notifications.column_settings.favourite": "دڵخوازترین:", + "notifications.column_settings.filter_bar.advanced": "هەموو پۆلەکان پیشان بدە", + "notifications.column_settings.filter_bar.category": "شریتی پاڵێوەری خێرا", + "notifications.column_settings.filter_bar.show": "نیشاندان", + "notifications.column_settings.follow": "شوێنکەوتوانی نوێ:", + "notifications.column_settings.follow_request": "شوینکەوتنی داواکاری نوێ:", + "notifications.column_settings.mention": "ئاماژەکان:", + "notifications.column_settings.poll": "ئەنجامەکانی ڕاپرسی:", + "notifications.column_settings.push": "ئاگانامەکان پاڵ بنێ", + "notifications.column_settings.reblog": "دووبارەتوتەکان:", + "notifications.column_settings.show": "Ù„Û• ستووندا پیشان بدە", + "notifications.column_settings.sound": "لێدانی دەنگ", + "notifications.column_settings.status": "توتەکانی نوێ:", + "notifications.filter.all": "هەموو", + "notifications.filter.boosts": "دووبارەتوتەکان", + "notifications.filter.favourites": "دڵخوازەکان", + "notifications.filter.follows": "شوێنکەوتن", + "notifications.filter.mentions": "ئاماژەکان", + "notifications.filter.polls": "ئەنجامەکانی ڕاپرسی", + "notifications.filter.statuses": "نوێکردنەوەکان ئەو کەسانەی Ú©Û• پەیڕەوی دەکەیت", + "notifications.grant_permission": "Grant permission.", + "notifications.group": "{count} ئاگانامە", + "notifications.mark_as_read": "هەموو ئاگانامەکان ÙˆÛ•Ú© خوێندراوەتەوە نیشان بکە", + "notifications.permission_denied": "ناتوانرێت ئاگانامەکانی دێسکتۆپ چالاک بکرێت ÙˆÛ•Ú© ڕێپێدان ڕەتکرایەوە.", + "notifications.permission_denied_alert": "ناتوانرێت ئاگانامەکانی دێسکتۆپ چالاک بکرێت، چونکە پێشتر مۆڵەتی وێبگەڕ ڕەتکرایەوە", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "چالاککردنی ئاگانامەکانی دێسکتۆپ", + "notifications_permission_banner.how_to_control": "بۆ وەرگرتنی ئاگانامەکان کاتێک ماستۆدۆن نەکراوەیە، ئاگانامەکانی دێسکتۆپ چالاک بکە. دەتوانیت بە وردی کۆنترۆڵی جۆری کارلێکەکان بکەیت Ú©Û• ئاگانامەکانی دێسکتۆپ دروست دەکەن Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ دوگمەی {icon} لەسەرەوە کاتێک چالاک دەکرێن.", + "notifications_permission_banner.title": "هەرگیز شتێک Ù„Û• دەست مەدە", + "picture_in_picture.restore": "بیگەڕێنەوە", + "poll.closed": "دابخە", + "poll.refresh": "نوێکردنەوە", + "poll.total_people": "{count, plural, one {# خەڵک} other {# خەڵک}}", + "poll.total_votes": "{count, plural, one {# دەنگ} other {# دەنگ}}\n", + "poll.vote": "دەنگ", + "poll.voted": "تۆ دەنگت بەو وەڵامە دا", + "poll_button.add_poll": "ڕاپرسییەک زیاد بکە", + "poll_button.remove_poll": "ده‌نگدان بسڕه‌وه‌‌", + "privacy.change": "ڕێکخستنی تایبەتمەندی توت", + "privacy.direct.long": "تەنیا بۆ بەکارهێنەرانی ناوبراو", + "privacy.direct.short": "ڕاستەوخۆ", + "privacy.private.long": "بینراو تەنها بۆ شوێنکەوتوان", + "privacy.private.short": "تەنها بۆ شوێنکەوتوان", + "privacy.public.long": "بۆ هەمووان دیاربێت، Ù„Û• Ù‡ÛŽÚµÛŒ کاتی گشتی دا نیشان دەدرێت", + "privacy.public.short": "گشتی", + "privacy.unlisted.long": "بۆ هەمووان دیارە، بەڵام Ù„Û• Ù‡ÛŽÚµÛŒ کاتی گشتیدا نا", + "privacy.unlisted.short": "Ù„Û• لیست نەکراو", + "refresh": "نوێکردنەوە", + "regeneration_indicator.label": "بارکردن…", + "regeneration_indicator.sublabel": "ڕاگەیەنەری ماڵەوەت ئامادە دەکرێت!", + "relative_time.days": "{number}Ú•Û†Ú˜", + "relative_time.hours": "{number}کات", + "relative_time.just_now": "ئێستا", + "relative_time.minutes": "{number}کات", + "relative_time.seconds": "{number}کات", + "relative_time.today": "ئیمڕۆ", + "reply_indicator.cancel": "هەڵوەشاندنەوه", + "report.forward": "ناردن بۆ {target}", + "report.forward_hint": "هەژمارەکە Ù„Û• ڕاژەیەکی ترە. ڕونووسێکی نەناسراو بنێرە بۆ گوزارشت Ù„Û•ÙˆÛŽ?", + "report.hint": "گوزارشتەکە دەنێردرێت بۆ بەرپرسانی ڕاژەکەت. دەتوانیت ڕوونکردنەوەیەک Ù¾ÛŽØ´Ú©Û•Ø´ بکەیت Ú©Û• بۆچی ئەم هەژمارە Ù„Û• خوارەوە گوزارش دەکەیت:", + "report.placeholder": "سەرنجەکانی زیاتر", + "report.submit": "ناردن", + "report.target": "گوزارشتکردنی{target}", + "search.placeholder": "گەڕان", + "search_popout.search_format": "Ø´ÛŽÙˆÛ•ÛŒ گەڕانی پێشکەوتوو", + "search_popout.tips.full_text": "گەڕانێکی دەقی سادە دەتوانێت توتەکانی ئێوە Ú©Û•ØŒ نووسیوتانە،پەسەنتان کردووە، دووبارەتانکردووە، یان ئەو توتانە Ú©Û• باسی ئێوەی تێدا کراوە پەیدا دەکا. هەروەها ناوی بەکارهێنەران، ناوی پیشاندراو Ùˆ هەشتەگەکانیش Ù„Û• خۆ دەگرێت.", + "search_popout.tips.hashtag": "هەشتاگ", + "search_popout.tips.status": "توت", + "search_popout.tips.text": "دەقی سادە هەڵدەسێ بە گەڕاندنەوەی هاوتایی ناوی پیشاندان، ناوی بەکارهێنەر Ùˆ هاشتاگەکان", + "search_popout.tips.user": "بەکارهێنەر", + "search_results.accounts": "خەڵک", + "search_results.hashtags": "هەشتاگ", + "search_results.statuses": "توتەکان", + "search_results.statuses_fts_disabled": "گەڕانی توتەکان بە ناوەڕۆکیان لەسەر ئەم ڕاژەی ماستۆدۆن چالاک نەکراوە.", + "search_results.total": "{count, number} {count, plural, one {دەرئەنجام} other {دەرئەنجام}}", + "status.admin_account": "کردنەوەی میانڕەوی بەڕێوەبەر بۆ @{name}", + "status.admin_status": "ئەم توتە بکەوە Ù„Û• ناو ڕووکاری بەڕیوەبەر", + "status.block": "بلۆکی @{name}", + "status.bookmark": "نیشانه", + "status.cancel_reblog_private": "بێبەهێزکردن", + "status.cannot_reblog": "ئەم بابەتە ناتوانرێت بەرزبکرێتەوە", + "status.copy": "ڕوونووسی بەستەر بۆ توت", + "status.delete": "سڕینەوە", + "status.detailed_status": "ڕوانگەی Ú¯ÙØªÙˆÚ¯Û† بە وردەکاری", + "status.direct": "پەیامی ڕاستەوخۆ @{name}", + "status.embed": "نیشتەجێ بکە", + "status.favourite": "دڵخواز", + "status.filtered": "پاڵاوتن", + "status.load_more": "بارکردنی زیاتر", + "status.media_hidden": "میدیای شاراوە", + "status.mention": "ناوبنێ @{name}", + "status.more": "زیاتر", + "status.mute": "بێدەنگکردن @{name}", + "status.mute_conversation": "Ú¯ÙØªÙˆÚ¯Û†ÛŒ بێدەنگ", + "status.open": "ئەم توتە ÙØ±Ø§ÙˆØ§Ù† بکە", + "status.pin": "لکاندن لەسەر Ù¾Ø±Û†ÙØ§ÛŒÙ„", + "status.pinned": "توتی چەسپکراو", + "status.read_more": "زیاتر بخوێنەوە", + "status.reblog": "بەهێزکردن", + "status.reblog_private": "بەهێزکردن بۆ بینەرانی سەرەتایی", + "status.reblogged_by": "{name} توتی کردەوە", + "status.reblogs.empty": "کەس ئەم توتەی دووبارە نەتوتاندوە ،کاتێک کەسێک وا بکات، لێرە دەرئەکەون.", + "status.redraft": "سڕینەوەی Ùˆ دووبارە ڕەشنووس", + "status.remove_bookmark": "لابردنی نیشانه", + "status.reply": "وەڵام", + "status.replyAll": "بە نووسراوە وەڵام بدەوە", + "status.report": "گوزارشت @{name}", + "status.sensitive_warning": "ناوەڕۆکی هەستیار", + "status.share": "هاوبەش کردن", + "status.show_less": "کەمتر نیشان بدە", + "status.show_less_all": "کەمتر نیشان بدە بۆ هەمووی", + "status.show_more": "زیاتر پیشان بدە", + "status.show_more_all": "زیاتر نیشان بدە بۆ هەمووی", + "status.show_thread": "نیشاندانی Ú¯ÙØªÙˆÚ¯Û†", + "status.uncached_media_warning": "بەردەست نیە", + "status.unmute_conversation": "Ú¯ÙØªÙˆÚ¯Û†ÛŒ بێدەنگ", + "status.unpin": "لابردن Ù„Û• Ù¾Ø±Û†ÙØ§ÛŒÙ„", + "suggestions.dismiss": "ڕەتکردنەوەی پێشنیار", + "suggestions.header": "لەوانەیە ØÛ•زت Ù„Û•Ù…Û•Ø´ بێت…", + "tabs_bar.federated_timeline": "گشتی", + "tabs_bar.home": "سەرەتا", + "tabs_bar.local_timeline": "ناوخۆیی", + "tabs_bar.notifications": "ئاگادارییەکان", + "tabs_bar.search": "گەڕان", + "time_remaining.days": "{number, plural, one {# Ú•Û†Ú˜} other {# Ú•Û†Ú˜}} ماوە", + "time_remaining.hours": "{number, plural, one {# کات} other {# کات}} ماوە", + "time_remaining.minutes": "{number, plural, one {# خۆلەک} other {# خولەک}} ماوە", + "time_remaining.moments": "ئەو ساتانەی ماونەتەوە", + "time_remaining.seconds": "{number, plural, one {# چرکە} other {# چرکە}} ماوە", + "timeline_hint.remote_resource_not_displayed": "{resource} Ù„Û• ڕاژەکانی ترەوە پیشان نادرێت.", + "timeline_hint.resources.followers": "شوێنکەوتووان", + "timeline_hint.resources.follows": "شوێنکەوتن", + "timeline_hint.resources.statuses": "توتی Ú©Û†Ù†", + "trends.counter_by_accounts": "{count, plural, one {{counter} کەس} other {{counter} کەس}} Ú¯ÙØªÙˆÚ¯Û† دەکا", + "trends.trending_now": "گۆگران", + "ui.beforeunload": "ڕەشنووسەکەت Ù„Û• دەست دەچێت ئەگەر Ù„Û• ماستۆدۆن بڕۆیت.", + "units.short.billion": "{count}ملیار", + "units.short.million": "{count}ملیۆن", + "units.short.thousand": "{count}هەزار", + "upload_area.title": "ڕاکێشان & دانان بۆ بارکردن", + "upload_button.label": "زیادکردنی وێنەکان، ڤیدیۆیەک یان ÙØ§ÛŒÙ„ÛŽÚ©ÛŒ دەنگی", + "upload_error.limit": "سنووری بارکردنی ÙØ§ÛŒÙ„ تێپەڕیوە.", + "upload_error.poll": "Ù¾Û•Ú•Ú¯Û•Ú©Û• Ú•ÛŽÛŒ پێنەدراوە بە ڕاپرسی باربکرێت.", + "upload_form.audio_description": "بۆ ئەو کەسانەی Ú©Û• Ú¯ÙˆÛŽ بیستیان هەیە وەس٠دەکات", + "upload_form.description": "وەس٠بکە بۆ کەمبینایان", + "upload_form.edit": "دەستکاری", + "upload_form.thumbnail": "گۆڕانی وینۆچکە", + "upload_form.undo": "سڕینەوە", + "upload_form.video_description": "بۆ Ú©Û•Ù… بینایان Ùˆ Ú©Û•Ù… بیستان وەسÙÛŒ بکە", + "upload_modal.analyzing_picture": "شیکردنەوەی وێنە…", + "upload_modal.apply": "جێبەجێ کردن", + "upload_modal.choose_image": "ÙˆÛŽÙ†Û• هەڵبژێرە", + "upload_modal.description_placeholder": "بە دڵ کەین با بە نەشئەی Ù…Û•ÛŒ غوباری Ù…ÛŒØÙ†Û•تی دونیا", + "upload_modal.detect_text": "دەقی ÙˆÛŽÙ†Û•Ú©Û• بدۆزیەوە", + "upload_modal.edit_media": "دەستکاریکردنی میدیا", + "upload_modal.hint": "گەر ÙˆÛŽÙ†Û• Ú†Ú©Û†Ù„Û• یان بڕاوەبێت، خاڵی ناوەندی دیار دەکەوێت. خاڵی ناوەندی ÙˆÛŽÙ†Û• بە کرتە یان جێبەجیکردنی رێکبخەن.", + "upload_modal.preparing_ocr": "ئامادەکردنی OCR…", + "upload_modal.preview_label": "پێشبینی ({ratio})", + "upload_progress.label": "بارکردن...", + "video.close": "داخستنی ڤیدیۆ", + "video.download": "داگرتنی ÙØ§ÛŒÙ„", + "video.exit_fullscreen": "دەرچوون Ù„Û• Ù¾Ú• شاشە", + "video.expand": "Ú¤ÛŒØ¯ÛŒÛ†ÙØ±Ø§ÙˆØ§Ù† بکە", + "video.fullscreen": "پڕپیشانگەر", + "video.hide": "شاردنەوەی ڤیدیۆ", + "video.mute": "دەنگی Ú©Ù¾", + "video.pause": "وەستان", + "video.play": "پەخشکردن", + "video.unmute": "دەنگ لابدە" } diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index e9618e0f2e91cae8ed9bdc402197b2d04f0f9176..46dc0975db7a67aa32a01a0ade413167416b76fe 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 2812760a658a2a08be243550f943aaecb8ff8d4b..f075731fedc6370e05d3a4c71fa1f0f5af8173aa 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "PÄrlÅ«kot vairÄk sÄkotnÄ“jÄ profilÄ", "account.cancel_follow_request": "Atcelt pieprasÄ«jumu", "account.direct": "PrivÄtÄ ziņa @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "DomÄ“ns ir paslÄ“pts", "account.edit_profile": "Labot profilu", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Izcelts profilÄ", "account.follow": "Sekot", "account.followers": "SekotÄji", @@ -96,7 +98,7 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "PublicÄ“t", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", "compose_form.sensitive.marked": "MÄ“dijs ir atzÄ«mÄ“ts kÄ sensitÄ«vs", "compose_form.sensitive.unmarked": "MÄ“dijs nav atzÄ«mÄ“ts kÄ sensitÄ«vs", "compose_form.spoiler.marked": "Teksts ir paslÄ“pts aiz brÄ«dinÄjuma", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Meklēšanas rezultÄti", "emoji_button.symbols": "Simboli", "emoji_button.travel": "CeļoÅ¡ana & Vietas", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Å eit ziņojumu nav!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "Tu neesi vÄ“l nevienu bloÄ·Ä“jis.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Tev nav paziņojumu. Iesaisties sarunÄs ar citiem.", "empty_column.public": "Å eit nekÄ nav, tukÅ¡ums! Ieraksti kaut ko publiski, vai uzmeklÄ“ un seko kÄdam no citas instances", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "AutorizÄ“t", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/mk.json b/app/javascript/mastodon/locales/mk.json index 2bb9a2e2ac7788e8b804c45e394c7d1b78c58c93..6dac40e8b8c5ce2aac34aa52d23954d855805876 100644 --- a/app/javascript/mastodon/locales/mk.json +++ b/app/javascript/mastodon/locales/mk.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Одкажи барање за Ñледење", "account.direct": "Директна порана @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Скриен домен", "account.edit_profile": "Измени профил", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "КарактериÑтики на профилот", "account.follow": "Следи", "account.followers": "Следбеници", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Резултати од барање", "emoji_button.symbols": "Симболи", "emoji_button.travel": "Патувања и МеÑта", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "ÐедоÑтапен профил", "empty_column.blocks": "Ðемате Ñеуште блокирано кориÑници.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Пријавете проблем", "follow_request.authorize": "Одобри", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "БуÑтови:", "notifications.column_settings.show": "Прикажи во колона", "notifications.column_settings.sound": "Свири звуци", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Сите", "notifications.filter.boosts": "БуÑтови", "notifications.filter.favourites": "Омилени", "notifications.filter.follows": "Следења", "notifications.filter.mentions": "Спомнувања", "notifications.filter.polls": "Резултати од анкета", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} нотификации", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Затворени", "poll.refresh": "ОÑвежи", "poll.total_people": "{count, plural, one {# човек} other {# луѓе}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index 4a390ad70fb57fb06670e1f63a2685a678e1619a..4f44f3800bd8f1368f17f5adf1e9edaf3fcce783 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -2,15 +2,17 @@ "account.account_note_header": "à´•àµà´±à´¿à´ªàµà´ªàµ", "account.add_or_remove_from_list": "പടàµà´Ÿà´¿à´•യിൽ ചേർകàµà´•àµà´•യോ à´…à´²àµà´²àµ†à´™àµà´•ിൽ മാറàµà´±àµà´•യോ ചെയàµà´¯àµà´•", "account.badges.bot": "റോബോടàµà´Ÿàµ", - "account.badges.group": "കൂടàµà´Ÿà´‚", - "account.block": "@{name} നെ à´¬àµà´²àµ‹à´•àµà´•ൠചെയàµà´¯àµà´•", + "account.badges.group": "à´—àµà´°àµ‚à´ªàµà´ªàµ", + "account.block": "@{name} -നെ തടയàµà´•", "account.block_domain": "{domain} ൽ നിനàµà´¨àµà´³àµà´³ à´Žà´²àµà´²à´¾à´‚ മറയàµà´•àµà´•", "account.blocked": "തടഞàµà´žàµ", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "യഥാർതàµà´¥ à´ªàµà´°àµŠà´«àµˆà´²à´¿à´²àµ‡à´•àµà´•ൠപോവàµà´•", "account.cancel_follow_request": "പിനàµà´¤àµà´Ÿà´°à´¾à´¨àµà´³àµà´³ അപേകàµà´· നിരസികàµà´•àµà´•", "account.direct": "@{name} നൠനേരിടàµà´Ÿàµ മെസേജൠഅയകàµà´•àµà´•", + "account.disable_notifications": "@{name} പോസàµà´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨à´¤àµ à´Žà´¨àµà´¨àµ† അറിയികàµà´•àµà´¨àµà´¨à´¤àµ നിർതàµà´¤àµà´•", "account.domain_blocked": "മേഖല മറയàµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ", "account.edit_profile": "à´ªàµà´°àµŠà´«àµˆàµ½ തിരàµà´¤àµà´¤àµà´•", + "account.enable_notifications": "@{name} പോസàµà´±àµà´±àµ ചെയàµà´¯àµà´®àµà´ªàµ‹àµ¾ à´Žà´¨àµà´¨àµ† അറിയികàµà´•àµà´•", "account.endorse": "à´ªàµà´°àµŠà´«àµˆà´²à´¿àµ½ à´ªàµà´°à´•ടമാകàµà´•àµà´•", "account.follow": "പിനàµà´¤àµà´Ÿà´°àµà´•", "account.followers": "പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µàµ¼", @@ -36,7 +38,7 @@ "account.requested": "à´…à´¨àµà´µà´¾à´¦à´¤àµà´¤à´¿à´¨à´¾à´¯à´¿ കാതàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. പിനàµà´¤àµà´Ÿà´°à´¾à´¨àµà´³àµà´³ അപേകàµà´· റദàµà´¦à´¾à´•àµà´•àµà´µà´¾àµ» ഞെകàµà´•àµà´•", "account.share": "@{name} à´¨àµà´±àµ† à´ªàµà´°àµŠà´«àµˆàµ½ പങàµà´•àµà´µàµ†à´•àµà´•àµà´•", "account.show_reblogs": "@{name} ൽ നിനàµà´¨àµà´³àµà´³ ബൂസàµà´±àµà´±àµà´•ൾ കാണികàµà´•àµà´•", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} ടൂടàµà´Ÿàµ} other {{counter} ടൂടàµà´Ÿàµà´•ൾ}}", "account.unblock": "à´¬àµà´²àµ‹à´•àµà´•ൠമാറàµà´±àµà´• @{name}", "account.unblock_domain": "{domain} വെളിപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•", "account.unendorse": "à´ªàµà´°àµŠà´«àµˆà´²à´¿àµ½ à´ªàµà´°à´•ടമാകàµà´•ാതിരികàµà´•àµà´•", @@ -65,7 +67,7 @@ "column.domain_blocks": "മറയàµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿ മേഖലകൾ", "column.favourites": "à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µ", "column.follow_requests": "പിനàµà´¤àµà´Ÿà´°à´¾à´¨àµà´³àµà´³ à´…à´àµà´¯àµ¼à´¤àµà´¥à´¨à´•ൾ", - "column.home": "à´à´µà´¨à´‚", + "column.home": "ഹോം", "column.lists": "പടàµà´Ÿà´¿à´•കൾ", "column.mutes": "നിശബàµà´¦à´®à´¾à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿ ഉപയോകàµà´¤à´¾à´•àµà´•ൾ", "column.notifications": "അറിയിപàµà´ªàµà´•ൾ", @@ -92,28 +94,28 @@ "compose_form.poll.duration": "തിരഞàµà´žàµ†à´Ÿàµà´ªàµà´ªà´¿à´¨àµà´±àµ† സമയദൈർഖàµà´¯à´‚", "compose_form.poll.option_placeholder": "ചോയàµâ€Œà´¸àµ {number}", "compose_form.poll.remove_option": "à´ˆ ഡിവൈസൠമാറàµà´±àµà´•", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.poll.switch_to_multiple": "വോടàµà´Ÿàµ†à´Ÿàµà´ªàµà´ªà´¿àµ½ à´’à´¨àµà´¨à´¿à´²à´§à´¿à´•à´‚ ചോയàµâ€Œà´¸àµà´•ൾ ഉൾപàµà´ªàµ†à´Ÿàµà´¤àµà´•", + "compose_form.poll.switch_to_single": "വോടàµà´Ÿàµ†à´Ÿàµà´ªàµà´ªà´¿àµ½ ഒരൊറàµà´± ചോയàµâ€Œà´¸àµâ€Œ മാതàµà´°à´‚ ആകàµà´•àµà´•", "compose_form.publish": "ടൂടàµà´Ÿàµ", - "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.publish_loud": "{à´ªàµà´°à´¸à´¿à´¦àµà´§àµ€à´•à´°à´¿à´•àµà´•àµà´•}!", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "à´Žà´´àµà´¤àµà´¤àµ à´®àµà´¨àµà´¨à´±à´¿à´¯à´¿à´ªàµà´ªà´¿à´¨à´¾àµ½ മറചàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ", "compose_form.spoiler.unmarked": "à´Žà´´àµà´¤àµà´¤àµ മറയàµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´Ÿàµà´Ÿà´¿à´²àµà´²", "compose_form.spoiler_placeholder": "നിങàµà´™à´³àµà´Ÿàµ† à´®àµà´¨àµà´¨à´±à´¿à´¯à´¿à´ªàµà´ªàµ ഇവിടെ à´Žà´´àµà´¤àµà´•", "confirmation_modal.cancel": "റദàµà´¦à´¾à´•àµà´•àµà´•", - "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.block_and_report": "തടയàµà´•à´¯àµà´‚ റിപàµà´ªàµ‹àµ¼à´Ÿàµà´Ÿàµà´‚ ചെയàµà´¯àµà´•", "confirmations.block.confirm": "തടയàµà´•", - "confirmations.block.message": "Are you sure you want to block {name}?", + "confirmations.block.message": "{name} തടയാൻ നിങàµà´™àµ¾ ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµà´£àµà´Ÿàµ‹?", "confirmations.delete.confirm": "മായàµà´•àµà´•àµà´•", - "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.delete.message": "à´ˆ ടൂടàµà´Ÿàµ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•ണം à´Žà´¨àµà´¨àµ നിങàµà´™àµ¾à´•àµà´•ൠഉറപàµà´ªà´¾à´£àµ‹?", "confirmations.delete_list.confirm": "മായàµà´•àµà´•àµà´•", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", - "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.delete_list.message": "à´ˆ പടàµà´Ÿà´¿à´• à´Žà´¨àµà´¨àµ†à´¨àµà´¨àµ‡à´•àµà´•àµà´®à´¾à´¯à´¿ നീകàµà´•à´‚ ചെയàµà´¯à´¾àµ» നിങàµà´™àµ¾ ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµà´£àµà´Ÿàµ‹?", + "confirmations.domain_block.confirm": "à´®àµà´´àµà´µàµ» ഡൊമെയàµâ€Œà´¨àµà´‚ തടയàµà´•", "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", "confirmations.logout.confirm": "à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´•", - "confirmations.logout.message": "Are you sure you want to log out?", + "confirmations.logout.message": "നിങàµà´™àµ¾à´•àµà´•ൠലോഗൠഔടàµà´Ÿàµ ചെയàµà´¯à´£à´®àµ†à´¨àµà´¨àµ ഉറപàµà´ªà´¾à´£àµ‹?", "confirmations.mute.confirm": "നിശàµà´¶à´¬àµà´¦à´®à´¾à´•àµà´•àµà´•", "confirmations.mute.explanation": "This will hide posts from them and posts mentioning them, but it will still allow them to see your posts and follow you.", "confirmations.mute.message": "Are you sure you want to mute {name}?", @@ -131,7 +133,7 @@ "directory.local": "{domain} ൽ നിനàµà´¨àµ മാതàµà´°à´‚", "directory.new_arrivals": "à´ªàµà´¤à´¿à´¯ വരവàµà´•ൾ", "directory.recently_active": "à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ†à´¯à´¾à´¯à´¿ സജീവമായ", - "embed.instructions": "Embed this status on your website by copying the code below.", + "embed.instructions": "à´šàµà´µà´Ÿàµ†à´¯àµà´³àµà´³ കോഡൠപകർതàµà´¤à´¿à´•àµà´•ൊണàµà´Ÿàµ നിങàµà´™à´³àµà´Ÿàµ† വെബàµâ€Œà´¸àµˆà´±àµà´±à´¿àµ½ à´ˆ ടൂടàµà´Ÿàµ ഉൾചàµà´šàµ‡àµ¼à´•àµà´•àµà´•.", "embed.preview": "ഇതൠഇങàµà´™à´¨àµ† കാണപàµà´ªàµ†à´Ÿàµà´‚:", "emoji_button.activity": "à´ªàµà´°à´µà´°àµâ€à´¤àµà´¤à´¨à´‚", "emoji_button.custom": "à´¸àµà´µà´¨àµà´¤à´®à´¾à´¯ à´àµ‡à´¦à´—തി", @@ -139,7 +141,7 @@ "emoji_button.food": "à´à´•àµà´·à´£à´µàµà´‚ പാനീയവàµà´‚", "emoji_button.label": "ഇമോജി ചേർകàµà´•àµà´•", "emoji_button.nature": "à´ªàµà´°à´•ൃതി", - "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ â”»â”â”»", + "emoji_button.not_found": "ഇമോജി പാടിലàµà´² (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "വസàµà´¤àµà´•àµà´•ൾ", "emoji_button.people": "ആളàµà´•ൾ", "emoji_button.recent": "à´…à´Ÿà´¿à´•àµà´•à´Ÿà´¿ ഉപയോഗികàµà´•àµà´¨àµà´¨à´µ", @@ -147,26 +149,29 @@ "emoji_button.search_results": "തിരചàµà´šà´¿àµ½ ഫലങàµà´™àµ¾", "emoji_button.symbols": "à´šà´¿à´¹àµà´¨à´™àµà´™àµ¾", "emoji_button.travel": "യാതàµà´°à´¯àµà´‚ à´¸àµà´¥à´²à´™àµà´™à´³àµà´‚", + "empty_column.account_suspended": "à´…à´•àµà´•ൗണàµà´Ÿàµ താൽകàµà´•ാലികമായി നിർതàµà´¤à´¿à´µà´šàµà´šàµ", "empty_column.account_timeline": "ഇവിടെ ടൂടàµà´Ÿàµà´•ൾ ഇലàµà´²!", "empty_column.account_unavailable": "à´ªàµà´°àµŠà´«àµˆàµ½ à´²à´àµà´¯à´®à´²àµà´²", "empty_column.blocks": "നിങàµà´™àµ¾ ഇതàµà´µà´°àµ† ഒരൠഉപയോകàµà´¤à´¾à´•àµà´•ളെയàµà´‚ തടഞàµà´žà´¿à´Ÿàµà´Ÿà´¿à´²àµà´².", - "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", + "empty_column.bookmarked_statuses": "നിങàµà´™àµ¾à´•ൠഇതàµà´µà´°àµ† അടയാളപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯ ടൂടàµà´Ÿàµà´•ൾ ഇലàµà´². അടയാളപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯à´¾àµ½ അതൠഇവിടെ വരàµà´‚.", "empty_column.community": "à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•മായ സമയരേഖ ശൂനàµà´¯à´®à´¾à´£àµ. à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ പരസàµà´¯à´®à´¾à´¯à´¿ à´Žà´´àµà´¤à´¿ à´¤àµà´Ÿà´•àµà´•à´‚ à´•àµà´±à´¿à´•àµà´•àµ!", "empty_column.direct": "നിങàµà´™àµ¾à´•àµà´•ൠഇതàµà´µà´°àµ† നേരിടàµà´Ÿàµà´³àµà´³ സനàµà´¦àµ‡à´¶à´™àµà´™àµ¾ à´’à´¨àµà´¨àµà´®à´¿à´²àµà´². നിങàµà´™àµ¾ à´…à´™àµà´™à´¨àµ† à´’à´¨àµà´¨àµ അയകàµà´•àµà´•യോ, നിങàµà´™àµ¾à´•àµà´•ൠലà´à´¿à´•àµà´•àµà´•യോ ചെയàµà´¯àµà´¨àµà´¨à´ªà´•àµà´·à´‚ അതിവിടെ കാണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¤à´¾à´£àµ.", "empty_column.domain_blocks": "മറയàµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ മേഖലകൾ ഇതàµà´µà´°àµ† ഇലàµà´².", "empty_column.favourited_statuses": "നിങàµà´™àµ¾à´•àµà´•ൠഇതൠവരെ ഒരൠപàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿ ടൂടàµà´Ÿàµà´‚ ഇലàµà´². നിങàµà´™àµ¾ à´…à´™àµà´™à´¨àµ† à´’à´¨àµà´¨àµ à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ പകàµà´·à´‚ അതിവിടെ കാണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¤à´¾à´£àµ.", "empty_column.favourites": "ഇതàµà´µà´°àµ† ആരàµà´‚ à´ˆ ടൂടàµà´Ÿàµ à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¤à´¾à´¯à´¿ അടയാളപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´². ആരെങàµà´•à´¿à´²àµà´‚ à´…à´™àµà´™à´¨àµ† ചെയàµà´¯àµà´¨àµà´¨à´ªà´•àµà´·à´‚ അതിവിടെ കാണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¤à´¾à´£àµ.", "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", - "empty_column.hashtag": "There is nothing in this hashtag yet.", + "empty_column.hashtag": "à´ˆ ഹാഷàµâ€Œà´Ÿà´¾à´—ിൽ ഇതàµà´µà´°àµ† à´’à´¨àµà´¨àµà´®à´¿à´²àµà´².", "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", - "empty_column.home.public_timeline": "the public timeline", + "empty_column.home.public_timeline": "പൊതൠസമയരേഖ", "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", "empty_column.mutes": "You haven't muted any users yet.", "empty_column.notifications": "നിങàµà´™àµ¾à´•àµà´•ൠഇതàµà´µà´°àµ† ഒരൠഅറിയിപàµà´ªàµà´•à´³àµà´‚ ഇലàµà´². മറàµà´±àµà´³àµà´³à´µà´°àµà´®à´¾à´¯à´¿ ഇടപെടàµà´Ÿàµ സംà´à´¾à´·à´£à´¤àµà´¤à´¿à´¨àµ à´¤àµà´Ÿà´•àµà´•à´‚ à´•àµà´±à´¿à´•àµà´•àµ.", "empty_column.public": "ഇവിടെ à´’à´¨àµà´¨àµà´®à´¿à´²àµà´²à´²àµà´²àµ‹! ഇവിടെ നിറയàµà´•àµà´•ാൻ à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ പരസàµà´¯à´®à´¾à´¯à´¿ à´Žà´´àµà´¤àµà´•യോ മറàµà´±àµ ഉപà´àµ‹à´•àµà´¤à´¾à´•àµà´•ളെ പിനàµà´¤àµà´Ÿà´°àµà´•യോ ചെയàµà´¯àµà´•", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "à´ªàµà´°à´¶àµà´¨à´‚ അറിയികàµà´•àµà´•", "follow_request.authorize": "à´šàµà´®à´¤à´²à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•", @@ -174,7 +179,7 @@ "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", "generic.saved": "സംരകàµà´·à´¿à´šàµà´šàµ", "getting_started.developers": "വികസിപàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´µàµ¼", - "getting_started.directory": "രൂപരേഖ നാമഗൃഹസൂചി", + "getting_started.directory": "à´ªàµà´°àµŠà´«àµˆàµ½ ഡയറകàµà´Ÿà´±à´¿", "getting_started.documentation": "രേഖാ സമാഹരണം", "getting_started.heading": "à´¤àµà´Ÿà´•àµà´•à´‚ à´•àµà´±à´¿à´•àµà´•àµà´•", "getting_started.invite": "ആളàµà´•ളെ à´•àµà´·à´£à´¿à´•àµà´•àµà´•", @@ -185,7 +190,7 @@ "hashtag.column_header.tag_mode.any": "à´…à´²àµà´²àµ†à´™àµà´•ിൽ {additional}", "hashtag.column_header.tag_mode.none": "{additional} ഇലàµà´²à´¾à´¤àµ†", "hashtag.column_settings.select.no_options_message": "ഒരൠസൂചനയàµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¿à´²àµà´²", - "hashtag.column_settings.select.placeholder": "ചർചàµà´šà´¾à´µà´¿à´·à´¯à´™àµà´™àµ¾ à´Žà´´àµà´¤àµà´•…", + "hashtag.column_settings.select.placeholder": "ഹാഷàµà´Ÿà´¾à´—àµà´•ൾ à´Žà´´àµà´¤àµà´•…", "hashtag.column_settings.tag_mode.all": "ഇവയെലàµà´²à´¾à´‚", "hashtag.column_settings.tag_mode.any": "ഇവയിലേതെങàµà´•à´¿à´²àµà´‚", "hashtag.column_settings.tag_mode.none": "ഇതിലൊനàµà´¨àµà´®à´²àµà´²", @@ -201,7 +206,7 @@ "introduction.federation.action": "à´…à´Ÿàµà´¤àµà´¤à´¤àµ", "introduction.federation.federated.headline": "സംയàµà´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯", "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", - "introduction.federation.home.headline": "à´à´µà´¨à´‚", + "introduction.federation.home.headline": "ഹോം", "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", "introduction.federation.local.headline": "à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•à´‚", "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", @@ -217,245 +222,265 @@ "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", "keyboard_shortcuts.back": "തിരികെ പോകàµà´•", "keyboard_shortcuts.blocked": "to open blocked users list", - "keyboard_shortcuts.boost": "to boost", + "keyboard_shortcuts.boost": "ബൂസàµà´±àµà´±àµ ചെയàµà´¯àµà´•", "keyboard_shortcuts.column": "to focus a status in one of the columns", "keyboard_shortcuts.compose": "to focus the compose textarea", "keyboard_shortcuts.description": "വിവരണം", "keyboard_shortcuts.direct": "to open direct messages column", "keyboard_shortcuts.down": "to move down in the list", - "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.enter": "ടൂടàµà´Ÿàµ à´Žà´Ÿàµà´•àµà´•ാൻ", "keyboard_shortcuts.favourite": "to favourite", "keyboard_shortcuts.favourites": "to open favourites list", "keyboard_shortcuts.federated": "to open federated timeline", "keyboard_shortcuts.heading": "കീബോർഡൠഎളàµà´ªàµà´ªà´µà´´à´¿à´•ൾ", - "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.home": "ഹോം ടൈംലൈൻ à´¤àµà´±à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ", "keyboard_shortcuts.hotkey": "Hotkey", "keyboard_shortcuts.legend": "to display this legend", - "keyboard_shortcuts.local": "to open local timeline", + "keyboard_shortcuts.local": "à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• സമയരേഖ à´¤àµà´±à´•àµà´•ാൻ", "keyboard_shortcuts.mention": "to mention author", "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.my_profile": "നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°àµŠà´«àµˆàµ½ à´¤àµà´±à´•àµà´•ാൻ", "keyboard_shortcuts.notifications": "to open notifications column", - "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.open_media": "മീഡിയ à´¤àµà´±à´•àµà´•ാൻ", "keyboard_shortcuts.pinned": "to open pinned toots list", - "keyboard_shortcuts.profile": "to open author's profile", - "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.profile": "രചയിതാവിനàµà´±àµ† à´ªàµà´°àµŠà´«àµˆàµ½ à´¤àµà´±à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ", + "keyboard_shortcuts.reply": "മറàµà´ªà´Ÿà´¿ അയകàµà´•ാൻ", "keyboard_shortcuts.requests": "to open follow requests list", "keyboard_shortcuts.search": "to focus search", "keyboard_shortcuts.spoilers": "to show/hide CW field", "keyboard_shortcuts.start": "to open \"get started\" column", "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", - "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.toggle_sensitivity": "മീഡിയ കാണികàµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµà´‚/മറയàµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµà´‚", + "keyboard_shortcuts.toot": "ഒരൠപàµà´¤à´¿à´¯ ടൂടàµà´Ÿàµ ആരംà´à´¿à´•àµà´•ാൻ", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", - "lightbox.close": "Close", - "lightbox.next": "Next", - "lightbox.previous": "Previous", - "lightbox.view_context": "View context", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.delete": "Delete list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", + "lightbox.close": "à´…à´Ÿà´¯àµà´•àµà´•àµà´•", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "à´…à´Ÿàµà´¤àµà´¤à´¤àµ", + "lightbox.previous": "à´ªàµà´±à´•ോടàµà´Ÿàµ", + "lists.account.add": "പടàµà´Ÿà´¿à´•യിലേകàµà´•ൠചേർകàµà´•àµà´•", + "lists.account.remove": "പടàµà´Ÿà´¿à´•യിൽ നിനàµà´¨àµ ഒഴിവാകàµà´•àµà´•", + "lists.delete": "പടàµà´Ÿà´¿à´• ഒഴിവാകàµà´•àµà´•", + "lists.edit": "പടàµà´Ÿà´¿à´• തിരàµà´¤àµà´¤àµà´•", + "lists.edit.submit": "തലകàµà´•െടàµà´Ÿàµ മാറàµà´±àµà´•", + "lists.new.create": "à´ªàµà´¤à´¿à´¯ പടàµà´Ÿà´¿à´• ചേർകàµà´•àµà´•", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "ആരàµà´®à´¿à´²àµà´²", + "lists.replies_policy.title": "ഇതിനàµà´³àµà´³ മറàµà´ªà´Ÿà´¿à´•ൾ കാണികàµà´•àµà´•:", "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lists.subheading": "à´Žà´¨àµà´±àµ† പടàµà´Ÿà´¿à´•കൾ", "load_pending": "{count, plural, one {# new item} other {# new items}}", - "loading_indicator.label": "Loading...", + "loading_indicator.label": "ലോഡിംഗàµ...", "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", - "missing_indicator.label": "Not found", + "missing_indicator.label": "കാണാനിലàµà´²", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "കാലാവധി", "mute_modal.hide_notifications": "Hide notifications from this user?", - "navigation_bar.apps": "Mobile apps", - "navigation_bar.blocks": "Blocked users", - "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.community_timeline": "Local timeline", - "navigation_bar.compose": "Compose new toot", - "navigation_bar.direct": "Direct messages", - "navigation_bar.discover": "Discover", + "mute_modal.indefinite": "അനിശàµà´šà´¿à´¤à´•ാല", + "navigation_bar.apps": "മൊബൈൽ ആപàµà´ªàµà´•ൾ", + "navigation_bar.blocks": "തടയപàµà´ªàµ†à´Ÿàµà´Ÿ ഉപയോകàµà´¤à´¾à´•àµà´•ൾ", + "navigation_bar.bookmarks": "à´¬àµà´•àµà´•àµà´®à´¾àµ¼à´•àµà´•àµà´•ൾ", + "navigation_bar.community_timeline": "à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• സമയരേഖ", + "navigation_bar.compose": "à´ªàµà´¤à´¿à´¯ ടൂടàµà´Ÿàµ à´Žà´´àµà´¤àµà´•", + "navigation_bar.direct": "നേരിടàµà´Ÿàµà´³àµà´³ സനàµà´¦àµ‡à´¶à´™àµà´™àµ¾", + "navigation_bar.discover": "à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•", "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.edit_profile": "Edit profile", - "navigation_bar.favourites": "Favourites", + "navigation_bar.edit_profile": "à´ªàµà´°àµŠà´«àµˆàµ½ തിരàµà´¤àµà´¤àµà´•", + "navigation_bar.favourites": "à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µ", "navigation_bar.filters": "Muted words", - "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.follow_requests": "പിനàµà´¤àµà´Ÿà´°à´¾à´¨àµà´³àµà´³ à´…à´àµà´¯àµ¼à´¤àµà´¥à´¨à´•ൾ", "navigation_bar.follows_and_followers": "Follows and followers", - "navigation_bar.info": "About this server", + "navigation_bar.info": "à´ˆ സെർവറിനെകàµà´•àµà´±à´¿à´šàµà´šàµ", "navigation_bar.keyboard_shortcuts": "Hotkeys", - "navigation_bar.lists": "Lists", - "navigation_bar.logout": "Logout", - "navigation_bar.mutes": "Muted users", + "navigation_bar.lists": "ലിസàµà´±àµà´±àµà´•ൾ", + "navigation_bar.logout": "ലോഗൗടàµà´Ÿàµ", + "navigation_bar.mutes": "നിശബàµà´¦à´®à´¾à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿ ഉപയോകàµà´¤à´¾à´•àµà´•ൾ", "navigation_bar.personal": "Personal", "navigation_bar.pins": "Pinned toots", - "navigation_bar.preferences": "Preferences", + "navigation_bar.preferences": "à´•àµà´°à´®àµ€à´•രണങàµà´™àµ¾", "navigation_bar.public_timeline": "Federated timeline", - "navigation_bar.security": "Security", + "navigation_bar.security": "à´¸àµà´°à´•àµà´·", "notification.favourite": "{name} favourited your status", - "notification.follow": "{name} followed you", - "notification.follow_request": "{name} has requested to follow you", + "notification.follow": "{name} നിങàµà´™à´³àµ† പിനàµà´¤àµà´Ÿàµ¼à´¨àµà´¨àµ", + "notification.follow_request": "{name} നിങàµà´™à´³àµ† പിനàµà´¤àµà´Ÿà´°à´¾àµ» à´…à´àµà´¯àµ¼à´¤àµà´¥à´¿à´šàµà´šàµ", "notification.mention": "{name} mentioned you", - "notification.own_poll": "Your poll has ended", + "notification.own_poll": "നിങàµà´™à´³àµà´Ÿàµ† പോൾ അവസാനിചàµà´šàµ", "notification.poll": "A poll you have voted in has ended", - "notification.reblog": "{name} boosted your status", - "notifications.clear": "Clear notifications", - "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", - "notifications.column_settings.alert": "Desktop notifications", - "notifications.column_settings.favourite": "Favourites:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notification.reblog": "{name} നിങàµà´™à´³àµà´Ÿàµ† പോസàµà´±àµà´±àµ ബൂസàµà´±àµà´±àµ ചെയàµà´¤àµ", + "notification.status": "{name} ഇപàµà´ªàµ‹àµ¾ പോസàµà´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤àµ", + "notifications.clear": "അറിയിപàµà´ªàµ മായàµà´•àµà´•àµà´•", + "notifications.clear_confirmation": "നിങàµà´™à´³àµà´Ÿàµ† à´Žà´²àµà´²à´¾ അറിയിപàµà´ªàµà´•à´³àµà´‚ ശാശàµà´µà´¤à´®à´¾à´¯à´¿ മായàµâ€Œà´•àµà´•ണമെനàµà´¨àµ നിങàµà´™àµ¾à´•àµà´•ൠഉറപàµà´ªà´¾à´£àµ‹?", + "notifications.column_settings.alert": "ഡെസàµà´•àµà´Ÿàµ‹à´ªàµà´ªàµ അറിയിപàµà´ªàµà´•ൾ", + "notifications.column_settings.favourite": "à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µ:", + "notifications.column_settings.filter_bar.advanced": "à´Žà´²àµà´²à´¾ വിà´à´¾à´—à´™àµà´™à´³àµà´‚ à´ªàµà´°à´¦àµ¼à´¶à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•", "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.filter_bar.show": "കാണികàµà´•àµà´•", "notifications.column_settings.follow": "New followers:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.follow_request": "à´ªàµà´¤à´¿à´¯ പിനàµà´¤àµà´Ÿà´°àµ½ à´…à´àµà´¯àµ¼à´¤àµà´¥à´¨à´•ൾ:", "notifications.column_settings.mention": "Mentions:", - "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.poll": "പോൾ ഫലങàµà´™àµ¾:", "notifications.column_settings.push": "Push notifications", - "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.reblog": "ബൂസàµà´±àµà´±àµà´•ൾ:", "notifications.column_settings.show": "Show in column", - "notifications.column_settings.sound": "Play sound", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Boosts", - "notifications.filter.favourites": "Favourites", - "notifications.filter.follows": "Follows", + "notifications.column_settings.sound": "à´¶à´¬àµà´¦à´‚ à´ªàµà´²àµ‡ ചെയàµà´¯àµà´•", + "notifications.column_settings.status": "à´ªàµà´¤à´¿à´¯ ടൂടàµà´Ÿàµà´•ൾ:", + "notifications.filter.all": "à´Žà´²àµà´²à´¾à´‚", + "notifications.filter.boosts": "ബൂസàµà´±àµà´±àµà´•ൾ", + "notifications.filter.favourites": "à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µ", + "notifications.filter.follows": "പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ", "notifications.filter.mentions": "Mentions", - "notifications.filter.polls": "Poll results", - "notifications.group": "{count} notifications", - "poll.closed": "Closed", - "poll.refresh": "Refresh", + "notifications.filter.polls": "പോൾ ഫലങàµà´™àµ¾", + "notifications.filter.statuses": "നിങàµà´™àµ¾ പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨ ആളàµà´•ളിൽ നിനàµà´¨àµà´³àµà´³ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´•ൾ", + "notifications.grant_permission": "à´…à´¨àµà´®à´¤à´¿ നൽകàµà´•.", + "notifications.group": "{count} അറിയിപàµà´ªàµà´•ൾ", + "notifications.mark_as_read": "à´Žà´²àµà´²à´¾ അറിയിപàµà´ªàµà´•à´³àµà´‚ വായിചàµà´šà´¤à´¾à´¯à´¿ അടയാളപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "ഡെസàµà´•àµà´Ÿàµ‹à´ªàµà´ªàµ അറിയിപàµà´ªàµà´•ൾ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "തിരികെ വയàµà´•àµà´•àµà´•", + "poll.closed": "à´…à´Ÿà´šàµà´šàµ", + "poll.refresh": "à´ªàµà´¤àµà´•àµà´•àµà´•", "poll.total_people": "{count, plural, one {# person} other {# people}}", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll.voted": "You voted for this answer", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", - "privacy.change": "Adjust status privacy", + "poll.vote": "വോടàµà´Ÿàµ ചെയàµà´¯àµà´•", + "poll.voted": "à´ˆ ഉതàµà´¤à´°à´¤àµà´¤à´¿à´¨à´¾à´¯à´¿ നിങàµà´™àµ¾ വോടàµà´Ÿàµ ചെയàµà´¤àµ", + "poll_button.add_poll": "ഒരൠപോൾ ചേർകàµà´•àµà´•", + "poll_button.remove_poll": "പോൾ നീകàµà´•ംചെയàµà´¯àµà´•", + "privacy.change": "ടൂടàµà´Ÿàµ à´¸àµà´µà´•ാരàµà´¯à´¤ à´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´•", "privacy.direct.long": "Post to mentioned users only", - "privacy.direct.short": "Direct", + "privacy.direct.short": "നേരിടàµà´Ÿàµ", "privacy.private.long": "Post to followers only", - "privacy.private.short": "Followers-only", + "privacy.private.short": "പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µàµ¼à´•àµà´•ൠമാതàµà´°à´‚", "privacy.public.long": "Post to public timelines", "privacy.public.short": "Public", "privacy.unlisted.long": "Do not show in public timelines", "privacy.unlisted.short": "Unlisted", - "refresh": "Refresh", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "refresh": "à´ªàµà´¤àµà´•àµà´•àµà´•", + "regeneration_indicator.label": "à´²à´àµà´¯à´®à´¾à´•àµà´•àµà´¨àµà´¨àµâ€¦", + "regeneration_indicator.sublabel": "നിങàµà´™à´³àµà´Ÿàµ† ഹോം ഫീഡൠതയാറാകàµà´•àµà´¨àµà´¨àµ!", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", - "relative_time.just_now": "now", + "relative_time.just_now": "ഇപàµà´ªàµ‹àµ¾", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", - "relative_time.today": "today", - "reply_indicator.cancel": "Cancel", + "relative_time.today": "ഇനàµà´¨àµ", + "reply_indicator.cancel": "റദàµà´¦à´¾à´•àµà´•àµà´•", "report.forward": "Forward to {target}", - "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.forward_hint": "à´ˆ à´…à´•àµà´•ൗണàµà´Ÿàµ മറàµà´±àµŠà´°àµ സെർവറിൽ നിനàµà´¨à´¾à´£àµ. റിപàµà´ªàµ‹àµ¼à´Ÿàµà´Ÿà´¿à´¨àµà´±àµ† à´…à´œàµà´žà´¾à´¤ പകർപàµà´ªàµ അവിടെ അയയàµà´•àµà´•ണോ?", "report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:", - "report.placeholder": "Additional comments", - "report.submit": "Submit", + "report.placeholder": "കൂടàµà´¤àµ½ à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™àµ¾", + "report.submit": "സമർപàµà´ªà´¿à´•àµà´•àµà´•", "report.target": "Report {target}", - "search.placeholder": "Search", + "search.placeholder": "തിരയàµà´•", "search_popout.search_format": "Advanced search format", "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "status", + "search_popout.tips.hashtag": "ഹാഷàµà´Ÿà´¾à´—àµ", + "search_popout.tips.status": "ടൂടàµà´Ÿàµ", "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", - "search_popout.tips.user": "user", - "search_results.accounts": "People", - "search_results.hashtags": "Hashtags", - "search_results.statuses": "Toots", + "search_popout.tips.user": "ഉപയോകàµà´¤à´¾à´µàµ", + "search_results.accounts": "ആളàµà´•ൾ", + "search_results.hashtags": "ഹാഷàµà´Ÿà´¾à´—àµà´•ൾ", + "search_results.statuses": "ടൂടàµà´Ÿàµà´•ൾ", "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "status.admin_account": "Open moderation interface for @{name}", "status.admin_status": "Open this status in the moderation interface", - "status.block": "Block @{name}", - "status.bookmark": "Bookmark", + "status.block": "@{name} -നെ തടയàµà´•", + "status.bookmark": "à´¬àµà´•àµà´•àµà´®à´¾àµ¼à´•àµà´•àµ", "status.cancel_reblog_private": "Unboost", - "status.cannot_reblog": "This post cannot be boosted", - "status.copy": "Copy link to status", + "status.cannot_reblog": "à´ˆ പോസàµà´±àµà´±àµ ബൂസàµà´±àµà´šàµ†à´¯àµà´¯à´¾àµ» കഴിയിലàµà´²", + "status.copy": "ടൂടàµà´Ÿà´¿à´²àµ‡à´•àµà´•ൠലിങàµà´•ൠപകർതàµà´¤àµà´•", "status.delete": "മായàµà´•àµà´•àµà´•", "status.detailed_status": "വിശദമായ സംà´à´¾à´·à´£ കാഴàµâ€Œà´š", "status.direct": "@{name} നൠനേരിടàµà´Ÿàµ മെസേജൠഅയകàµà´•àµà´•", "status.embed": "ഉൾചàµà´šàµ‡àµ¼à´•àµà´•àµà´•", "status.favourite": "à´ªàµà´°à´¿à´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¤àµ", - "status.filtered": "Filtered", + "status.filtered": "ഫിൽടàµà´Ÿàµ¼ ചെയàµâ€Œà´¤àµ", "status.load_more": "കൂടàµà´¤àµ½ ലോഡൠചെയàµà´¯àµà´•", - "status.media_hidden": "Media hidden", + "status.media_hidden": "മീഡിയ മറചàµà´šàµ", "status.mention": "@{name} സൂചിപàµà´ªà´¿à´•àµà´•àµà´•", - "status.more": "More", - "status.mute": "Mute @{name}", + "status.more": "കൂടàµà´¤àµ½", + "status.mute": "@{name}-നെ നിശàµà´¶à´¬àµà´¦à´®à´¾à´•àµà´•àµà´•", "status.mute_conversation": "Mute conversation", "status.open": "Expand this status", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", - "status.read_more": "Read more", - "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", - "status.reblogged_by": "{name} boosted", + "status.read_more": "കൂടàµà´¤àµ½ വായികàµà´•àµà´•", + "status.reblog": "ബൂസàµà´±àµà´±àµ", + "status.reblog_private": "Boost with original visibility", + "status.reblogged_by": "{name} ബൂസàµà´±àµà´±àµ ചെയàµà´¤àµ", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.remove_bookmark": "Remove bookmark", - "status.reply": "Reply", + "status.redraft": "ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• & വീണàµà´Ÿàµà´‚ à´¡àµà´°à´¾à´«àµà´±àµà´±àµ ചെയàµà´¯àµà´•", + "status.remove_bookmark": "à´¬àµà´•àµà´•àµà´®à´¾àµ¼à´•àµà´•ൠനീകàµà´•ംചെയàµà´¯àµà´•", + "status.reply": "മറàµà´ªà´Ÿà´¿", "status.replyAll": "Reply to thread", - "status.report": "Report @{name}", + "status.report": "@{name}--നെ റിപàµà´ªàµ‹àµ¼à´Ÿàµà´Ÿàµ ചെയàµà´¯àµà´•", "status.sensitive_warning": "Sensitive content", - "status.share": "Share", - "status.show_less": "Show less", + "status.share": "പങàµà´•à´¿à´Ÿàµà´•", + "status.show_less": "à´•àµà´±à´šàµà´šàµ കാണികàµà´•àµà´•", "status.show_less_all": "Show less for all", - "status.show_more": "Show more", - "status.show_more_all": "Show more for all", - "status.show_thread": "Show thread", - "status.uncached_media_warning": "Not available", + "status.show_more": "കൂടàµà´¤à´•ൽ കാണികàµà´•àµà´•", + "status.show_more_all": "à´Žà´²àµà´²à´¾à´µàµ¼à´•àµà´•àµà´®à´¾à´¯à´¿ കൂടàµà´¤àµ½ കാണികàµà´•àµà´•", + "status.show_thread": "à´¤àµà´°àµ†à´¡àµ കാണികàµà´•àµà´•", + "status.uncached_media_warning": "à´²à´àµà´¯à´®à´²àµà´²", "status.unmute_conversation": "Unmute conversation", "status.unpin": "Unpin from profile", "suggestions.dismiss": "Dismiss suggestion", - "suggestions.header": "You might be interested in…", - "tabs_bar.federated_timeline": "Federated", - "tabs_bar.home": "Home", - "tabs_bar.local_timeline": "Local", - "tabs_bar.notifications": "Notifications", - "tabs_bar.search": "Search", + "suggestions.header": "നിങàµà´™àµ¾à´•àµà´•ൠതാൽപàµà´ªà´°àµà´¯à´®àµà´£àµà´Ÿà´¾à´•ാം…", + "tabs_bar.federated_timeline": "സംയàµà´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯", + "tabs_bar.home": "ഹോം", + "tabs_bar.local_timeline": "à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•à´‚", + "tabs_bar.notifications": "അറിയിപàµà´ªàµà´•ൾ", + "tabs_bar.search": "തിരയàµà´•", "time_remaining.days": "{number, plural, one {# day} other {# days}} left", "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", "time_remaining.moments": "Moments remaining", "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", + "timeline_hint.resources.followers": "പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µàµ¼", + "timeline_hint.resources.follows": "പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ", + "timeline_hint.resources.statuses": "പഴയ ടൂടàµà´Ÿàµà´•ൾ", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", - "trends.trending_now": "Trending now", + "trends.trending_now": "ഇപàµà´ªàµ‹àµ¾ à´Ÿàµà´°àµ†àµ»à´¡à´¿à´‚à´—àµ", "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", "units.short.billion": "{count}B", - "units.short.million": "{count}M", + "units.short.million": "{count}ദശലകàµà´·à´‚", "units.short.thousand": "{count}K", - "upload_area.title": "Drag & drop to upload", - "upload_button.label": "Add images, a video or an audio file", - "upload_error.limit": "File upload limit exceeded.", + "upload_area.title": "à´…à´ªàµâ€Œà´²àµ‹à´¡àµà´šàµ†à´¯àµà´¯à´¾àµ» വലിചàµà´šà´¿à´Ÿàµà´•", + "upload_button.label": "ഇമേജàµà´•ൾ, ഒരൠവീഡിയോ à´…à´²àµà´²àµ†à´™àµà´•ിൽ ഓഡിയോ ഫയൽ ചേർകàµà´•àµà´•", + "upload_error.limit": "ഫയൽ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ പരിധി കവിഞàµà´žàµ.", "upload_error.poll": "File upload not allowed with polls.", - "upload_form.audio_description": "Describe for people with hearing loss", - "upload_form.description": "Describe for the visually impaired", - "upload_form.edit": "Edit", - "upload_form.thumbnail": "Change thumbnail", - "upload_form.undo": "Delete", + "upload_form.audio_description": "കേൾവിശകàµà´¤à´¿ ഇലàµà´²à´¾à´¤àµà´¤à´µàµ¼à´•àµà´•ൠവേണàµà´Ÿà´¿ വിവരണം നൽകൂ", + "upload_form.description": "കാഴàµà´šà´¶à´•àµà´¤à´¿ ഇലàµà´²à´¾à´¤àµà´¤à´µàµ¼à´•àµà´•ൠവേണàµà´Ÿà´¿ വിവരണം നൽകൂ", + "upload_form.edit": "തിരàµà´¤àµà´¤àµà´•", + "upload_form.thumbnail": "ലഘàµà´šà´¿à´¤àµà´°à´‚ മാറàµà´±àµà´•", + "upload_form.undo": "ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•", "upload_form.video_description": "Describe for people with hearing loss or visual impairment", - "upload_modal.analyzing_picture": "Analyzing picture…", - "upload_modal.apply": "Apply", - "upload_modal.choose_image": "Choose image", + "upload_modal.analyzing_picture": "à´šà´¿à´¤àµà´°à´‚ വിശകലനം ചെയàµà´¯àµà´¨àµà´¨àµâ€¦", + "upload_modal.apply": "à´ªàµà´°à´¯àµ‹à´—à´¿à´•àµà´•àµà´•", + "upload_modal.choose_image": "à´šà´¿à´¤àµà´°à´‚ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•", "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", "upload_modal.detect_text": "Detect text from picture", - "upload_modal.edit_media": "Edit media", + "upload_modal.edit_media": "മീഡിയ തിരàµà´¤àµà´¤àµà´•", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "OCR തയàµà´¯à´¾à´±à´¾à´•àµà´•àµà´¨àµà´¨àµâ€¦", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", - "video.close": "Close video", - "video.download": "Download file", - "video.exit_fullscreen": "Exit full screen", + "video.close": "വീഡിയോ à´…à´Ÿà´¯àµà´•àµà´•àµà´•", + "video.download": "ഫയൽ ഡൌൺലോഡൠചെയàµà´¯àµà´•", + "video.exit_fullscreen": "പൂർണàµà´£ à´¸àµà´•àµà´°àµ€à´¨à´¿àµ½ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´•", "video.expand": "Expand video", - "video.fullscreen": "Full screen", - "video.hide": "Hide video", + "video.fullscreen": "പൂർണàµà´£ à´¸àµà´•àµà´°àµ€àµ»", + "video.hide": "വീഡിയോ മറയàµà´•àµà´•àµà´•", "video.mute": "Mute sound", "video.pause": "Pause", - "video.play": "Play", + "video.play": "à´ªàµà´²àµ‡", "video.unmute": "Unmute sound" } diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index 5a93ae851bec0ef18d043c34d1b186ffe8626e60..8559665b9e1483ddd49901d86f14d22a80c6d691 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "अनà¥à¤¯à¤¾à¤¯à¥€ होणà¥à¤¯à¤¾à¤šà¥€ विनंती रदà¥à¤¦ करा", "account.direct": "थेट संदेश @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤² à¤à¤¡à¤¿à¤Ÿ करा", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "अनà¥à¤¯à¤¾à¤¯à¥€ वà¥à¤¹à¤¾", "account.followers": "अनà¥à¤¯à¤¾à¤¯à¥€", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 5fc777887934798e990fd98a3febbde591c2059b..ec992c67944bb3c1321abf687c762dc86bcef6e7 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 73e2b9a1369e2dbf83c01a88f5bee518d2bd2498..e19f0b6d343fca4c44d38c282de9344851037dfc 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Meer op het originele profiel bekijken", "account.cancel_follow_request": "Volgverzoek annuleren", "account.direct": "@{name} een direct bericht sturen", + "account.disable_notifications": "Geef geen melding meer wanneer @{name} toot", "account.domain_blocked": "Server verborgen", "account.edit_profile": "Profiel bewerken", + "account.enable_notifications": "Geef een melding wanneer @{name} toot", "account.endorse": "Op profiel weergeven", "account.follow": "Volgen", "account.followers": "Volgers", "account.followers.empty": "Niemand volgt nog deze gebruiker.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} volger} other {{counter} volgers}}", + "account.following_counter": "{count, plural, one {{counter} volgend} other {{counter} volgend}}", "account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows_you": "Volgt jou", "account.hide_reblogs": "Verberg boosts van @{name}", @@ -36,7 +38,7 @@ "account.requested": "Wacht op goedkeuring. Klik om het volgverzoek te annuleren", "account.share": "Profiel van @{name} delen", "account.show_reblogs": "Toon boosts van @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} toot} other {{counter} toots}}", "account.unblock": "@{name} deblokkeren", "account.unblock_domain": "{domain} niet langer verbergen", "account.unendorse": "Niet op profiel weergeven", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Poll wijzigen om een enkele keuze toe te staan", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Media als gevoelig markeren", - "compose_form.sensitive.marked": "Media is als gevoelig gemarkeerd", - "compose_form.sensitive.unmarked": "Media is niet als gevoelig gemarkeerd", + "compose_form.sensitive.hide": "{count, plural, one {Media als gevoelig markeren} other {Media als gevoelig markeren}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is als gevoelig gemarkeerd} other {Media is als gevoelig gemarkeerd}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is niet als gevoelig gemarkeerd} other {Media is niet als gevoelig gemarkeerd}}", "compose_form.spoiler.marked": "Tekst is achter een waarschuwing verborgen", "compose_form.spoiler.unmarked": "Tekst is niet verborgen", "compose_form.spoiler_placeholder": "Waarschuwingstekst", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Zoekresultaten", "emoji_button.symbols": "Symbolen", "emoji_button.travel": "Reizen en plekken", + "empty_column.account_suspended": "Account opgeschort", "empty_column.account_timeline": "Hier zijn geen toots!", "empty_column.account_unavailable": "Profiel is niet beschikbaar", "empty_column.blocks": "Jij hebt nog geen enkele gebruiker geblokkeerd.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Je hebt nog geen meldingen. Begin met iemand een gesprek.", "empty_column.public": "Er is hier helemaal niks! Toot iets in het openbaar of volg mensen van andere servers om het te vullen", "error.unexpected_crash.explanation": "Als gevolg van een bug in onze broncode of als gevolg van een compatibiliteitsprobleem met jouw webbrowser, kan deze pagina niet goed worden weergegeven.", + "error.unexpected_crash.explanation_addons": "Deze pagina kon niet correct geladen worden. Deze fout wordt waarschijnlijk door een browser-add-on of een automatische vertalingshulpmiddel veroorzaakt.", "error.unexpected_crash.next_steps": "Probeer deze pagina te vernieuwen. Wanneer dit niet helpt is het nog steeds mogelijk om Mastodon in een andere webbrowser of mobiele app te gebruiken.", + "error.unexpected_crash.next_steps_addons": "Probeer deze uit te schakelen en de pagina te verversen. Wanneer dat niet helpt, kun je Mastodon nog altijd met een andere webbrowser of mobiele app gebruiken.", "errors.unexpected_crash.copy_stacktrace": "Stacktrace naar klembord kopiëren", "errors.unexpected_crash.report_issue": "Technisch probleem melden", "follow_request.authorize": "Goedkeuren", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "om het tekst- en zoekvak te ontfocussen", "keyboard_shortcuts.up": "om omhoog te bewegen in de lijst", "lightbox.close": "Sluiten", + "lightbox.compress": "Afbeelding passend weergeven", + "lightbox.expand": "Afbeelding groot weergeven", "lightbox.next": "Volgende", "lightbox.previous": "Vorige", - "lightbox.view_context": "Context tonen", "lists.account.add": "Aan lijst toevoegen", "lists.account.remove": "Uit lijst verwijderen", "lists.delete": "Lijst verwijderen", @@ -260,6 +266,10 @@ "lists.edit.submit": "Titel veranderen", "lists.new.create": "Lijst toevoegen", "lists.new.title_placeholder": "Naam nieuwe lijst", + "lists.replies_policy.followed": "Elke gevolgde gebruiker", + "lists.replies_policy.list": "Leden van de lijst", + "lists.replies_policy.none": "Niemand", + "lists.replies_policy.title": "Toon reacties aan:", "lists.search": "Zoek naar mensen die je volgt", "lists.subheading": "Jouw lijsten", "load_pending": "{count, plural, one {# nieuw item} other {# nieuwe items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Media verbergen", "missing_indicator.label": "Niet gevonden", "missing_indicator.sublabel": "Deze hulpbron kan niet gevonden worden", + "mute_modal.duration": "Duur", "mute_modal.hide_notifications": "Verberg meldingen van deze persoon?", + "mute_modal.indefinite": "Voor onbepaalde tijd", "navigation_bar.apps": "Mobiele apps", "navigation_bar.blocks": "Geblokkeerde gebruikers", "navigation_bar.bookmarks": "Bladwijzers", @@ -298,6 +310,7 @@ "notification.own_poll": "Jouw poll is beëindigd", "notification.poll": "Een poll waaraan jij hebt meegedaan is beëindigd", "notification.reblog": "{name} boostte jouw toot", + "notification.status": "{name} heeft zojuist een toot geplaatst", "notifications.clear": "Meldingen verwijderen", "notifications.clear_confirmation": "Weet je het zeker dat je al jouw meldingen wilt verwijderen?", "notifications.column_settings.alert": "Desktopmeldingen", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "In kolom tonen", "notifications.column_settings.sound": "Geluid afspelen", + "notifications.column_settings.status": "Nieuwe toots:", "notifications.filter.all": "Alles", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favorieten", "notifications.filter.follows": "Die jij volgt", "notifications.filter.mentions": "Vermeldingen", "notifications.filter.polls": "Pollresultaten", + "notifications.filter.statuses": "Updates van mensen die je volgt", + "notifications.grant_permission": "Toestemming geven.", "notifications.group": "{count} meldingen", + "notifications.mark_as_read": "Markeer elke melding als gelezen", + "notifications.permission_denied": "Desktopmeldingen zijn niet beschikbaar omdat een eerdere browsertoestemming werd geweigerd", + "notifications.permission_denied_alert": "Desktopmeldingen kunnen niet worden ingeschakeld, omdat een eerdere browsertoestemming werd geweigerd", + "notifications.permission_required": "Desktopmeldingen zijn niet beschikbaar omdat de benodigde toestemming niet is verleend.", + "notifications_permission_banner.enable": "Desktopmeldingen inschakelen", + "notifications_permission_banner.how_to_control": "Om meldingen te ontvangen wanneer Mastodon niet open is. Je kunt precies bepalen welke soort interacties wel of geen desktopmeldingen geven via de bovenstaande {icon} knop.", + "notifications_permission_banner.title": "Mis nooit meer iets", + "picture_in_picture.restore": "Terugzetten", "poll.closed": "Gesloten", "poll.refresh": "Vernieuwen", "poll.total_people": "{count, plural, one {# persoon} other {# mensen}}", @@ -423,12 +447,12 @@ "timeline_hint.resources.followers": "Volgers", "timeline_hint.resources.follows": "Volgend", "timeline_hint.resources.statuses": "Oudere toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, one {{counter} persoon} other {{counter} personen}} zijn aan het praten", "trends.trending_now": "Trends", "ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count} mrd.", + "units.short.million": "{count} mln.", + "units.short.thousand": "{count}k", "upload_area.title": "Hiernaar toe slepen om te uploaden", "upload_button.label": "Afbeeldingen, een video- of een geluidsbestand toevoegen", "upload_error.limit": "Uploadlimiet van bestand overschreden.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Omschrijf dit voor mensen met een auditieve beperking", "upload_form.description": "Omschrijf dit voor mensen met een visuele beperking", "upload_form.edit": "Bewerken", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Miniatuurafbeelding wijzigen", "upload_form.undo": "Verwijderen", "upload_form.video_description": "Omschrijf dit voor mensen met een auditieve of visuele beperking", "upload_modal.analyzing_picture": "Afbeelding analyseren…", "upload_modal.apply": "Toepassen", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Kies een afbeelding", "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", "upload_modal.detect_text": "Tekst in een afbeelding detecteren", "upload_modal.edit_media": "Media bewerken", "upload_modal.hint": "Klik of sleep de cirkel in de voorvertoning naar een centraal punt dat op elke thumbnail zichtbaar moet blijven.", + "upload_modal.preparing_ocr": "OCR voorbereiden…", "upload_modal.preview_label": "Voorvertoning ({ratio})", "upload_progress.label": "Uploaden...", "video.close": "Video sluiten", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index b567a35330d89d34132f767b3c5475e4a2b1c589..38a95533c7faf5e022727848139dcedecf649c37 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Merknad", "account.add_or_remove_from_list": "Legg til eller tak vekk frÃ¥ listene", "account.badges.bot": "Robot", "account.badges.group": "Gruppe", "account.block": "Blokker @{name}", "account.block_domain": "Skjul alt frÃ¥ {domain}", "account.blocked": "Blokkert", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "SjÃ¥ gjennom meir pÃ¥ den opphavlege profilen", "account.cancel_follow_request": "Fjern fylgjeførespurnad", "account.direct": "Send melding til @{name}", + "account.disable_notifications": "Slutt Ã¥ varsle meg nÃ¥r @{name} legger ut innlegg", "account.domain_blocked": "Domenet er gøymt", "account.edit_profile": "Rediger profil", + "account.enable_notifications": "Varsle meg nÃ¥r @{name} legger ut innlegg", "account.endorse": "Framhev pÃ¥ profil", "account.follow": "Fylg", "account.followers": "Fylgjarar", "account.followers.empty": "Ingen fylgjer denne brukaren enno.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} fylgjar} other {{counter} fylgjarar}}", + "account.following_counter": "{count, plural, one {{counter} fylgjar} other {{counter} fylgjar}}", "account.follows.empty": "Denne brukaren fylgjer ikkje nokon enno.", "account.follows_you": "Fylgjer deg", "account.hide_reblogs": "Gøym fremhevingar frÃ¥ @{name}", @@ -36,14 +38,14 @@ "account.requested": "Ventar pÃ¥ samtykke. Klikk for Ã¥ avbryta fylgjeførespurnaden", "account.share": "Del @{name} sin profil", "account.show_reblogs": "Vis framhevingar frÃ¥ @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tut}}", "account.unblock": "Slutt Ã¥ blokera @{name}", "account.unblock_domain": "Vis {domain}", "account.unendorse": "Ikkje framhev pÃ¥ profil", "account.unfollow": "Slutt Ã¥ fylgja", "account.unmute": "Av-demp @{name}", "account.unmute_notifications": "Vis varsel frÃ¥ @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Klikk for Ã¥ leggja til merknad", "alert.rate_limited.message": "Ver venleg Ã¥ prøva igjen etter {retry_time, time, medium}.", "alert.rate_limited.title": "Begrensa rate", "alert.unexpected.message": "Eit uventa problem oppstod.", @@ -54,7 +56,7 @@ "bundle_column_error.body": "Noko gjekk gale mens denne komponenten vart lasta ned.", "bundle_column_error.retry": "Prøv igjen", "bundle_column_error.title": "Nettverksfeil", - "bundle_modal_error.close": "Lukk", + "bundle_modal_error.close": "Lat att", "bundle_modal_error.message": "Noko gjekk gale under lastinga av denne komponenten.", "bundle_modal_error.retry": "Prøv igjen", "column.blocks": "Blokkerte brukarar", @@ -79,9 +81,9 @@ "column_header.show_settings": "Vis innstillingar", "column_header.unpin": "Løys", "column_subheading.settings": "Innstillingar", - "community.column_settings.local_only": "Kun lokalt", + "community.column_settings.local_only": "Berre lokalt", "community.column_settings.media_only": "Berre media", - "community.column_settings.remote_only": "Kun eksternt", + "community.column_settings.remote_only": "Berre eksternt", "compose_form.direct_message_warning": "Dette tutet vert berre synleg for nemnde brukarar.", "compose_form.direct_message_warning_learn_more": "Lær meir", "compose_form.hashtag_warning": "Dette tutet vert ikkje oppført under nokon emneknagg sidan det ikkje er oppført. Berre offentlege tut kan verta søkt etter med emneknagg.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Søkeresultat", "emoji_button.symbols": "Symbol", "emoji_button.travel": "Reise & stader", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ingen tut her!", "empty_column.account_unavailable": "Profil ikkje tilgjengelig", "empty_column.blocks": "Du har ikkje blokkert nokon brukarar enno.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Du har ingen varsel ennÃ¥. Kommuniser med andre for Ã¥ starte samtalen.", "empty_column.public": "Det er ingenting her! Skriv noko offentleg, eller følg brukarar frÃ¥ andre tenarar manuelt for Ã¥ fylle det opp", "error.unexpected_crash.explanation": "PÃ¥ grunn av ein feil i vÃ¥r kode eller eit nettlesarkompatibilitetsproblem, kunne ikkje denne sida verte vist korrekt.", + "error.unexpected_crash.explanation_addons": "Denne siden kunne ikke vises riktig. Denne feilen er sannsynligvis forÃ¥rsaket av en nettleserutvidelse eller automatiske oversettelsesverktøy.", "error.unexpected_crash.next_steps": "Prøv Ã¥ lasta inn sida pÃ¥ nytt. Om det ikkje hjelper sÃ¥ kan du framleis nytta Mastodon i ein annan nettlesar eller app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopier stacktrace til utklippstavla", "errors.unexpected_crash.report_issue": "Rapporter problem", "follow_request.authorize": "Autoriser", "follow_request.reject": "Avvis", - "follow_requests.unlocked_explanation": "Selv om kontoen din ikke er lÃ¥st, tror {domain} ansatte at du kanskje vil gjennomgÃ¥ forespørsler fra disse kontoene manuelt.", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "Sjølv om kontoen din ikkje er lÃ¥st tenkte {domain} tilsette at du ville gÃ¥ gjennom førespurnadar frÃ¥ desse kontoane manuelt.", + "generic.saved": "Lagra", "getting_started.developers": "Utviklarar", "getting_started.directory": "Profilkatalog", "getting_started.documentation": "Dokumentasjon", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "for Ã¥ svara", "keyboard_shortcuts.requests": "for Ã¥ opna lista med fylgjeførespurnader", "keyboard_shortcuts.search": "for Ã¥ fokusera søket", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "for Ã¥ visa/gøyma CW-felt", "keyboard_shortcuts.start": "for Ã¥ opna \"kom i gang\"-feltet", "keyboard_shortcuts.toggle_hidden": "for Ã¥ visa/gøyma tekst bak innhaldsvarsel", "keyboard_shortcuts.toggle_sensitivity": "for Ã¥ visa/gøyma media", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "for Ã¥ fokusere vekk skrive-/søkefeltet", "keyboard_shortcuts.up": "for Ã¥ flytta seg opp pÃ¥ lista", "lightbox.close": "Lukk att", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Neste", "lightbox.previous": "Førre", - "lightbox.view_context": "SjÃ¥ kontekst", "lists.account.add": "Legg til i liste", "lists.account.remove": "Fjern frÃ¥ liste", "lists.delete": "Slett liste", @@ -260,6 +266,10 @@ "lists.edit.submit": "Endre tittel", "lists.new.create": "Legg til liste", "lists.new.title_placeholder": "Ny listetittel", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Vis svar pÃ¥:", "lists.search": "Søk gjennom folk du følgjer", "lists.subheading": "Dine lister", "load_pending": "{count, plural, one {# nytt element} other {# nye element}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Gjer synleg/usynleg", "missing_indicator.label": "Ikkje funne", "missing_indicator.sublabel": "Fann ikkje ressursen", + "mute_modal.duration": "Varighet", "mute_modal.hide_notifications": "Gøyme varsel frÃ¥ denne brukaren?", + "mute_modal.indefinite": "PÃ¥ ubestemt tid", "navigation_bar.apps": "Mobilappar", "navigation_bar.blocks": "Blokkerte brukarar", "navigation_bar.bookmarks": "Bokmerke", @@ -298,6 +310,7 @@ "notification.own_poll": "Rundspørjinga di er ferdig", "notification.poll": "Ei rundspørjing du har røysta i er ferdig", "notification.reblog": "{name} framheva statusen din", + "notification.status": "{name} la nettopp ut", "notifications.clear": "Tøm varsel", "notifications.clear_confirmation": "Er du sikker pÃ¥ at du vil fjerna alle varsla dine for alltid?", "notifications.column_settings.alert": "Skrivebordsvarsel", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Framhevingar:", "notifications.column_settings.show": "Vis i kolonne", "notifications.column_settings.sound": "Spel av lyd", + "notifications.column_settings.status": "Nye tuter:", "notifications.filter.all": "Alle", "notifications.filter.boosts": "Framhevingar", "notifications.filter.favourites": "Favorittar", "notifications.filter.follows": "Fylgjer", "notifications.filter.mentions": "Nemningar", "notifications.filter.polls": "Røysteresultat", + "notifications.filter.statuses": "Oppdateringer fra folk du følger", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} varsel", + "notifications.mark_as_read": "Merk alle varsler som lest", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Skru pÃ¥ skrivebordsvarsler", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Aldri gÃ¥ glipp av noe", + "picture_in_picture.restore": "Legg den tilbake", "poll.closed": "Lukka", "poll.refresh": "Oppdater", "poll.total_people": "{count, plural, one {# person} other {# folk}}", @@ -419,33 +443,34 @@ "time_remaining.minutes": "{number, plural, one {# minutt} other {# minutt}} igjen", "time_remaining.moments": "Kort tid igjen", "time_remaining.seconds": "{number, plural, one {# sekund} other {# sekund}} igjen", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "{resource} frÃ¥ andre tenarar synest ikkje.", + "timeline_hint.resources.followers": "Fylgjarar", + "timeline_hint.resources.follows": "Fylgjer", + "timeline_hint.resources.statuses": "Eldre tut", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} folk}} pratar", "trends.trending_now": "Populært no", "ui.beforeunload": "Kladden din forsvinn om du forlèt Mastodon no.", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Drag & slepp for Ã¥ lasta opp", - "upload_button.label": "Legg til medium ({formats})", + "upload_button.label": "Legg til medium", "upload_error.limit": "Du har gÃ¥tt over opplastingsgrensa.", "upload_error.poll": "Filopplasting ikkje tillate med meiningsmÃ¥lingar.", "upload_form.audio_description": "Grei ut for folk med nedsett høyrsel", "upload_form.description": "Skildr for synshemja", "upload_form.edit": "Rediger", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Bytt miniatyrbilete", "upload_form.undo": "Slett", "upload_form.video_description": "Greit ut for folk med nedsett høyrsel eller syn", "upload_modal.analyzing_picture": "Analyserer bilete…", "upload_modal.apply": "Bruk", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Vel bilete", "upload_modal.description_placeholder": "Ein rask brun rev hoppar over den late hunden", "upload_modal.detect_text": "Gjenkjenn tekst i biletet", "upload_modal.edit_media": "Rediger medium", "upload_modal.hint": "Klikk og dra sirkelen pÃ¥ førehandsvisninga for Ã¥ velge fokuspunktet som alltid vil vere synleg pÃ¥ alle miniatyrbileta.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Førehandsvis ({ratio})", "upload_progress.label": "Lastar opp...", "video.close": "Lukk video", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index a15e96fdc2d193eda23186e415dea345ba585e84..e64bf4a5a4e9c0f5bfbe5ea48ede0be7d9c6a920 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Notis", "account.add_or_remove_from_list": "Legg til eller fjern fra lister", "account.badges.bot": "Bot", "account.badges.group": "Gruppe", "account.block": "Blokkér @{name}", "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blokkert", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Bla mer pÃ¥ den opprinnelige profilen", "account.cancel_follow_request": "Avbryt følge forespørsel", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Slutt Ã¥ varsle meg nÃ¥r @{name} legger ut innlegg", "account.domain_blocked": "Domenet skjult", "account.edit_profile": "Rediger profil", + "account.enable_notifications": "Varsle meg nÃ¥r @{name} legger ut innlegg", "account.endorse": "Vis frem pÃ¥ profilen", "account.follow": "Følg", "account.followers": "Følgere", "account.followers.empty": "Ingen følger denne brukeren ennÃ¥.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} følger} other {{counter} følgere}}", + "account.following_counter": "{count, plural, one {{counter} som følges} other {{counter} som følges}}", "account.follows.empty": "Denne brukeren følger ikke noen enda.", "account.follows_you": "Følger deg", "account.hide_reblogs": "Skjul fremhevinger fra @{name}", @@ -36,14 +38,14 @@ "account.requested": "Venter pÃ¥ godkjennelse", "account.share": "Del @{name}s profil", "account.show_reblogs": "Vis boosts fra @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tuter}}", "account.unblock": "Avblokker @{name}", "account.unblock_domain": "Vis {domain}", "account.unendorse": "Ikke vis frem pÃ¥ profilen", "account.unfollow": "Avfølg", "account.unmute": "Avdemp @{name}", "account.unmute_notifications": "Vis varsler fra @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Klikk for Ã¥ legge til et notat", "alert.rate_limited.message": "Vennligst prøv igjen etter kl. {retry_time, time, medium}.", "alert.rate_limited.title": "Hastighetsbegrenset", "alert.unexpected.message": "En uventet feil oppstod.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Søkeresultat", "emoji_button.symbols": "Symboler", "emoji_button.travel": "Reise & steder", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Ingen tuter er her!", "empty_column.account_unavailable": "Profilen er utilgjengelig", "empty_column.blocks": "Du har ikke blokkert noen brukere enda.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Du har ingen varsler ennÃ¥. Kommuniser med andre for Ã¥ begynne samtalen.", "empty_column.public": "Det er ingenting her! Skriv noe offentlig, eller følg brukere manuelt fra andre instanser for Ã¥ fylle den opp", "error.unexpected_crash.explanation": "PÃ¥ grunn av en bug i koden vÃ¥r eller et nettleserkompatibilitetsproblem, kunne denne siden ikke vises riktig.", + "error.unexpected_crash.explanation_addons": "Denne siden kunne ikke vises riktig. Denne feilen er sannsynligvis forÃ¥rsaket av en nettleserutvidelse eller automatiske oversettelsesverktøy.", "error.unexpected_crash.next_steps": "Prøv Ã¥ oppfriske siden. Dersom det ikke hjelper, vil du kanskje fortsatt kunne bruke Mastodon gjennom en annen nettleser eller app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Kopier stacktrace-en til utklippstavlen", "errors.unexpected_crash.report_issue": "Rapporter en feil", "follow_request.authorize": "Autorisér", "follow_request.reject": "Avvis", "follow_requests.unlocked_explanation": "Selv om kontoen din ikke er lÃ¥st, tror {domain} ansatte at du kanskje vil gjennomgÃ¥ forespørsler fra disse kontoene manuelt.", - "generic.saved": "Saved", + "generic.saved": "Lagret", "getting_started.developers": "Utviklere", "getting_started.directory": "Profilmappe", "getting_started.documentation": "Dokumentasjon", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "Ã¥ ufokusere komponerings-/søkefeltet", "keyboard_shortcuts.up": "Ã¥ flytte opp i listen", "lightbox.close": "Lukk", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Neste", "lightbox.previous": "Forrige", - "lightbox.view_context": "Vis sammenheng", "lists.account.add": "Legg til i listen", "lists.account.remove": "Fjern fra listen", "lists.delete": "Slett listen", @@ -260,6 +266,10 @@ "lists.edit.submit": "Endre tittel", "lists.new.create": "Ligg til liste", "lists.new.title_placeholder": "Ny listetittel", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Vis svar pÃ¥:", "lists.search": "Søk blant personer du følger", "lists.subheading": "Dine lister", "load_pending": "{count, plural,one {# ny gjenstand} other {# nye gjenstander}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Veksle synlighet", "missing_indicator.label": "Ikke funnet", "missing_indicator.sublabel": "Denne ressursen ble ikke funnet", + "mute_modal.duration": "Varighet", "mute_modal.hide_notifications": "Skjul varslinger fra denne brukeren?", + "mute_modal.indefinite": "PÃ¥ ubestemt tid", "navigation_bar.apps": "Mobilapper", "navigation_bar.blocks": "Blokkerte brukere", "navigation_bar.bookmarks": "Bokmerker", @@ -298,6 +310,7 @@ "notification.own_poll": "Avstemningen din er ferdig", "notification.poll": "En avstemning du har stemt pÃ¥ har avsluttet", "notification.reblog": "{name} fremhevde din status", + "notification.status": "{name} la nettopp ut", "notifications.clear": "Fjern varsler", "notifications.clear_confirmation": "Er du sikker pÃ¥ at du vil fjerne alle dine varsler permanent?", "notifications.column_settings.alert": "Skrivebordsvarslinger", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Fremhevet:", "notifications.column_settings.show": "Vis i kolonne", "notifications.column_settings.sound": "Spill lyd", + "notifications.column_settings.status": "Nye tuter:", "notifications.filter.all": "Alle", "notifications.filter.boosts": "Fremhevinger", "notifications.filter.favourites": "Favoritter", "notifications.filter.follows": "Følginger", "notifications.filter.mentions": "Nevnelser", "notifications.filter.polls": "Avstemningsresultater", + "notifications.filter.statuses": "Oppdateringer fra folk du følger", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} varslinger", + "notifications.mark_as_read": "Merk alle varsler som lest", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Skru pÃ¥ skrivebordsvarsler", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Aldri gÃ¥ glipp av noe", + "picture_in_picture.restore": "Legg den tilbake", "poll.closed": "Lukket", "poll.refresh": "Oppdater", "poll.total_people": "{count, plural, one {# person} other {# personer}}", @@ -420,15 +444,15 @@ "time_remaining.moments": "Gjenværende øyeblikk", "time_remaining.seconds": "{number, plural, one {# sekund} other {# sekunder}} igjen", "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.resources.followers": "Følgere", + "timeline_hint.resources.follows": "Følger", + "timeline_hint.resources.statuses": "Eldre tuter", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} personer}} snakker", "trends.trending_now": "Trender nÃ¥", "ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count}m.ard", + "units.short.million": "{count}mill", + "units.short.thousand": "{count}T", "upload_area.title": "Dra og slipp for Ã¥ laste opp", "upload_button.label": "Legg til media", "upload_error.limit": "Filopplastingsgrensen er oversteget.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Beskriv det for folk med hørselstap", "upload_form.description": "Beskriv for synshemmede", "upload_form.edit": "Rediger", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Endre miniatyrbilde", "upload_form.undo": "Angre", "upload_form.video_description": "Beskriv det for folk med hørselstap eller synshemminger", "upload_modal.analyzing_picture": "Analyserer bildet …", "upload_modal.apply": "Bruk", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Velg et bilde", "upload_modal.description_placeholder": "NÃ¥r du en gang kommer, neste sommer, skal vi atter drikke vin", "upload_modal.detect_text": "Oppdag tekst i bildet", "upload_modal.edit_media": "Rediger media", "upload_modal.hint": "Klikk eller dra sirkelen i forhÃ¥ndsvisningen for Ã¥ velge hovedpunktet som alltid vil bli vist i alle miniatyrbilder.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "ForhÃ¥ndsvisning ({ratio})", "upload_progress.label": "Laster opp...", "video.close": "Lukk video", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 1aa0193a527b0e66f03ab527d5ee2817e97fbcc7..f56d337d3c1ca7464707cb7bbf84cc905342196b 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Navigar sul perfil original", "account.cancel_follow_request": "Anullar la demanda de seguiment", "account.direct": "Escriure un MP a @{name}", + "account.disable_notifications": "Quitar de m’avisar quand @{name} publica quicòm", "account.domain_blocked": "Domeni amagat", "account.edit_profile": "Modificar lo perfil", + "account.enable_notifications": "M’avisar quand @{name} publica quicòm", "account.endorse": "Mostrar pel perfil", "account.follow": "Sègre", "account.followers": "Seguidors", "account.followers.empty": "Degun sèc pas aqueste utilizaire pel moment.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidors}}", + "account.following_counter": "{count, plural, one {{counter} Abonaments} other {{counter} Abonaments}}", "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.", "account.follows_you": "Vos sèc", "account.hide_reblogs": "Rescondre los partatges de @{name}", @@ -36,7 +38,7 @@ "account.requested": "Invitacion mandada. Clicatz per anullar", "account.share": "Partejar lo perfil a @{name}", "account.show_reblogs": "Mostrar los partatges de @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} Tut} other {{counter} Tuts}}", "account.unblock": "Desblocar @{name}", "account.unblock_domain": "Desblocar {domain}", "account.unendorse": "Mostrar pas pel perfil", @@ -85,7 +87,7 @@ "compose_form.direct_message_warning": "Sols los mencionats poirà n veire aqueste tut.", "compose_form.direct_message_warning_learn_more": "Ne saber mai", "compose_form.hashtag_warning": "Aqueste tut serà pas ligat a cap d’etiqueta estant qu’es pas listat. Ã’m pòt pas cercar que los tuts publics per etiqueta.", - "compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo monde pòt vos sègre e veire los estatuts reservats als seguidors.", + "compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo mond pòt vos sègre e veire los estatuts reservats als seguidors.", "compose_form.lock_disclaimer.lock": "clavat", "compose_form.placeholder": "A de qué pensatz ?", "compose_form.poll.add_option": "Ajustar una causida", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultats de recèrca", "emoji_button.symbols": "Simbòls", "emoji_button.travel": "Viatges & lòcs", + "empty_column.account_suspended": "Compte suspendut", "empty_column.account_timeline": "Cap de tuts aquÃ !", "empty_column.account_unavailable": "Perfil pas disponible", "empty_column.blocks": "Avètz pas blocat degun pel moment.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualqu’un per començar una conversacion.", "empty_column.public": "I a pas res aquÃ ! Escrivètz quicòm de public, o seguètz de personas d’autres servidors per garnir lo flux public", "error.unexpected_crash.explanation": "A causa d’una avaria dins nòstre còdi o d’un problèma de compatibilitat de navegador, aquesta pagina se pòt pas afichar corrèctament.", + "error.unexpected_crash.explanation_addons": "Aquesta pagina podiá pas s’afichar corrèctament. Aquesta error arriba sovent a causa d’un modul complementari de navigador o una aisina de traduccion automatica.", "error.unexpected_crash.next_steps": "Ensajatz d’actualizar la pagina. S’aquò cà mbia pas res, podètz provar d’utilizar Mastodon via un navegador diferent o d’una aplicacion nativa estant.", + "error.unexpected_crash.next_steps_addons": "Ensajatz de los desactivar o actualizatz la pagina. Se aquò ajuda pas, podètz ensajar d’utilizar Mastodon via un autre navigador o una aplicacion nativa.", "errors.unexpected_crash.copy_stacktrace": "Copiar las traças al quichapapièrs", "errors.unexpected_crash.report_issue": "Senhalar un problèma", "follow_request.authorize": "Acceptar", @@ -177,7 +182,7 @@ "getting_started.directory": "Annuari de perfils", "getting_started.documentation": "Documentacion", "getting_started.heading": "Per començar", - "getting_started.invite": "Convidar de monde", + "getting_started.invite": "Convidar de mond", "getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {github} sus GitHub.", "getting_started.security": "Seguretat", "getting_started.terms": "Condicions d’utilizacion", @@ -202,9 +207,9 @@ "introduction.federation.federated.headline": "Federat", "introduction.federation.federated.text": "Los tuts publics d’autres servidors del fediverse apareisserà n dins lo flux d’actualitats.", "introduction.federation.home.headline": "Acuèlh", - "introduction.federation.home.text": "Los tuts del monde que seguètz apareisserà n dins vòstre flux d’acuèlh. Podètz sègre de monde ont que siasquen !", + "introduction.federation.home.text": "Los tuts del mond que seguètz apareisserà n dins vòstre flux d’acuèlh. Podètz sègre de mond ont que siasquen !", "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Los tuts publics del monde del meteis servidor que vosautres apareisserà n dins lo flux local.", + "introduction.federation.local.text": "Los tuts publics del mond del meteis servidor que vosautres apareisserà n dins lo flux local.", "introduction.interactions.action": "Acabar la leiçon !", "introduction.interactions.favourite.headline": "Favorit", "introduction.interactions.favourite.text": "Podètz enregistrar un tut per mai tard, e avisar l’autor que l’avètz aimat, en l’ajustant als favorits.", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "quitar lo camp tèxte/de recèrca", "keyboard_shortcuts.up": "far montar dins la lista", "lightbox.close": "Tampar", + "lightbox.compress": "Fenèstra de visualizacion dels imatges compressats", + "lightbox.expand": "Espandir la fenèstra de visualizacion d’imatge", "lightbox.next": "Seguent", "lightbox.previous": "Precedent", - "lightbox.view_context": "Veire lo contèxt", "lists.account.add": "Ajustar a la lista", "lists.account.remove": "Levar de la lista", "lists.delete": "Suprimir la lista", @@ -260,14 +266,20 @@ "lists.edit.submit": "Cambiar lo tÃtol", "lists.new.create": "Ajustar una lista", "lists.new.title_placeholder": "TÃtol de la nòva lista", - "lists.search": "Cercar demest lo monde que seguètz", + "lists.replies_policy.followed": "Quin seguidor que siá", + "lists.replies_policy.list": "Membres de la lista", + "lists.replies_policy.none": "Degun", + "lists.replies_policy.title": "Mostrar las responsas a :", + "lists.search": "Cercar demest lo mond que seguètz", "lists.subheading": "Vòstras listas", "load_pending": "{count, plural, one {# nòu element} other {# nòu elements}}", "loading_indicator.label": "Cargament…", "media_gallery.toggle_visible": "Modificar la visibilitat", "missing_indicator.label": "Pas trobat", "missing_indicator.sublabel": "Aquesta ressorsa es pas estada trobada", + "mute_modal.duration": "Durada", "mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?", + "mute_modal.indefinite": "Cap de data de fin", "navigation_bar.apps": "Aplicacions mobil", "navigation_bar.blocks": "Personas blocadas", "navigation_bar.bookmarks": "Marcadors", @@ -298,6 +310,7 @@ "notification.own_poll": "Vòstre sondatge es acabat", "notification.poll": "Avètz participat a un sondatge que ven de s’acabar", "notification.reblog": "{name} a partejat vòstre estatut", + "notification.status": "{name} ven de publicar", "notifications.clear": "Escafar", "notifications.clear_confirmation": "Volètz vertadièrament escafar totas vòstras las notificacions ?", "notifications.column_settings.alert": "Notificacions localas", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Partatges :", "notifications.column_settings.show": "Mostrar dins la colomna", "notifications.column_settings.sound": "Emetre un son", + "notifications.column_settings.status": "Tuts novèls :", "notifications.filter.all": "Totas", "notifications.filter.boosts": "Partages", "notifications.filter.favourites": "Favorits", "notifications.filter.follows": "Seguiments", "notifications.filter.mentions": "Mencions", "notifications.filter.polls": "Resultats del sondatge", + "notifications.filter.statuses": "Mesas a jorn del monde que seguissètz", + "notifications.grant_permission": "Acordar l’autorizacion.", "notifications.group": "{count} notificacions", + "notifications.mark_as_read": "Marcar totas las notificacions coma legidas", + "notifications.permission_denied": "Las notificacion burèu son pas disponiblas a causa del refús de las demandas d’autorizacion navigador", + "notifications.permission_denied_alert": "Las notificacions burèu son pas activada, per çò que las autorizacions son estadas refusada abans", + "notifications.permission_required": "Las notificacions de burèu son pas indisponiblas perque las permissions requeridas son pas estadas acordadas.", + "notifications_permission_banner.enable": "Activar las notificacions burèu", + "notifications_permission_banner.how_to_control": "Per recebre las notificacions de Mastodon quand es pas dobèrt, activatz las notificacions de burèu. Podètz precisar quin tipe de notificacion generarà una notificacion de burèu via lo boton {icon} dessús un còp activadas.", + "notifications_permission_banner.title": "Manquetz pas jamai res", + "picture_in_picture.restore": "Lo tornar", "poll.closed": "Tampat", "poll.refresh": "Actualizar", "poll.total_people": "{count, plural, one {# persona} other {# personas}}", @@ -423,7 +447,7 @@ "timeline_hint.resources.followers": "Seguidors", "timeline_hint.resources.follows": "Abonaments", "timeline_hint.resources.statuses": "Tuts mai ancians", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, one {{counter} persona ne parla} other {{counter} personas ne parlan}}", "trends.trending_now": "Tendéncia del moment", "ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.", "units.short.billion": "{count}B", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Descriure per las personas amb pèrdas auditivas", "upload_form.description": "Descripcion pels mal vesents", "upload_form.edit": "Modificar", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Cambiar la vinheta", "upload_form.undo": "Suprimir", "upload_form.video_description": "Descriure per las personas amb pèrdas auditivas o mal vesent", "upload_modal.analyzing_picture": "Analisi de l’imatge…", "upload_modal.apply": "Aplicar", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Causir un imatge", "upload_modal.description_placeholder": "Lo dròlle bilingüe manja un yaourt de ròcs exagonals e kiwis verds farà un an mai", "upload_modal.detect_text": "Detectar lo tèxt de l’imatge", "upload_modal.edit_media": "Modificar lo mèdia", "upload_modal.hint": "Clicatz o lisatz lo cercle de l’apercebut per causir lo ponch que serà totjorn visible dins las vinhetas.", + "upload_modal.preparing_ocr": "Preparacion de la ROC…", "upload_modal.preview_label": "Apercebut ({ratio})", "upload_progress.label": "MandadÃs…", "video.close": "Tampar la vidèo", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 4e0230b75815b5b0869d85cbd7f39c2347c24502..0af58e3513b7230f6649345e825d460a9a08d77b 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -1,5 +1,5 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Notatka", "account.add_or_remove_from_list": "Dodaj lub usuÅ„ z list", "account.badges.bot": "Bot", "account.badges.group": "Grupa", @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Zobacz wiÄ™cej na oryginalnym profilu", "account.cancel_follow_request": "Zrezygnuj z proÅ›by o możliwość Å›ledzenia", "account.direct": "WyÅ›lij wiadomość bezpoÅ›redniÄ… do @{name}", + "account.disable_notifications": "PrzestaÅ„ powiadamiać mnie o wpisach @{name}", "account.domain_blocked": "Ukryto domenÄ™", "account.edit_profile": "Edytuj profil", - "account.endorse": "Polecaj na profilu", + "account.enable_notifications": "Powiadamiaj mnie o wpisach @{name}", + "account.endorse": "Wyróżnij na profilu", "account.follow": "Åšledź", "account.followers": "ÅšledzÄ…cy", "account.followers.empty": "Nikt jeszcze nie Å›ledzi tego użytkownika.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Å›ledzÄ…cy} few {{counter} Å›ledzÄ…cych} many {{counter} Å›ledzÄ…cych} other {{counter} Å›ledzÄ…cych}}", + "account.following_counter": "{count, plural, one {{counter} Å›ledzony} few {{counter} Å›ledzonych} many {{counter} Å›ledzonych} other {{counter} Å›ledzonych}}", "account.follows.empty": "Ten użytkownik nie Å›ledzi jeszcze nikogo.", "account.follows_you": "Åšledzi CiÄ™", "account.hide_reblogs": "Ukryj podbicia od @{name}", @@ -36,14 +38,14 @@ "account.requested": "OczekujÄ…ca proÅ›ba, kliknij aby anulować", "account.share": "UdostÄ™pnij profil @{name}", "account.show_reblogs": "Pokazuj podbicia od @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} wpis} few {{counter} wpisy} many {{counter} wpisów} other {{counter} wpisów}}", "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenÄ™ {domain}", "account.unendorse": "PrzestaÅ„ polecać", "account.unfollow": "PrzestaÅ„ Å›ledzić", "account.unmute": "Cofnij wyciszenie @{name}", "account.unmute_notifications": "Cofnij wyciszenie powiadomieÅ„ od @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "NaciÅ›nij aby dodać notatkÄ™", "alert.rate_limited.message": "Spróbuj ponownie po {retry_time, time, medium}.", "alert.rate_limited.title": "Ograniczony czasowo", "alert.unexpected.message": "WystÄ…piÅ‚ nieoczekiwany błąd.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Wyniki wyszukiwania", "emoji_button.symbols": "Symbole", "emoji_button.travel": "Podróże i miejsca", + "empty_column.account_suspended": "Konto zawieszone", "empty_column.account_timeline": "Brak wpisów tutaj!", "empty_column.account_unavailable": "Profil niedostÄ™pny", "empty_column.blocks": "Nie zablokowaÅ‚eÅ›(-aÅ›) jeszcze żadnego użytkownika.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Nie masz żadnych powiadomieÅ„. Rozpocznij interakcje z innymi użytkownikami.", "empty_column.public": "Tu nic nie ma! Napisz coÅ› publicznie, lub dodaj ludzi z innych serwerów, aby to wyÅ›wietlić", "error.unexpected_crash.explanation": "W zwiÄ…zku z błędem w naszym kodzie lub braku kompatybilnoÅ›ci przeglÄ…darki, ta strona nie może być poprawnie wyÅ›wietlona.", + "error.unexpected_crash.explanation_addons": "Ta strona nie mogÅ‚a zostać poprawnie wyÅ›wietlona. Może to być spowodowane dodatkiem do przeglÄ…darki lub narzÄ™dziem do automatycznego tÅ‚umaczenia.", "error.unexpected_crash.next_steps": "Spróbuj odÅ›wieżyć stronÄ™. JeÅ›li to nie pomoże, wciąż jesteÅ› w stanie używać Mastodona przez innÄ… przeglÄ…darkÄ™ lub natywnÄ… aplikacjÄ™.", + "error.unexpected_crash.next_steps_addons": "Spróbuj je wyłączyć lub odÅ›wieżyć stronÄ™. JeÅ›li to nie pomoże, możesz wciąż korzystać z Mastodona w innej przeglÄ…darce lub natywnej aplikacji.", "errors.unexpected_crash.copy_stacktrace": "Skopiuj Å›lad stosu do schowka", "errors.unexpected_crash.report_issue": "ZgÅ‚oÅ› problem", "follow_request.authorize": "Autoryzuj", "follow_request.reject": "Odrzuć", "follow_requests.unlocked_explanation": "Mimo że Twoje konto nie jest zablokowane, zespół {domain} uznaÅ‚ że możesz chcieć rÄ™cznie przejrzeć proÅ›by o możliwość Å›ledzenia.", - "generic.saved": "Saved", + "generic.saved": "Zapisano", "getting_started.developers": "Dla programistów", "getting_started.directory": "Katalog profilów", "getting_started.documentation": "Dokumentacja", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "aby opuÅ›cić pole wyszukiwania/pisania", "keyboard_shortcuts.up": "aby przejść na górÄ™ listy", "lightbox.close": "Zamknij", + "lightbox.compress": "Zmniejsz pole widoku obrazu", + "lightbox.expand": "RozwiÅ„ pole widoku obrazu", "lightbox.next": "NastÄ™pne", "lightbox.previous": "Poprzednie", - "lightbox.view_context": "Pokaż kontekst", "lists.account.add": "Dodaj do listy", "lists.account.remove": "Usunąć z listy", "lists.delete": "UsuÅ„ listÄ™", @@ -260,6 +266,10 @@ "lists.edit.submit": "ZmieÅ„ tytuÅ‚", "lists.new.create": "Utwórz listÄ™", "lists.new.title_placeholder": "Wprowadź tytuÅ‚ listy", + "lists.replies_policy.followed": "Dowolny obserwowany użytkownik", + "lists.replies_policy.list": "CzÅ‚onkowie listy", + "lists.replies_policy.none": "Nikt", + "lists.replies_policy.title": "Pokazuj odpowiedzi dla:", "lists.search": "Szukaj wÅ›ród osób które Å›ledzisz", "lists.subheading": "Twoje listy", "load_pending": "{count, plural, one {# nowy przedmiot} other {nowe przedmioty}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Przełącz widoczność", "missing_indicator.label": "Nie znaleziono", "missing_indicator.sublabel": "Nie można odnaleźć tego zasobu", + "mute_modal.duration": "Czas", "mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?", + "mute_modal.indefinite": "NieokreÅ›lony", "navigation_bar.apps": "Aplikacje mobilne", "navigation_bar.blocks": "Zablokowani użytkownicy", "navigation_bar.bookmarks": "ZakÅ‚adki", @@ -298,6 +310,7 @@ "notification.own_poll": "Twoje gÅ‚osowanie zakoÅ„czyÅ‚o siÄ™", "notification.poll": "GÅ‚osowanie w którym braÅ‚eÅ›(-aÅ›) udziaÅ‚ zakoÅ„czyÅ‚a siÄ™", "notification.reblog": "{name} podbiÅ‚(a) Twój wpis", + "notification.status": "{name} wÅ‚aÅ›nie utworzyÅ‚(a) wpis", "notifications.clear": "Wyczyść powiadomienia", "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", "notifications.column_settings.alert": "Powiadomienia na pulpicie", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Podbicia:", "notifications.column_settings.show": "Pokaż w kolumnie", "notifications.column_settings.sound": "Odtwarzaj dźwiÄ™k", + "notifications.column_settings.status": "Nowe wpisy:", "notifications.filter.all": "Wszystkie", "notifications.filter.boosts": "Podbicia", "notifications.filter.favourites": "Ulubione", "notifications.filter.follows": "Åšledzenia", "notifications.filter.mentions": "Wspomienia", "notifications.filter.polls": "Wyniki gÅ‚osowania", + "notifications.filter.statuses": "Aktualizacje od osób które obserwujesz", + "notifications.grant_permission": "Przyznaj uprawnienia.", "notifications.group": "{count, number} {count, plural, one {powiadomienie} few {powiadomienia} many {powiadomieÅ„} more {powiadomieÅ„}}", + "notifications.mark_as_read": "Oznacz wszystkie powiadomienia jako przeczytane", + "notifications.permission_denied": "Powiadomienia na pulpicie nie sÄ… dostÄ™pne, ponieważ wczeÅ›niej nie udzielono uprawnieÅ„ w przeglÄ…darce", + "notifications.permission_denied_alert": "Powiadomienia na pulpicie nie mogÄ… zostać włączone, ponieważ wczeÅ›niej odmówiono uprawnieÅ„", + "notifications.permission_required": "Powiadomienia na pulpicie nie sÄ… dostÄ™pne, ponieważ nie przyznano wymaganego uprawnienia.", + "notifications_permission_banner.enable": "Włącz powiadomienia na pulpicie", + "notifications_permission_banner.how_to_control": "Aby otrzymywać powiadomienia, gdy Mastodon nie jest otwarty, włącz powiadomienia pulpitu. Możesz dokÅ‚adnie kontrolować, októrych dziaÅ‚aniach bÄ™dziesz powiadomienia na pulpicie za pomocÄ… przycisku {icon} powyżej, jeżeli tylko zostanÄ… włączone.", + "notifications_permission_banner.title": "Nie przegap niczego", + "picture_in_picture.restore": "Odłóż", "poll.closed": "ZamkniÄ™te", "poll.refresh": "OdÅ›wież", "poll.total_people": "{count, plural, one {# osoba} few {# osoby} many {# osób} other {# osób}}", @@ -423,12 +447,12 @@ "timeline_hint.resources.followers": "ÅšledzÄ…cy", "timeline_hint.resources.follows": "Åšledzeni", "timeline_hint.resources.statuses": "Starsze wpisy", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "rozmawiajÄ…: {count, plural, one {{counter} osoba} few {{counter} osoby} many {{counter} osób} other {{counter} osoby}}", "trends.trending_now": "Popularne teraz", "ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuÅ›cisz Mastodona.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count} mld", + "units.short.million": "{count} mln", + "units.short.thousand": "{count} tys.", "upload_area.title": "PrzeciÄ…gnij i upuść aby wysÅ‚ać", "upload_button.label": "Dodaj zawartość multimedialnÄ… (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Przekroczono limit plików do wysÅ‚ania.", @@ -436,16 +460,17 @@ "upload_form.audio_description": "Opisz dla osób niesÅ‚yszÄ…cych i niedosÅ‚yszÄ…cych", "upload_form.description": "Wprowadź opis dla niewidomych i niedowidzÄ…cych", "upload_form.edit": "Edytuj", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "ZmieÅ„ miniaturÄ™", "upload_form.undo": "UsuÅ„", "upload_form.video_description": "Opisz dla osób niesÅ‚yszÄ…cych, niedosÅ‚yszÄ…cych, niewidomych i niedowidzÄ…cych", "upload_modal.analyzing_picture": "Analizowanie obrazu…", "upload_modal.apply": "Zastosuj", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Wybierz obraz", "upload_modal.description_placeholder": "Pchnąć w tÄ™ łódź jeża lub oÅ›m skrzyÅ„ fig", - "upload_modal.detect_text": "Wykryj tekst ze obrazu", + "upload_modal.detect_text": "Wykryj tekst z obrazu", "upload_modal.edit_media": "Edytuj multimedia", "upload_modal.hint": "Kliknij lub przeciÄ…gnij kółko na podglÄ…dzie by wybrać centralny punkt, który zawsze bÄ™dzie na widoku na miniaturce.", + "upload_modal.preparing_ocr": "Przygotowywanie OCR…", "upload_modal.preview_label": "PodglÄ…d ({ratio})", "upload_progress.label": "WysyÅ‚anie…", "video.close": "Zamknij film", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index f494eaaa9c8d241a5377a3917393c4512b0f9f4d..65d5815edce2f193d659ce76605beaf8fa2b6e1f 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Encontre mais no perfil original", "account.cancel_follow_request": "Cancelar solicitação para seguir", "account.direct": "Enviar toot direto para @{name}", + "account.disable_notifications": "Parar de me notificar quando @{name} fizer publicações", "account.domain_blocked": "DomÃnio bloqueado", "account.edit_profile": "Editar perfil", + "account.enable_notifications": "Notificar-me quando @{name} fizer publicações", "account.endorse": "Destacar no perfil", "account.follow": "Seguir", "account.followers": "Seguidores", @@ -118,7 +120,7 @@ "confirmations.mute.explanation": "Isso ocultará toots deles e toots mencionando-os, mas ainda permitirá que eles vejam seus toots e te sigam.", "confirmations.mute.message": "Você tem certeza de que deseja silenciar {name}?", "confirmations.redraft.confirm": "Excluir e rascunhar", - "confirmations.redraft.message": "Tem certeza que quer excluir este status e re-rascunhá-lo? Favoritos e boots vão ser perdidos, e as respostas ao post original vão ficar órfãs.", + "confirmations.redraft.message": "Você tem certeza de que deseja apagar o toot e usá-lo como rascunho? Boosts e favoritos serão perdidos e as respostas ao toot original ficarão desconectadas.", "confirmations.reply.confirm": "Responder", "confirmations.reply.message": "Responder agora sobrescreverá o toot que você está compondo. Deseja continuar?", "confirmations.unfollow.confirm": "Deixar de seguir", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultados da pesquisa", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viagem & Lugares", + "empty_column.account_suspended": "Conta suspensa", "empty_column.account_timeline": "Nada aqui!", "empty_column.account_unavailable": "Perfil indisponÃvel", "empty_column.blocks": "Nada aqui.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Nada aqui. Interaja com outros usuários para começar a conversar.", "empty_column.public": "Não há nada aqui! Escreva algo publicamente, ou siga manualmente usuários de outros servidores para enchê-la", "error.unexpected_crash.explanation": "Devido a um bug em nosso código ou um problema de compatibilidade de navegador, esta página não pôde ser exibida corretamente.", + "error.unexpected_crash.explanation_addons": "Esta página não pôde ser exibida corretamente. Este erro provavelmente é causado por um complemento do navegador ou ferramentas de tradução automática.", "error.unexpected_crash.next_steps": "Tente atualizar a página. Se não resolver, você ainda pode conseguir usar o Mastodon por meio de um navegador ou app nativo diferente.", + "error.unexpected_crash.next_steps_addons": "Tente desabilitá-los e atualizar a página. Se isso não ajudar, você ainda poderá usar o Mastodon por meio de um navegador diferente ou de um aplicativo nativo.", "errors.unexpected_crash.copy_stacktrace": "Copiar stacktrace para área de transferência", "errors.unexpected_crash.report_issue": "Denunciar problema", "follow_request.authorize": "Aprovar", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "para desfocar de área de texto de composição/pesquisa", "keyboard_shortcuts.up": "para mover para cima na lista", "lightbox.close": "Fechar", + "lightbox.compress": "Compactar caixa de visualização de imagem", + "lightbox.expand": "Expandir caixa de visualização de imagem", "lightbox.next": "Próximo", "lightbox.previous": "Anterior", - "lightbox.view_context": "Ver contexto", "lists.account.add": "Adicionar à lista", "lists.account.remove": "Remover da lista", "lists.delete": "Excluir lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Renomear", "lists.new.create": "Criar lista", "lists.new.title_placeholder": "Nome da lista", + "lists.replies_policy.followed": "Qualquer usuário seguido", + "lists.replies_policy.list": "Membros da lista", + "lists.replies_policy.none": "Ninguém", + "lists.replies_policy.title": "Mostrar respostas para:", "lists.search": "Procurar entre as pessoas que você segue", "lists.subheading": "Suas listas", "load_pending": "{count, plural, one {# novo item} other {# novos items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Esconder mÃdia", "missing_indicator.label": "Não encontrado", "missing_indicator.sublabel": "Esse recurso não pôde ser encontrado", + "mute_modal.duration": "Duração", "mute_modal.hide_notifications": "Ocultar notificações deste usuário?", + "mute_modal.indefinite": "Indefinida", "navigation_bar.apps": "Aplicativos", "navigation_bar.blocks": "Usuários bloqueados", "navigation_bar.bookmarks": "Salvos", @@ -298,6 +310,7 @@ "notification.own_poll": "Sua enquete terminou", "notification.poll": "Uma enquete que você votou terminou", "notification.reblog": "{name} boostou seu status", + "notification.status": "{name} acabou de postar", "notifications.clear": "Limpar notificações", "notifications.clear_confirmation": "Você tem certeza de que deseja limpar todas as suas notificações?", "notifications.column_settings.alert": "Notificações no computador", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Mostrar nas colunas", "notifications.column_settings.sound": "Tocar som", + "notifications.column_settings.status": "Novos toots:", "notifications.filter.all": "Tudo", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguindo", "notifications.filter.mentions": "Menções", "notifications.filter.polls": "Resultados de enquete", + "notifications.filter.statuses": "Atualizações de pessoas que você segue", + "notifications.grant_permission": "Conceder permissão.", "notifications.group": "{count} notificações", + "notifications.mark_as_read": "Marcar todas as notificações como lidas", + "notifications.permission_denied": "Não é possÃvel habilitar as notificações da área de trabalho pois a permissão foi negada.", + "notifications.permission_denied_alert": "As notificações da área de trabalho não podem ser habilitdas pois a permissão do navegador foi negada antes", + "notifications.permission_required": "Notificações da área de trabalho não estão disponÃveis porque a permissão necessária não foi concedida.", + "notifications_permission_banner.enable": "Habilitar notificações da área de trabalho", + "notifications_permission_banner.how_to_control": "Para receber notificações quando o Mastodon não estiver aberto, habilite as notificações da área de trabalho. Você pode controlar precisamente quais tipos de interações geram notificações da área de trabalho através do botão {icon} acima uma vez habilitadas.", + "notifications_permission_banner.title": "Nunca perca nada", + "picture_in_picture.restore": "Colocar de volta", "poll.closed": "Fechou", "poll.refresh": "Atualizar", "poll.total_people": "{count, plural, one {# pessoa} other {# pessoas}}", @@ -392,7 +416,7 @@ "status.reblog_private": "Boostar para audiência original", "status.reblogged_by": "{name} boostou", "status.reblogs.empty": "Nada aqui. Quando alguém der boost, o autor aparecerá aqui.", - "status.redraft": "Excluir & re-rascunhar", + "status.redraft": "Excluir e rascunhar", "status.remove_bookmark": "Remover marcador", "status.reply": "Responder", "status.replyAll": "Responder a thread", @@ -425,27 +449,28 @@ "timeline_hint.resources.statuses": "Toots mais antigos", "trends.counter_by_accounts": "{count, plural, one {{counter} pessoa} other {{counter} pessoas}} falando", "trends.trending_now": "Em alta no momento", - "ui.beforeunload": "Seu rascunho vai ser perdido se você sair do Mastodon.", + "ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.", "units.short.billion": "{count} bi", "units.short.million": "{count} mi", "units.short.thousand": "{count} mil", "upload_area.title": "Arraste & solte para fazer upload", - "upload_button.label": "Adicionar mÃdia ({formats})", + "upload_button.label": "Adicionar mÃdia", "upload_error.limit": "Limite de upload de arquivos excedido.", "upload_error.poll": "Não é possÃvel fazer upload de arquivos com enquetes.", "upload_form.audio_description": "Descrever para pessoas com deficiência auditiva", "upload_form.description": "Descreva para deficientes visuais", "upload_form.edit": "Editar", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Alterar miniatura", "upload_form.undo": "Excluir", "upload_form.video_description": "Descreva para pessoas com deficiência auditiva ou visual", "upload_modal.analyzing_picture": "Analisando imagem…", "upload_modal.apply": "Aplicar", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Escolher imagem", "upload_modal.description_placeholder": "Um pequeno jabuti xereta viu dez cegonhas felizes", "upload_modal.detect_text": "Detectar texto da imagem", "upload_modal.edit_media": "Editar mÃdia", "upload_modal.hint": "Clique ou arraste o cÃrculo na prévia para escolher o ponto focal que vai estar sempre visÃvel em todas as thumbnails.", + "upload_modal.preparing_ocr": "Preparando OCR…", "upload_modal.preview_label": "Prévia ({ratio})", "upload_progress.label": "Fazendo upload...", "video.close": "Fechar vÃdeo", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 49fb95885b319bd643a12c5aee2bdf17c01ea49f..dd3b4eba21252e51b24959f9164e6ef7b867ffdf 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -1,36 +1,38 @@ { - "account.account_note_header": "A sua nota para @{name}", + "account.account_note_header": "A tua nota para @{name}", "account.add_or_remove_from_list": "Adicionar ou remover das listas", - "account.badges.bot": "Robô", + "account.badges.bot": "Bot", "account.badges.group": "Grupo", "account.block": "Bloquear @{name}", "account.block_domain": "Esconder tudo do domÃnio {domain}", - "account.blocked": "Bloqueado", - "account.browse_more_on_origin_server": "Encontre mais no perfil original", - "account.cancel_follow_request": "Cancelar pedido de seguidor", - "account.direct": "Mensagem directa @{name}", - "account.domain_blocked": "DomÃnio escondido", + "account.blocked": "Bloqueado(a)", + "account.browse_more_on_origin_server": "Encontrar mais no perfil original", + "account.cancel_follow_request": "Cancelar pedido para seguir", + "account.direct": "Enviar mensagem directa para @{name}", + "account.disable_notifications": "Parar de me notificar das publicações de @{name}", + "account.domain_blocked": "DomÃnio bloqueado", "account.edit_profile": "Editar perfil", - "account.endorse": "Atributo no perfil", + "account.enable_notifications": "Notificar-me das publicações de @{name}", + "account.endorse": "Destacar no perfil", "account.follow": "Seguir", "account.followers": "Seguidores", "account.followers.empty": "Ainda ninguém segue este utilizador.", "account.followers_counter": "{count, plural, one {{counter} Seguidor} other {{counter} Seguidores}}", "account.following_counter": "{count, plural, other {A seguir {counter}}}", - "account.follows.empty": "Este utilizador ainda não segue alguém.", + "account.follows.empty": "Este utilizador ainda não segue ninguém.", "account.follows_you": "Segue-te", "account.hide_reblogs": "Esconder partilhas de @{name}", "account.last_status": "Última atividade", "account.link_verified_on": "A posse deste link foi verificada em {date}", "account.locked_info": "O estatuto de privacidade desta conta é fechado. O dono revê manualmente quem a pode seguir.", - "account.media": "Media", + "account.media": "Média", "account.mention": "Mencionar @{name}", "account.moved_to": "{name} mudou a sua conta para:", "account.mute": "Silenciar @{name}", "account.mute_notifications": "Silenciar notificações de @{name}", "account.muted": "Silenciada", "account.never_active": "Nunca", - "account.posts": "Publicações", + "account.posts": "Toots", "account.posts_with_replies": "Publicações e respostas", "account.report": "Denunciar @{name}", "account.requested": "A aguardar aprovação. Clique para cancelar o pedido de seguidor", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Resultados da pesquisa", "emoji_button.symbols": "SÃmbolos", "emoji_button.travel": "Viagens & Lugares", + "empty_column.account_suspended": "Conta suspensa", "empty_column.account_timeline": "Sem toots por aqui!", "empty_column.account_unavailable": "Perfil indisponÃvel", "empty_column.blocks": "Ainda não bloqueaste qualquer utilizador.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.", "empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para veres aqui os conteúdos públicos", "error.unexpected_crash.explanation": "Devido a um erro no nosso código ou a uma compatilidade com o seu navegador, esta página não pôde ser apresentada correctamente.", + "error.unexpected_crash.explanation_addons": "Esta página não pôde ser exibida corretamente. Este erro provavelmente é causado por um complemento do navegador ou ferramentas de tradução automática.", "error.unexpected_crash.next_steps": "Tente atualizar a página. Se isso não ajudar, pode usar o Mastodon através de um navegador diferente ou uma aplicação nativa.", + "error.unexpected_crash.next_steps_addons": "Tente desabilitá-los e atualizar a página. Se isso não ajudar, você ainda poderá usar o Mastodon por meio de um navegador diferente ou de um aplicativo nativo.", "errors.unexpected_crash.copy_stacktrace": "Copiar a stacktrace para o clipboard", "errors.unexpected_crash.report_issue": "Reportar problema", "follow_request.authorize": "Autorizar", @@ -202,9 +207,9 @@ "introduction.federation.federated.headline": "Federada", "introduction.federation.federated.text": "Publicações públicas de outras instâncias do fediverso aparecerão na cronologia federada.", "introduction.federation.home.headline": "InÃcio", - "introduction.federation.home.text": "As publicações das pessoas que você segue aparecerão na sua coluna de inÃcio. Você pode seguir qualquer pessoa em qualquer instância!", + "introduction.federation.home.text": "As publicações das pessoas que segues aparecerão na tua coluna de inÃcio. Podes seguir qualquer pessoa em qualquer instância!", "introduction.federation.local.headline": "Local", - "introduction.federation.local.text": "Publicações públicas de pessoas na mesma instância que você aparecerão na coluna local.", + "introduction.federation.local.text": "Publicações públicas de pessoas na mesma instância que tu aparecerão na coluna local.", "introduction.interactions.action": "Terminar o tutorial!", "introduction.interactions.favourite.headline": "Favorito", "introduction.interactions.favourite.text": "Podes guardar um toot para depois e deixar o autor saber que gostaste dele, marcando-o como favorito.", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "para remover o foco da área de texto/pesquisa", "keyboard_shortcuts.up": "para mover para cima na lista", "lightbox.close": "Fechar", + "lightbox.compress": "Compactar caixa de visualização de imagem", + "lightbox.expand": "Expandir caixa de visualização de imagem", "lightbox.next": "Próximo", "lightbox.previous": "Anterior", - "lightbox.view_context": "Ver contexto", "lists.account.add": "Adicionar à lista", "lists.account.remove": "Remover da lista", "lists.delete": "Remover lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Mudar o tÃtulo", "lists.new.create": "Adicionar lista", "lists.new.title_placeholder": "TÃtulo da nova lista", + "lists.replies_policy.followed": "Qualquer utilizador seguido", + "lists.replies_policy.list": "Membros da lista", + "lists.replies_policy.none": "Ninguém", + "lists.replies_policy.title": "Mostrar respostas para:", "lists.search": "Pesquisa entre as pessoas que segues", "lists.subheading": "As tuas listas", "load_pending": "{count, plural, one {# novo item} other {# novos itens}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Alternar visibilidade", "missing_indicator.label": "Não encontrado", "missing_indicator.sublabel": "Este recurso não foi encontrado", + "mute_modal.duration": "Duração", "mute_modal.hide_notifications": "Esconder notificações deste utilizador?", + "mute_modal.indefinite": "Indefinidamente", "navigation_bar.apps": "Aplicações móveis", "navigation_bar.blocks": "Utilizadores bloqueados", "navigation_bar.bookmarks": "Itens salvos", @@ -298,9 +310,10 @@ "notification.own_poll": "A sua votação terminou", "notification.poll": "Uma votação em que participaste chegou ao fim", "notification.reblog": "{name} partilhou a tua publicação", + "notification.status": "{name} acabou de publicar", "notifications.clear": "Limpar notificações", "notifications.clear_confirmation": "Queres mesmo limpar todas as notificações?", - "notifications.column_settings.alert": "Notificações no computador", + "notifications.column_settings.alert": "Notificações no ambiente de trabalho", "notifications.column_settings.favourite": "Favoritos:", "notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorias", "notifications.column_settings.filter_bar.category": "Barra de filtros rápidos", @@ -313,19 +326,30 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Mostrar na coluna", "notifications.column_settings.sound": "Reproduzir som", + "notifications.column_settings.status": "Novos toots:", "notifications.filter.all": "Todas", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favoritos", "notifications.filter.follows": "Seguidores", "notifications.filter.mentions": "Menções", "notifications.filter.polls": "Votações", + "notifications.filter.statuses": "Atualizações de pessoas que você segue", + "notifications.grant_permission": "Conceder permissões.", "notifications.group": "{count} notificações", + "notifications.mark_as_read": "Marcar todas as notificações como lidas", + "notifications.permission_denied": "Notificações no ambiente de trabalho não estão disponÃveis porque a permissão, solicitada pelo navegador, foi recusada anteriormente", + "notifications.permission_denied_alert": "Notificações no ambinente de trabalho não podem ser ativadas, pois a permissão do navegador foi recusada anteriormente", + "notifications.permission_required": "Notificações no ambiente de trabalho não estão disponÃveis porque a permissão necessária não foi concedida.", + "notifications_permission_banner.enable": "Ativar notificações no ambiente de trabalho", + "notifications_permission_banner.how_to_control": "Para receber notificações quando o Mastodon não estiver aberto, ative as notificações no ambiente de trabalho. Depois da sua ativação, pode controlar precisamente quais tipos de interações geram notificações, através do botão {icon} acima.", + "notifications_permission_banner.title": "Nunca perca nada", + "picture_in_picture.restore": "Colocá-lo de volta", "poll.closed": "Fechado", "poll.refresh": "Recarregar", "poll.total_people": "{count, plural, one {# pessoa} other {# pessoas}}", "poll.total_votes": "{contar, plural, um {# vote} outro {# votes}}", "poll.vote": "Votar", - "poll.voted": "Você votou nesta resposta", + "poll.voted": "Votaste nesta resposta", "poll_button.add_poll": "Adicionar votação", "poll_button.remove_poll": "Remover votação", "privacy.change": "Ajustar a privacidade da publicação", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}m", "upload_area.title": "Arraste e solte para enviar", - "upload_button.label": "Adicionar media ({formats})", + "upload_button.label": "Adicionar media", "upload_error.limit": "Limite máximo do ficheiro a carregar excedido.", "upload_error.poll": "Carregamento de ficheiros não é permitido em votações.", "upload_form.audio_description": "Descreva para pessoas com diminuição da acuidade auditiva", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detectar texto na imagem", "upload_modal.edit_media": "Editar media", "upload_modal.hint": "Clique ou arraste o cÃrculo na pré-visualização para escolher o ponto focal que será sempre visÃvel em todas as miniaturas.", + "upload_modal.preparing_ocr": "A preparar OCR…", "upload_modal.preview_label": "Pré-visualizar ({ratio})", "upload_progress.label": "A enviar...", "video.close": "Fechar vÃdeo", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 544d6810215dd9cb1f469aae537d0bb15a620c14..a80bfa82251431df6f200bfbc5617621cc9b2b8c 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Caută mai multe în profilul original", "account.cancel_follow_request": "AnulaÈ›i cererea de urmărire", "account.direct": "Mesaj direct @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domeniu blocat", "account.edit_profile": "EditaÈ›i profilul", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "PromovaÈ›i pe profil", "account.follow": "UrmăreÈ™te", "account.followers": "Urmăritori", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Rezultatele căutării", "emoji_button.symbols": "Simboluri", "emoji_button.travel": "Călătorii È™i Locuri", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Nicio postare aici!", "empty_column.account_unavailable": "Profil indisponibil", "empty_column.blocks": "Nu ai blocat nici un utilizator încă.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Nu ai nici o notificare încă. InteracÈ›ionează cu alÈ›ii pentru a începe o conversaÈ›ie.", "empty_column.public": "Nu este nimic aici! Scrie ceva public, sau urmăreÈ™te alÈ›i utilizatori din alte instanÈ›e pentru a porni fluxul", "error.unexpected_crash.explanation": "Din cauza unei erori în codul nostru sau a unei probleme de compatibilitate cu navigatorul, această pagină nu a putut fi afiÈ™ată corect.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "ÃŽncercaÈ›i să reîmprospătaÈ›i pagina. Dacă acest lucru nu ajută, este posibil să mai puteÈ›i folosi site-ul printr-un navigator diferit sau o aplicaÈ›ie nativă.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "CopiaÈ›i stiva în clipboard", "errors.unexpected_crash.report_issue": "RaportaÈ›i o problemă", "follow_request.authorize": "Autorizează", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "să dezactiveze zona de compunere/căutare", "keyboard_shortcuts.up": "să mute mai sus în listă", "lightbox.close": "ÃŽnchide", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Următorul", "lightbox.previous": "Precedentul", - "lightbox.view_context": "VizualizaÈ›i contextul", "lists.account.add": "Adaugă în listă", "lists.account.remove": "Elimină din listă", "lists.delete": "Șterge lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Schimbă titlul", "lists.new.create": "Adaugă listă", "lists.new.title_placeholder": "Titlu pentru noua listă", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Caută printre persoanele pe care le urmăreÈ™ti", "lists.subheading": "Listele tale", "load_pending": "{count, plural, one {# element nou} other {# elemente noi}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Ascunde media", "missing_indicator.label": "Nu a fost găsit", "missing_indicator.sublabel": "Această resursă nu a putut fi găsită", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Ascunzi notificările de la acest utilizator?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "AplicaÈ›ii mobile", "navigation_bar.blocks": "Utilizatori blocaÈ›i", "navigation_bar.bookmarks": "Marcaje", @@ -298,6 +310,7 @@ "notification.own_poll": "Sondajul tău s-a sfârÈ™it", "notification.poll": "Un sondaj la care ai votat s-a sfârÈ™it", "notification.reblog": "{name} a impulsionat postarea ta", + "notification.status": "{name} just posted", "notifications.clear": "Șterge notificările", "notifications.clear_confirmation": "EÈ™ti sigur că vrei să È™tergi permanent toate notificările?", "notifications.column_settings.alert": "Notificări pe desktop", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Impulsuri:", "notifications.column_settings.show": "Arată în coloană", "notifications.column_settings.sound": "Redă sunet", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Toate", "notifications.filter.boosts": "Impulsuri", "notifications.filter.favourites": "Favorite", "notifications.filter.follows": "UrmăreÈ™te", "notifications.filter.mentions": "MenÈ›ionări", "notifications.filter.polls": "Rezultate sondaj", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notificări", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "ÃŽnchis", "poll.refresh": "Reîmprospătează", "poll.total_people": "{count, plural, one {# persoană} other {# persoane}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detectare text din imagine", "upload_modal.edit_media": "EditaÈ›i media", "upload_modal.hint": "FaceÅ£i clic sau trageÅ£i cercul pe previzualizare pentru a alege punctul focal care va fi întotdeauna vizualizat pe toate miniaturile.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Previzualizare ({ratio})", "upload_progress.label": "Se ÃŽncarcă...", "video.close": "ÃŽnchide video", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 38d7145250d4b4757a4405b09d537d57be96d21e..2853b3302d56667b3af4dd0c35eec70f91c70c35 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "ПоÑмотреть их можно в оригинальном профиле", "account.cancel_follow_request": "Отменить запроÑ", "account.direct": "ÐапиÑать @{name}", + "account.disable_notifications": "Отключить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ @{name}", "account.domain_blocked": "Домен Ñкрыт", "account.edit_profile": "Изменить профиль", + "account.enable_notifications": "Включить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ @{name}", "account.endorse": "Рекомендовать в профиле", "account.follow": "ПодпиÑатьÑÑ", "account.followers": "ПодпиÑаны", @@ -96,7 +98,7 @@ "compose_form.poll.switch_to_single": "Переключить в режим выбора одного ответа", "compose_form.publish": "ЗапоÑтить", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Отметить медиафайл как деликатный", + "compose_form.sensitive.hide": "{count, plural, one {Отметить медифайл как деликатный} other {Отметить медифайлы как деликатные}}", "compose_form.sensitive.marked": "Медиафайл отмечен как деликатный", "compose_form.sensitive.unmarked": "Медиафайл не отмечен как деликатный", "compose_form.spoiler.marked": "ТекÑÑ‚ Ñкрыт за предупреждением", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Результаты поиÑка", "emoji_button.symbols": "Символы", "emoji_button.travel": "ПутешеÑÑ‚Ð²Ð¸Ñ Ð¸ меÑта", + "empty_column.account_suspended": "Ð£Ñ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ заблокирована", "empty_column.account_timeline": "ЗдеÑÑŒ нет поÑтов!", "empty_column.account_unavailable": "Профиль недоÑтупен", "empty_column.blocks": "Ð’Ñ‹ ещё никого не заблокировали.", @@ -166,7 +169,9 @@ "empty_column.notifications": "У Ð²Ð°Ñ Ð¿Ð¾ÐºÐ° нет уведомлений. ВзаимодейÑтвуйте Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸, чтобы завеÑти разговор.", "empty_column.public": "ЗдеÑÑŒ ничего нет! Опубликуйте что-нибудь или подпишитеÑÑŒ на пользователей Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… узлов, чтобы заполнить ленту", "error.unexpected_crash.explanation": "Из-за неÑовмеÑтимого браузера или ошибки в нашем коде, Ñта Ñтраница не может быть корректно отображена.", + "error.unexpected_crash.explanation_addons": "Ðта Ñтраница не может быть корректно отображена. Скорее вÑего, Ñта ошибка вызвана раÑширением браузера или инÑтрументом автоматичеÑкого перевода.", "error.unexpected_crash.next_steps": "Попробуйте обновить Ñтраницу. ЕÑли проблема не иÑчезает, иÑпользуйте Mastodon из-под другого браузера или приложениÑ.", + "error.unexpected_crash.next_steps_addons": "Попробуйте их отключить и перезагрузить Ñтраницу. ЕÑли Ñто не поможет, вы по-прежнему Ñможете войти в Mastodon через другой браузер или приложение.", "errors.unexpected_crash.copy_stacktrace": "Скопировать диагноÑтичеÑкую информацию", "errors.unexpected_crash.report_issue": "Сообщить о проблеме", "follow_request.authorize": "Ðвторизовать", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "убрать Ñ„Ð¾ÐºÑƒÑ Ñ Ð¿Ð¾Ð»Ñ Ð²Ð²Ð¾Ð´Ð°/поиÑка", "keyboard_shortcuts.up": "вверх по ÑпиÑку", "lightbox.close": "Закрыть", + "lightbox.compress": "Сжать окно проÑмотра изображений", + "lightbox.expand": "Развернуть окно проÑмотра изображений", "lightbox.next": "Далее", "lightbox.previous": "Ðазад", - "lightbox.view_context": "КонтекÑÑ‚", "lists.account.add": "Добавить в ÑпиÑок", "lists.account.remove": "Убрать из ÑпиÑка", "lists.delete": "Удалить ÑпиÑок", @@ -260,6 +266,10 @@ "lists.edit.submit": "Изменить название", "lists.new.create": "Создать ÑпиÑок", "lists.new.title_placeholder": "Ðазвание Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÑпиÑка", + "lists.replies_policy.followed": "Любой подпиÑанный пользователь", + "lists.replies_policy.list": "Пользователи в ÑпиÑке", + "lists.replies_policy.none": "Ðикого", + "lists.replies_policy.title": "Показать ответы только:", "lists.search": "ИÑкать Ñреди подпиÑок", "lists.subheading": "Ваши ÑпиÑки", "load_pending": "{count, plural, one {# новый Ñлемент} few {# новых Ñлемента} other {# новых Ñлементов}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Показать/Ñкрыть", "missing_indicator.label": "Ðе найдено", "missing_indicator.sublabel": "Запрашиваемый реÑÑƒÑ€Ñ Ð½Ðµ найден", + "mute_modal.duration": "ПродолжительноÑть", "mute_modal.hide_notifications": "Скрыть ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ Ñтого пользователÑ?", + "mute_modal.indefinite": "Ðе определена", "navigation_bar.apps": "Мобильные приложениÑ", "navigation_bar.blocks": "СпиÑок блокировки", "navigation_bar.bookmarks": "Закладки", @@ -298,6 +310,7 @@ "notification.own_poll": "Ваш Ð¾Ð¿Ñ€Ð¾Ñ Ð·Ð°ÐºÐ¾Ð½Ñ‡Ð¸Ð»ÑÑ", "notification.poll": "ОпроÑ, в котором вы принÑли учаÑтие, завершилÑÑ", "notification.reblog": "{name} продвинул(а) ваш поÑÑ‚", + "notification.status": "{name} только что запоÑтил", "notifications.clear": "ОчиÑтить уведомлениÑ", "notifications.clear_confirmation": "Ð’Ñ‹ уверены, что хотите очиÑтить вÑе уведомлениÑ?", "notifications.column_settings.alert": "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð² фоне", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Ваш поÑÑ‚ продвинули:", "notifications.column_settings.show": "Отображать в ÑпиÑке", "notifications.column_settings.sound": "Проигрывать звук", + "notifications.column_settings.status": "Ðовые поÑты:", "notifications.filter.all": "Ð’Ñе", "notifications.filter.boosts": "ПродвижениÑ", "notifications.filter.favourites": "Отметки «избранного»", "notifications.filter.follows": "ПодпиÑки", "notifications.filter.mentions": "УпоминаниÑ", "notifications.filter.polls": "Результаты опроÑов", + "notifications.filter.statuses": "ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ людей, на которых вы подпиÑаны", + "notifications.grant_permission": "Дать разрешение.", "notifications.group": "{count} уведомл.", + "notifications.mark_as_read": "Отмечать вÑе ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ‹Ð¼Ð¸", + "notifications.permission_denied": "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð½Ð° рабочем Ñтоле недоÑтупны из-за ранее отклонённого запроÑа разрешений браузера", + "notifications.permission_denied_alert": "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð½Ð° рабочем Ñтоле не могут быть включены, так как раньше было отказано в разрешении браузера", + "notifications.permission_required": "ДеÑктоп нотификации недоÑтупны, потому что требуемое разрешение не было предоÑтавлено.", + "notifications_permission_banner.enable": "Включить ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð½Ð° рабочем Ñтоле", + "notifications_permission_banner.how_to_control": "Чтобы получать уведомлениÑ, когда МаÑтодон не открыт, включите ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‡ÐµÐ³Ð¾ Ñтола. Ð’Ñ‹ можете точно управлÑть, какие типы взаимодейÑÑ‚Ð²Ð¸Ñ Ð³ÐµÐ½ÐµÑ€Ð¸Ñ€ÑƒÑŽÑ‚ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‡ÐµÐ³Ð¾ Ñтола Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ кнопки {icon} выше, когда они включены.", + "notifications_permission_banner.title": "Ðичего не пропуÑтите", + "picture_in_picture.restore": "Вернуть обратно", "poll.closed": "Завершён", "poll.refresh": "Обновить", "poll.total_people": "{count, plural, one {# человек} few {# человека} many {# человек} other {# человек}}", @@ -423,7 +447,7 @@ "timeline_hint.resources.followers": "подпиÑчиков", "timeline_hint.resources.follows": "подпиÑки", "timeline_hint.resources.statuses": "прошлые поÑты", - "trends.counter_by_accounts": "{count, plural, one {{counter} человек} many {{counter} человек} other {{counter} человека}}", + "trends.counter_by_accounts": "{count, plural, one {{counter} человек обÑуждает} few {{counter} человека обÑуждает} many {{counter} человек обÑуждают} other {{counter} обÑуждают}} ", "trends.trending_now": "Самое актуальное", "ui.beforeunload": "Ваш черновик будет утерÑн, еÑли вы покинете Mastodon.", "units.short.billion": "{count} млрд", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Ðайти текÑÑ‚ на картинке", "upload_modal.edit_media": "Изменить файл", "upload_modal.hint": "Ðажмите и перетащите круг в предпроÑмотре в точку фокуÑа, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð²Ñегда будет видна на ÑÑкизах.", + "upload_modal.preparing_ocr": "Подготовка раÑпознованиÑ…", "upload_modal.preview_label": "ПредпроÑмотр ({ratio})", "upload_progress.label": "Загрузка...", "video.close": "Закрыть видео", diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json new file mode 100644 index 0000000000000000000000000000000000000000..4656aa275675d55176212462724774abea006c90 --- /dev/null +++ b/app/javascript/mastodon/locales/sa.json @@ -0,0 +1,486 @@ +{ + "account.account_note_header": "टीका", + "account.add_or_remove_from_list": "यà¥à¤œà¥à¤¯à¤¤à¤¾à¤‚ / नशà¥à¤¯à¤¤à¤¾à¤‚ सूचà¥à¤¯à¤¾à¤ƒ", + "account.badges.bot": "यनà¥à¤¤à¥à¤°à¤®à¥", + "account.badges.group": "समूहः", + "account.block": "अवरà¥à¤§à¥à¤¯à¤¤à¤¾à¤®à¥ @{name}", + "account.block_domain": "अवरà¥à¤§à¥à¤¯à¤¤à¤¾à¤‚ पà¥à¤°à¤¦à¥‡à¤¶à¤ƒ {domain}", + "account.blocked": "अवरà¥à¤¦à¥à¤§à¤®à¥", + "account.browse_more_on_origin_server": "अधिकं मूलवà¥à¤¯à¤•à¥à¤¤à¤¿à¤—तविवरणे दृशà¥à¤¯à¤¤à¤¾à¤®à¥", + "account.cancel_follow_request": "अनà¥à¤¸à¤°à¤£à¤¾à¤¨à¥à¤°à¥‹à¤§à¥‹ नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "account.direct": "पà¥à¤°à¤¤à¥à¤¯à¤•à¥à¤·à¤¸à¤¨à¥à¤¦à¥‡à¤¶à¤ƒ @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", + "account.domain_blocked": "पà¥à¤°à¤¦à¥‡à¤¶à¥‹ निषिदà¥à¤§à¤ƒ", + "account.edit_profile": "समà¥à¤ªà¤¾à¤¦à¥à¤¯à¤¤à¤¾à¤®à¥", + "account.enable_notifications": "Notify me when @{name} posts", + "account.endorse": "वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—तविवरणे वैशिषà¥à¤Ÿà¥à¤¯à¤®à¥", + "account.follow": "अनà¥à¤¸à¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "account.followers": "अनà¥à¤¸à¤°à¥à¤¤à¤¾à¤°à¤ƒ", + "account.followers.empty": "नाऽनà¥à¤¸à¤°à¥à¤¤à¤¾à¤°à¥‹ वरà¥à¤¤à¤¨à¥à¤¤à¥‡", + "account.followers_counter": "{count, plural, one {{counter} अनà¥à¤¸à¤°à¥à¤¤à¤¾} two {{counter} अनà¥à¤¸à¤°à¥à¤¤à¤¾à¤°à¥Œ} other {{counter} अनà¥à¤¸à¤°à¥à¤¤à¤¾à¤°à¤ƒ}}", + "account.following_counter": "{count, plural, one {{counter} अनà¥à¤¸à¥ƒà¤¤à¤ƒ} two {{counter} अनà¥à¤¸à¥ƒà¤¤à¥Œ} other {{counter} अनà¥à¤¸à¥ƒà¤¤à¤¾à¤ƒ}}", + "account.follows.empty": "न कोऽपà¥à¤¯à¤¨à¥à¤¸à¥ƒà¤¤à¥‹ वरà¥à¤¤à¤¤à¥‡", + "account.follows_you": "तà¥à¤µà¤¾à¤®à¤¨à¥à¤¸à¤°à¤¤à¤¿", + "account.hide_reblogs": "@{name} मितà¥à¤°à¤¸à¥à¤¯ पà¥à¤°à¤•ाशनानि छिदà¥à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "account.last_status": "गतसकà¥à¤°à¤¿à¤¯à¤¤à¤¾", + "account.link_verified_on": "अनà¥à¤¤à¤°à¥à¤œà¤¾à¤²à¤¸à¥à¤¥à¤¾à¤¨à¤¸à¥à¤¯à¤¾à¤¸à¥à¤¯ सà¥à¤µà¤¾à¤®à¤¿à¤¤à¥à¤µà¤‚ परीकà¥à¤·à¤¿à¤¤à¤®à¤¾à¤¸à¥€à¤¤à¥ {date} दिने", + "account.locked_info": "à¤à¤¤à¤¸à¥à¤¯à¤¾ लेखायाः गà¥à¤¹à¥à¤¯à¤¤à¤¾ \"निषिदà¥à¤§\"इति वरà¥à¤¤à¤¤à¥‡ । सà¥à¤µà¤¾à¤®à¥€ सà¥à¤µà¤¯à¤žà¥à¤šà¤¿à¤¨à¥‹à¤¤à¤¿ कोऽनà¥à¤¸à¤°à¥à¤¤à¤¾ à¤à¤µà¤¿à¤¤à¥à¤®à¤°à¥à¤¹à¤¤à¥€à¤¤à¤¿ ।", + "account.media": "सामगà¥à¤°à¥€", + "account.mention": "उलà¥à¤²à¤¿à¤–à¥à¤¯à¤¤à¤¾à¤®à¥ @{name}", + "account.moved_to": "{name} अतà¥à¤° पà¥à¤°à¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤à¤®à¥:", + "account.mute": "निःशबà¥à¤¦à¤®à¥ @{name}", + "account.mute_notifications": "@{name} सूचनाः निषà¥à¤•à¥à¤°à¤¿à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "account.muted": "निःशबà¥à¤¦à¤®à¥", + "account.never_active": "नैव कदापि", + "account.posts": "दौतà¥à¤¯à¤¾à¤¨à¤¿", + "account.posts_with_replies": "दौतà¥à¤¯à¤¾à¤¨à¤¿ पà¥à¤°à¤¤à¥à¤¯à¥à¤¤à¥à¤¤à¤°à¤¾à¤£à¤¿ च", + "account.report": "आविदà¥à¤¯à¤¤à¤¾à¤®à¥ @{name}", + "account.requested": "सà¥à¤µà¥€à¤•ृतिः पà¥à¤°à¤¤à¥€à¤•à¥à¤·à¥à¤¯à¤¤à¥‡ । नशà¥à¤¯à¤¤à¤¾à¤®à¤¿à¤¤à¥à¤¯à¤¸à¥à¤®à¤¿à¤¨à¥à¤¨à¥à¤¦à¥à¤¯à¤¤à¤¾à¤‚ निराकरà¥à¤¤à¥à¤®à¥ ।", + "account.share": "@{name} मितà¥à¤°à¤¸à¥à¤¯ विवरणं विà¤à¤¾à¤œà¥à¤¯à¤¤à¤¾à¤®à¥", + "account.show_reblogs": "@{name} मितà¥à¤°à¤¸à¥à¤¯ पà¥à¤°à¤•ाशनानि दृशà¥à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "account.statuses_counter": "{count, plural, one {{counter} दौतà¥à¤¯à¤®à¥} two {{counter} दौतà¥à¤¯à¥‡} other {{counter} दौतà¥à¤¯à¤¾à¤¨à¤¿}}", + "account.unblock": "निषेधता नशà¥à¤¯à¤¤à¤¾à¤®à¥ @{name}", + "account.unblock_domain": "पà¥à¤°à¤¦à¥‡à¤¶à¤¨à¤¿à¤·à¥‡à¤§à¤¤à¤¾ नशà¥à¤¯à¤¤à¤¾à¤®à¥ {domain}", + "account.unendorse": "वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—तविवरणे मा पà¥à¤°à¤•ाशà¥à¤¯à¤¤à¤¾à¤®à¥", + "account.unfollow": "नशà¥à¤¯à¤¤à¤¾à¤®à¤¨à¥à¤¸à¤°à¤£à¤®à¥", + "account.unmute": "सशबà¥à¤¦à¤®à¥ @{name}", + "account.unmute_notifications": "@{name} सूचनाः सकà¥à¤°à¤¿à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "account_note.placeholder": "टीकायोजनारà¥à¤¥à¤‚ नà¥à¤¦à¥à¤¯à¤¤à¤¾à¤®à¥", + "alert.rate_limited.message": "{retry_time, time, medium}. समयातॠपशà¥à¤šà¤¾à¤¤à¥ पà¥à¤°à¤¯à¤¤à¤¤à¤¾à¤®à¥", + "alert.rate_limited.title": "सीमितगतिः", + "alert.unexpected.message": "अनपेकà¥à¤·à¤¿à¤¤à¤¦à¥‹à¤·à¥‹ जातः ।", + "alert.unexpected.title": "अरे !", + "announcement.announcement": "उदà¥à¤˜à¥‹à¤·à¤£à¤¾", + "autosuggest_hashtag.per_week": "{count} पà¥à¤°à¤¤à¤¿à¤¸à¤ªà¥à¤¤à¤¾à¤¹à¥‡", + "boost_modal.combo": "{combo} अतà¥à¤° सà¥à¤ªà¥à¤°à¤·à¥à¤Ÿà¥à¤‚ शकà¥à¤¯à¤¤à¥‡, तà¥à¤¯à¤•à¥à¤¤à¥à¤®à¥‡à¤¤à¤®à¤¨à¥à¤¯à¤¸à¥à¤®à¤¿à¤¨à¥ समये", + "bundle_column_error.body": "विषयसà¥à¤¯à¤¾à¤½à¤½à¤°à¥‹à¤ªà¤£à¥‡ कशà¥à¤šà¤¿à¤¦à¥à¤¦à¥‹à¤·à¥‹ जातः", + "bundle_column_error.retry": "पà¥à¤¨à¤ƒ यततामà¥", + "bundle_column_error.title": "जाले दोषः", + "bundle_modal_error.close": "पिधीयतामà¥", + "bundle_modal_error.message": "आरोपणे कशà¥à¤šà¤¨ दोषो जातः", + "bundle_modal_error.retry": "पà¥à¤¨à¤ƒ यततामà¥", + "column.blocks": "निषिदà¥à¤§à¤à¥‹à¤•à¥à¤¤à¤¾à¤°à¤ƒ", + "column.bookmarks": "पà¥à¤Ÿà¤šà¤¿à¤¹à¥à¤¨à¤¾à¤¨à¤¿", + "column.community": "सà¥à¤¥à¤¾à¤¨à¥€à¤¯à¤¸à¤®à¤¯à¤¤à¤¾à¤²à¤¿à¤•ा", + "column.direct": "पà¥à¤°à¤¤à¥à¤¯à¤•à¥à¤·à¤¸à¤¨à¥à¤¦à¥‡à¤¶à¤¾à¤ƒ", + "column.directory": "वà¥à¤¯à¤•à¥à¤¤à¤¿à¤¤à¥à¤µà¤¾à¤¨à¤¿ दृशà¥à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "column.domain_blocks": "निषिदà¥à¤§à¤ªà¥à¤°à¤¦à¥‡à¤¶à¤¾à¤ƒ", + "column.favourites": "पà¥à¤°à¤¿à¤¯à¤¾à¤ƒ", + "column.follow_requests": "अनà¥à¤¸à¤°à¤£à¤¾à¤¨à¥à¤°à¥‹à¤§à¤¾à¤ƒ", + "column.home": "गृहमà¥", + "column.lists": "सूचयः", + "column.mutes": "निःशबà¥à¤¦à¤¾à¤ƒ à¤à¥‹à¤•à¥à¤¤à¤¾à¤°à¤ƒ", + "column.notifications": "सूचनाः", + "column.pins": "कीलितदौतà¥à¤¯à¤¾à¤¨à¤¿", + "column.public": "सङà¥à¤˜à¥€à¤¯à¤¸à¤®à¤¯à¤¤à¤¾à¤²à¤¿à¤•ा", + "column_back_button.label": "पूरà¥à¤µà¤®à¥", + "column_header.hide_settings": "विनà¥à¤¯à¤¾à¤¸à¤¾à¤ƒ छादà¥à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "column_header.moveLeft_settings": "सà¥à¤¤à¤®à¥à¤à¥‹ वामी कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "column_header.moveRight_settings": "सà¥à¤¤à¤®à¥à¤à¥‹ दकà¥à¤·à¤¿à¤£à¥€ कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "column_header.pin": "कीलयतà¥", + "column_header.show_settings": "विनà¥à¤¯à¤¾à¤¸à¤¾à¤ƒ दृशà¥à¤¯à¤¨à¥à¤¤à¤¾à¤®à¥", + "column_header.unpin": "कीलनं नाशय", + "column_subheading.settings": "विनà¥à¤¯à¤¾à¤¸à¤¾à¤ƒ", + "community.column_settings.local_only": "केवलं सà¥à¤¥à¤¾à¤¨à¥€à¤¯à¤®à¥", + "community.column_settings.media_only": "सामगà¥à¤°à¥€ केवलमà¥", + "community.column_settings.remote_only": "दरà¥à¤—मः केवलमà¥", + "compose_form.direct_message_warning": "दौतà¥à¤¯à¤®à¥‡à¤¤à¤¤à¥à¤•ेवलमà¥à¤²à¥à¤²à¥‡à¤–ितजनानां कृते वरà¥à¤¤à¤¤à¥‡", + "compose_form.direct_message_warning_learn_more": "अधिकं जà¥à¤žà¤¾à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.hashtag_warning": "न कसà¥à¤®à¤¿à¤¨à¥à¤¨à¤ªà¤¿ पà¥à¤°à¤šà¤²à¤¿à¤¤à¤µà¤¸à¥à¤¤à¥à¤·à¥ सूचितमिदं दौतà¥à¤¯à¤®à¥ । केवलं सारà¥à¤µà¤œà¤¨à¤¿à¤•दौतà¥à¤¯à¤¾à¤¨à¤¿ पà¥à¤°à¤šà¤²à¤¿à¤¤à¤µà¤¸à¥à¤¤à¥à¤šà¤¿à¤¹à¥à¤¨à¥‡à¤¨ अनà¥à¤µà¥‡à¤·à¤¯à¤¿à¤¤à¥à¤‚ शकà¥à¤¯à¤¤à¥‡ ।", + "compose_form.lock_disclaimer": "तव लेखा न पà¥à¤°à¤µà¥‡à¤·à¥à¤Ÿà¥à¤®à¤¶à¤•à¥à¤¯à¤¾ {locked} । कोऽपà¥à¤¯à¤¨à¥à¤¸à¤°à¥à¤¤à¤¾ ते केवलमनà¥à¤¸à¤°à¥à¤¤à¥ƒà¥ƒà¤£à¤¾à¤‚ कृते सà¥à¤¥à¤¿à¤¤à¤¾à¤¨à¤¿ दौतà¥à¤¯à¤¾à¤¨à¤¿ दà¥à¤°à¤·à¥à¤Ÿà¥à¤‚ शकà¥à¤¨à¥‹à¤¤à¤¿ ।", + "compose_form.lock_disclaimer.lock": "अवरà¥à¤¦à¥à¤§à¤ƒ", + "compose_form.placeholder": "मनसि ते किमसà¥à¤¤à¤¿?", + "compose_form.poll.add_option": "मतमपरं यà¥à¤œà¥à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.poll.duration": "मतदान-समयावधिः", + "compose_form.poll.option_placeholder": "मतमॠ{number}", + "compose_form.poll.remove_option": "मतमेतनà¥à¤¨à¤¶à¥à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.poll.switch_to_multiple": "मतदानं परिवरà¥à¤¤à¤¯à¤¿à¤¤à¥à¤µà¤¾ बहà¥à¤µà¥ˆà¤•लà¥à¤ªà¤¿à¤•मतदानं कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.poll.switch_to_single": "मतदानं परिवरà¥à¤¤à¤¯à¤¿à¤¤à¥à¤µà¤¾ निरà¥à¤µà¤¿à¤•लà¥à¤ªà¤®à¤¤à¤¦à¤¾à¤¨à¤‚ कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.publish": "दौतà¥à¤¯à¤®à¥", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.hide": "संवेदनशीलसामगà¥à¤°à¥€à¤¤à¥à¤¯à¤™à¥à¤¯à¤¤à¤¾à¤®à¥", + "compose_form.sensitive.marked": "संवेदनशीलसामगà¥à¤°à¥€à¤¤à¥à¤¯à¤™à¥à¤•ितमà¥", + "compose_form.sensitive.unmarked": "संवेदनशीलसामगà¥à¤°à¥€à¤¤à¤¿ नाङà¥à¤•ितमà¥", + "compose_form.spoiler.marked": "पà¥à¤°à¤šà¥à¤›à¤¾à¤¨à¥à¤¨à¤¾à¤•à¥à¤·à¤°à¤‚ विदà¥à¤¯à¤¤à¥‡", + "compose_form.spoiler.unmarked": "अपà¥à¤°à¤šà¥à¤›à¤¨à¥à¤¨à¤¾à¤•à¥à¤·à¤°à¤‚ विदà¥à¤¯à¤¤à¥‡", + "compose_form.spoiler_placeholder": "पà¥à¤°à¤¤à¥à¤¯à¤¾à¤¦à¥‡à¤¶à¤¸à¥à¤¤à¥‡ लिखà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmation_modal.cancel": "नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.block.block_and_report": "अवरà¥à¤§à¥à¤¯ आविदà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.block.confirm": "निषेधः", + "confirmations.block.message": "निशà¥à¤šà¤¯à¥‡à¤¨à¤¾à¤½à¤µà¤°à¥‹à¤§à¥‹ विधेयः {name}?", + "confirmations.delete.confirm": "नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.delete.message": "निशà¥à¤šà¤¯à¥‡à¤¨ दौतà¥à¤¯à¤®à¤¿à¤¦à¤‚ नशà¥à¤¯à¤¤à¤¾à¤®à¥?", + "confirmations.delete_list.confirm": "नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.delete_list.message": "सूचिरियं निशà¥à¤šà¤¯à¥‡à¤¨ सà¥à¤¥à¤¾à¤¯à¤¿à¤¤à¥à¤µà¥‡à¤¨ च नशà¥à¤¯à¤¤à¤¾à¤®à¥ वा?", + "confirmations.domain_block.confirm": "निषिदà¥à¤§à¤ƒ पà¥à¤°à¤¦à¥‡à¤¶à¤ƒ कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.domain_block.message": "नूनं निशà¥à¤šà¤¯à¥‡à¤¨à¥ˆà¤µ विनषà¥à¤Ÿà¥à¤®à¤¿à¤šà¥à¤›à¤¤à¤¿ पूरà¥à¤£à¤ªà¥à¤°à¤¦à¥‡à¤¶à¤®à¥‡à¤µ {domain} ? अधिकांशसनà¥à¤¦à¤°à¥à¤à¥‡à¤½à¤¸à¥à¤¥à¤¾à¤¯à¤¿à¤¤à¥à¤µà¥‡à¤¨ निषेधता निःशबà¥à¤¦à¤¤à¥à¤µà¤žà¥à¤š परà¥à¤¯à¤¾à¤ªà¥à¤¤à¤‚ चयनीयञà¥à¤š । न तसà¥à¤®à¤¾à¤¤à¥ पà¥à¤°à¤¦à¥‡à¤¶à¤¾à¤¤à¥à¤¸à¤°à¥à¤µà¥‡ विषया दà¥à¤°à¤·à¥à¤Ÿà¥à¤®à¤¶à¤•à¥à¤¯à¤¾à¤ƒ किसà¥à¤¯à¤¾à¤‚शà¥à¤šà¤¿à¤¦à¤ªà¤¿ सरà¥à¤µà¤œà¤¨à¤¿à¤•समयतालिकायां वा सà¥à¤µà¥€à¤¯à¤¸à¥‚चनापटले । सरà¥à¤µà¥‡à¤½à¤¨à¥à¤¸à¤°à¥à¤¤à¤¾à¤°à¤¸à¥à¤¤à¥‡ पà¥à¤°à¤¦à¥‡à¤¶à¤¾à¤¤à¥ ये सनà¥à¤¤à¤¿ ते नशà¥à¤¯à¤¨à¥à¤¤à¥‡ ।", + "confirmations.logout.confirm": "बहिरà¥à¤—मà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.logout.message": "निशà¥à¤šà¤¯à¥‡à¤¨à¥ˆà¤µ बहिरà¥à¤—मनं वाञà¥à¤›à¤¿à¤¤à¤®à¥?", + "confirmations.mute.confirm": "निःशबà¥à¤¦à¤®à¥", + "confirmations.mute.explanation": "à¤à¤¤à¥‡à¤¨ तेषां पà¥à¤°à¤•टनानि तथा च यतà¥à¤° ते उलà¥à¤²à¤¿à¤–िताः तानि छादà¥à¤¯à¤¨à¥à¤¤à¥‡, किनà¥à¤¤à¥à¤µà¥‡à¤µà¤‚ सतà¥à¤¯à¤ªà¤¿ ते तà¥à¤µà¤¾à¤®à¤¨à¥à¤¸à¤°à¥à¤¤à¥à¤‚ ततशà¥à¤š पà¥à¤°à¤•टनानि दà¥à¤°à¤·à¥à¤Ÿà¥à¤‚ शकà¥à¤¨à¥à¤µà¤¨à¥à¤¤à¤¿ ।", + "confirmations.mute.message": "किं निशà¥à¤šà¤¯à¥‡à¤¨ निःशबà¥à¤¦à¤‚ à¤à¤µà¥‡à¤¤à¥ {name} मितà¥à¤°à¤®à¥‡à¤¤à¤¤à¥ ?", + "confirmations.redraft.confirm": "विनशà¥à¤¯ पà¥à¤¨à¤ƒ लिखà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.redraft.message": "किं वा निशà¥à¤šà¤¯à¥‡à¤¨ नषà¥à¤Ÿà¥à¤®à¤¿à¤šà¥à¤›à¤¸à¤¿ दौतà¥à¤¯à¤®à¥‡à¤¤à¤¤à¥à¤¤à¤¥à¤¾ च पà¥à¤¨à¤ƒ लेखितà¥à¤‚? पà¥à¤°à¤•ाशनानि पà¥à¤°à¥€à¤¤à¤¯à¤¶à¥à¤š विनषà¥à¤Ÿà¤¾ à¤à¤µà¤¿à¤·à¥à¤¯à¤¨à¥à¤¤à¤¿, पà¥à¤°à¤¤à¥à¤¯à¥à¤¤à¥à¤¤à¤°à¤¾à¤£à¥à¤¯à¤ªà¤¿ नशà¥à¤¯à¤¨à¥à¤¤à¥‡ ।", + "confirmations.reply.confirm": "उतà¥à¤¤à¤°à¤®à¥", + "confirmations.reply.message": "पà¥à¤°à¤¤à¥à¤¯à¥à¤¤à¥à¤¤à¤°à¤®à¤¿à¤¦à¤¾à¤¨à¥€à¤‚ लिखà¥à¤¯à¤¤à¥‡ तरà¥à¤¹à¤¿ पूरà¥à¤µà¤²à¤¿à¤–ितसनà¥à¤¦à¥‡à¤¶à¤‚ विनशà¥à¤¯ पà¥à¤¨à¤ƒ लिखà¥à¤¯à¤¤à¥‡ । निशà¥à¤šà¤¯à¥‡à¤¨à¥ˆà¤µà¤‚ करà¥à¤¤à¤µà¥à¤¯à¤®à¥ ?", + "confirmations.unfollow.confirm": "अनà¥à¤¸à¤°à¤£à¤‚ नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "confirmations.unfollow.message": "निशà¥à¤šà¤¯à¥‡à¤¨à¥ˆà¤µà¤¾à¤½à¤¨à¥à¤¸à¤°à¤£à¤‚ नशà¥à¤¯à¤¤à¤¾à¤‚ {name} मितà¥à¤°à¤¸à¥à¤¯?", + "conversation.delete": "वारà¥à¤¤à¤¾à¤²à¤¾à¤ªà¥‹ नशà¥à¤¯à¤¤à¤¾à¤®à¥", + "conversation.mark_as_read": "पठितमितà¥à¤¯à¤™à¥à¤•à¥à¤¯à¤¤à¤¾à¤®à¥", + "conversation.open": "वारà¥à¤¤à¤¾à¤²à¤¾à¤ªà¥‹ दृशà¥à¤¯à¤¤à¤¾à¤®à¥", + "conversation.with": "{names} जनैः साकमà¥", + "directory.federated": "सà¥à¤ªà¤°à¤¿à¤šà¤¿à¤¤à¤‚ Fediverse इति सà¥à¤¥à¤¾à¤¨à¤¾à¤¤à¥", + "directory.local": "{domain} पà¥à¤°à¤¦à¥‡à¤¶à¤¾à¤¤à¥à¤•ेवलमà¥", + "directory.new_arrivals": "नवामगमाः", + "directory.recently_active": "नातिपूरà¥à¤µà¤‚ सकà¥à¤°à¤¿à¤¯à¤ƒ", + "embed.instructions": "दौतà¥à¤¯à¤®à¥‡à¤¤à¤¤à¥ सà¥à¤µà¥€à¤¯à¤œà¤¾à¤²à¤¸à¥à¤¥à¤¾à¤¨à¥‡ सà¥à¤¥à¤¾à¤ªà¤¯à¤¿à¤¤à¥à¤®à¤§à¥‹ लिखितो विधà¥à¤¯à¤¾à¤¦à¥‡à¤¶à¥‹ यà¥à¤œà¥à¤¯à¤¤à¤¾à¤®à¥", + "embed.preview": "अतà¥à¤°à¥ˆà¤µà¤‚ दृशà¥à¤¯à¤¤à¥‡ ततà¥:", + "emoji_button.activity": "आचरणमà¥", + "emoji_button.custom": "सà¥à¤µà¥€à¤¯à¤¾à¤¨à¥à¤•ूलमà¥", + "emoji_button.flags": "धà¥à¤µà¤œà¤¾à¤ƒ", + "emoji_button.food": "à¤à¥‹à¤œà¤¨à¤‚ पेयञà¥à¤š", + "emoji_button.label": "à¤à¤¾à¤µà¤šà¤¿à¤¹à¥à¤¨à¤‚ यà¥à¤œà¥à¤¯à¤¤à¤¾à¤®à¥", + "emoji_button.nature": "पà¥à¤°à¤•ृतिः", + "emoji_button.not_found": "न à¤à¤¾à¤µà¤šà¤¿à¤¹à¥à¤¨à¤¾à¤¨à¤¿ (╯°□°)╯︵ â”»â”â”»", + "emoji_button.objects": "वसà¥à¤¤à¥‚नि", + "emoji_button.people": "जनाः", + "emoji_button.recent": "आधिकà¥à¤¯à¥‡à¤¨ पà¥à¤°à¤¯à¥à¤•à¥à¤¤à¤®à¥", + "emoji_button.search": "अनà¥à¤µà¤¿à¤·à¥à¤¯à¤¤à¤¾à¤®à¥...", + "emoji_button.search_results": "अनà¥à¤µà¥‡à¤·à¤£à¤ªà¤°à¤¿à¤£à¤¾à¤®à¤¾à¤ƒ", + "emoji_button.symbols": "चिहà¥à¤¨à¤¾à¤¨à¤¿", + "emoji_button.travel": "यातà¥à¤°à¤¾ च सà¥à¤¥à¤¾à¤¨à¤¾à¤¨à¤¿", + "empty_column.account_suspended": "Account suspended", + "empty_column.account_timeline": "न दौतà¥à¤¯à¤¾à¤¨à¥à¤¯à¤¤à¥à¤°", + "empty_column.account_unavailable": "वà¥à¤¯à¤•à¥à¤¤à¤¿à¤¤à¥à¤µà¤‚ न पà¥à¤°à¤¾à¤ªà¥à¤¯à¤¤à¥‡", + "empty_column.blocks": "नैकोऽपà¥à¤¯à¥à¤ªà¤à¥‹à¤•à¥à¤¤à¤¾ निषिदà¥à¤§à¥‹ वरà¥à¤¤à¤¤à¥‡", + "empty_column.bookmarked_statuses": "नैकमपि पà¥à¤Ÿà¤šà¤¿à¤¹à¥à¤¨à¤¯à¥à¤•à¥à¤¤à¤¦à¥Œà¤¤à¥à¤¯à¤¾à¤¨à¤¿ सनà¥à¤¤à¤¿ । यदा à¤à¤µà¤¿à¤·à¥à¤¯à¤¤à¤¿ तदतà¥à¤° दृशà¥à¤¯à¤¤à¥‡ ।", + "empty_column.community": "सà¥à¤¥à¤¾à¤¨à¥€à¤¯à¤¸à¤®à¤¯à¤¤à¤¾à¤²à¤¿à¤•ा रिकà¥à¤¤à¤¾ । सारà¥à¤µà¤œà¤¨à¤¿à¤•तà¥à¤µà¥‡à¤¨à¤¾à¤½à¤¤à¥à¤° किमपि लिखà¥à¤¯à¤¤à¤¾à¤®à¥ ।", + "empty_column.direct": "नैकोऽपि पà¥à¤°à¤¤à¥à¤¯à¤•à¥à¤·à¤¸à¤¨à¥à¤¦à¥‡à¤¶à¥‹ वरà¥à¤¤à¤¤à¥‡ । यदा पà¥à¤°à¥‡à¤·à¥à¤¯à¤¤à¥‡ वा पà¥à¤°à¤¾à¤ªà¥à¤¯à¤¤à¥‡à¤½à¤¤à¥à¤° दृशà¥à¤¯à¤¤à¥‡", + "empty_column.domain_blocks": "न निषिदà¥à¤§à¤ªà¥à¤°à¤¦à¥‡à¤¶à¤¾à¤ƒ सनà¥à¤¤à¤¿ ।", + "empty_column.favourited_statuses": "न पà¥à¤°à¤¿à¤¯à¤¦à¥Œà¤¤à¥à¤¯à¤¾à¤¨à¤¿ सनà¥à¤¤à¤¿ । यदा पà¥à¤°à¥€à¤¤à¤¿à¤°à¤¿à¤¤à¥à¤¯à¤™à¥à¤•à¥à¤¯à¤¤à¥‡à¤½à¤¤à¥à¤° दृशà¥à¤¯à¤¤à¥‡ ।", + "empty_column.favourites": "नैतदà¥à¤¦à¥Œà¤¤à¥à¤¯à¤‚ पà¥à¤°à¤¿à¤¯à¤®à¤¸à¥à¤¤à¤¿ कसà¥à¤®à¥ˆ अपि । यदा कसà¥à¤®à¥ˆ पà¥à¤°à¤¿à¤¯à¤‚ à¤à¤µà¤¤à¤¿ तदाऽतà¥à¤° दृशà¥à¤¯à¤¤à¥‡ ।", + "empty_column.follow_requests": "नाऽनà¥à¤¸à¤°à¤£à¤¾à¤¨à¥à¤°à¥‹à¤§à¤¸à¥à¤¤à¥‡ वरà¥à¤¤à¤¤à¥‡ । यदैको पà¥à¤°à¤¾à¤ªà¥à¤¯à¤¤à¥‡à¤½à¤¤à¥à¤° दृशà¥à¤¯à¤¤à¥‡ ।", + "empty_column.hashtag": "नाऽसà¥à¤®à¤¿à¤¨à¥ पà¥à¤°à¤šà¤²à¤¿à¤¤à¤µà¤¸à¥à¤¤à¥à¤šà¤¿à¤¹à¥à¤¨à¥‡ किमपि ।", + "empty_column.home": "गृहसमयतालिका रिकà¥à¤¤à¤¾à¤½à¤¸à¥à¤¤à¤¿ । गमà¥à¤¯à¤¤à¤¾à¤‚ {public} वाऽनà¥à¤µà¥‡à¤·à¤£à¥ˆà¤ƒ पà¥à¤°à¤¾à¤°à¤à¥à¤¯à¤¤à¤¾à¤‚ मेलनं कà¥à¤°à¤¿à¤¯à¤¤à¤¾à¤žà¥à¤š ।", + "empty_column.home.public_timeline": "सारà¥à¤µà¤œà¤¨à¤¿à¤•समयतालिका", + "empty_column.list": "न किमपि वरà¥à¤¤à¤¤à¥‡ सूचà¥à¤¯à¤¾à¤®à¤¸à¥à¤¯à¤¾à¤®à¥ । यदा सूचà¥à¤¯à¤¾à¤ƒ सदसà¥à¤¯à¤¾ नवदौतà¥à¤¯à¤¾à¤¨à¤¿ पà¥à¤°à¤•टीकà¥à¤°à¥à¤µà¤¨à¥à¤¤à¤¿ तदाऽतà¥à¤°à¤¾à¤½à¤½à¤¯à¤¾à¤¨à¥à¤¤à¤¿ ।", + "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", + "empty_column.mutes": "You haven't muted any users yet.", + "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", + "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", + "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", + "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", + "errors.unexpected_crash.report_issue": "Report issue", + "follow_request.authorize": "Authorize", + "follow_request.reject": "Reject", + "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", + "generic.saved": "Saved", + "getting_started.developers": "Developers", + "getting_started.directory": "Profile directory", + "getting_started.documentation": "Documentation", + "getting_started.heading": "Getting started", + "getting_started.invite": "Invite people", + "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", + "getting_started.security": "Security", + "getting_started.terms": "Terms of service", + "hashtag.column_header.tag_mode.all": "and {additional}", + "hashtag.column_header.tag_mode.any": "or {additional}", + "hashtag.column_header.tag_mode.none": "without {additional}", + "hashtag.column_settings.select.no_options_message": "No suggestions found", + "hashtag.column_settings.select.placeholder": "Enter hashtags…", + "hashtag.column_settings.tag_mode.all": "All of these", + "hashtag.column_settings.tag_mode.any": "Any of these", + "hashtag.column_settings.tag_mode.none": "None of these", + "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "home.column_settings.basic": "Basic", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Show replies", + "home.hide_announcements": "Hide announcements", + "home.show_announcements": "Show announcements", + "intervals.full.days": "{number, plural, one {# day} other {# days}}", + "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "introduction.federation.action": "Next", + "introduction.federation.federated.headline": "Federated", + "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.home.headline": "Home", + "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", + "introduction.federation.local.headline": "Local", + "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", + "introduction.interactions.action": "Finish toot-orial!", + "introduction.interactions.favourite.headline": "Favourite", + "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", + "introduction.interactions.reblog.headline": "Boost", + "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", + "introduction.interactions.reply.headline": "Reply", + "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", + "introduction.welcome.action": "Let's go!", + "introduction.welcome.headline": "First steps", + "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "keyboard_shortcuts.back": "to navigate back", + "keyboard_shortcuts.blocked": "to open blocked users list", + "keyboard_shortcuts.boost": "to boost", + "keyboard_shortcuts.column": "to focus a status in one of the columns", + "keyboard_shortcuts.compose": "to focus the compose textarea", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.direct": "to open direct messages column", + "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.favourites": "to open favourites list", + "keyboard_shortcuts.federated": "to open federated timeline", + "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.local": "to open local timeline", + "keyboard_shortcuts.mention": "to mention author", + "keyboard_shortcuts.muted": "to open muted users list", + "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.notifications": "to open notifications column", + "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.pinned": "to open pinned toots list", + "keyboard_shortcuts.profile": "to open author's profile", + "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.search": "to focus search", + "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.start": "to open \"get started\" column", + "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", + "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.up": "to move up in the list", + "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "Next", + "lightbox.previous": "Previous", + "lists.account.add": "Add to list", + "lists.account.remove": "Remove from list", + "lists.delete": "Delete list", + "lists.edit": "Edit list", + "lists.edit.submit": "Change title", + "lists.new.create": "Add list", + "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", + "lists.search": "Search among people you follow", + "lists.subheading": "Your lists", + "load_pending": "{count, plural, one {# new item} other {# new items}}", + "loading_indicator.label": "Loading...", + "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", + "missing_indicator.label": "Not found", + "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", + "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", + "navigation_bar.apps": "Mobile apps", + "navigation_bar.blocks": "Blocked users", + "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.compose": "Compose new toot", + "navigation_bar.direct": "Direct messages", + "navigation_bar.discover": "Discover", + "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.favourites": "Favourites", + "navigation_bar.filters": "Muted words", + "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.follows_and_followers": "Follows and followers", + "navigation_bar.info": "About this server", + "navigation_bar.keyboard_shortcuts": "Hotkeys", + "navigation_bar.lists": "Lists", + "navigation_bar.logout": "Logout", + "navigation_bar.mutes": "Muted users", + "navigation_bar.personal": "Personal", + "navigation_bar.pins": "Pinned toots", + "navigation_bar.preferences": "Preferences", + "navigation_bar.public_timeline": "Federated timeline", + "navigation_bar.security": "Security", + "notification.favourite": "{name} favourited your status", + "notification.follow": "{name} followed you", + "notification.follow_request": "{name} has requested to follow you", + "notification.mention": "{name} mentioned you", + "notification.own_poll": "Your poll has ended", + "notification.poll": "A poll you have voted in has ended", + "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", + "notifications.clear": "Clear notifications", + "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.column_settings.alert": "Desktop notifications", + "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notifications.column_settings.filter_bar.category": "Quick filter bar", + "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.follow": "New followers:", + "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Show in column", + "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", + "notifications.filter.all": "All", + "notifications.filter.boosts": "Boosts", + "notifications.filter.favourites": "Favourites", + "notifications.filter.follows": "Follows", + "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", + "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", + "poll.closed": "Closed", + "poll.refresh": "Refresh", + "poll.total_people": "{count, plural, one {# person} other {# people}}", + "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", + "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll_button.add_poll": "Add a poll", + "poll_button.remove_poll": "Remove poll", + "privacy.change": "Adjust status privacy", + "privacy.direct.long": "Visible for mentioned users only", + "privacy.direct.short": "Direct", + "privacy.private.long": "Visible for followers only", + "privacy.private.short": "Followers-only", + "privacy.public.long": "Visible for all, shown in public timelines", + "privacy.public.short": "Public", + "privacy.unlisted.long": "Visible for all, but not in public timelines", + "privacy.unlisted.short": "Unlisted", + "refresh": "Refresh", + "regeneration_indicator.label": "Loading…", + "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "now", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "relative_time.today": "today", + "reply_indicator.cancel": "Cancel", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Additional comments", + "report.submit": "Submit", + "report.target": "Report {target}", + "search.placeholder": "Search", + "search_popout.search_format": "Advanced search format", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "search_popout.tips.status": "status", + "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", + "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", + "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "status.admin_account": "Open moderation interface for @{name}", + "status.admin_status": "Open this status in the moderation interface", + "status.block": "Block @{name}", + "status.bookmark": "Bookmark", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "This post cannot be boosted", + "status.copy": "Copy link to status", + "status.delete": "Delete", + "status.detailed_status": "Detailed conversation view", + "status.direct": "Direct message @{name}", + "status.embed": "Embed", + "status.favourite": "Favourite", + "status.filtered": "Filtered", + "status.load_more": "Load more", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "More", + "status.mute": "Mute @{name}", + "status.mute_conversation": "Mute conversation", + "status.open": "Expand this status", + "status.pin": "Pin on profile", + "status.pinned": "Pinned toot", + "status.read_more": "Read more", + "status.reblog": "Boost", + "status.reblog_private": "Boost with original visibility", + "status.reblogged_by": "{name} boosted", + "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", + "status.redraft": "Delete & re-draft", + "status.remove_bookmark": "Remove bookmark", + "status.reply": "Reply", + "status.replyAll": "Reply to thread", + "status.report": "Report @{name}", + "status.sensitive_warning": "Sensitive content", + "status.share": "Share", + "status.show_less": "Show less", + "status.show_less_all": "Show less for all", + "status.show_more": "Show more", + "status.show_more_all": "Show more for all", + "status.show_thread": "Show thread", + "status.uncached_media_warning": "Not available", + "status.unmute_conversation": "Unmute conversation", + "status.unpin": "Unpin from profile", + "suggestions.dismiss": "Dismiss suggestion", + "suggestions.header": "You might be interested in…", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "Home", + "tabs_bar.local_timeline": "Local", + "tabs_bar.notifications": "Notifications", + "tabs_bar.search": "Search", + "time_remaining.days": "{number, plural, one {# day} other {# days}} left", + "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", + "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", + "time_remaining.moments": "Moments remaining", + "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", + "timeline_hint.resources.followers": "Followers", + "timeline_hint.resources.follows": "Follows", + "timeline_hint.resources.statuses": "Older toots", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.trending_now": "Trending now", + "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "units.short.billion": "{count}B", + "units.short.million": "{count}M", + "units.short.thousand": "{count}K", + "upload_area.title": "Drag & drop to upload", + "upload_button.label": "Add images, a video or an audio file", + "upload_error.limit": "File upload limit exceeded.", + "upload_error.poll": "File upload not allowed with polls.", + "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.description": "Describe for the visually impaired", + "upload_form.edit": "Edit", + "upload_form.thumbnail": "Change thumbnail", + "upload_form.undo": "Delete", + "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_modal.analyzing_picture": "Analyzing picture…", + "upload_modal.apply": "Apply", + "upload_modal.choose_image": "Choose image", + "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", + "upload_modal.detect_text": "Detect text from picture", + "upload_modal.edit_media": "Edit media", + "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", + "upload_modal.preview_label": "Preview ({ratio})", + "upload_progress.label": "Uploading…", + "video.close": "Close video", + "video.download": "Download file", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound" +} diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 30a3e33745b1fff6f40a50827ef7c86932534cc7..e1b4e39987d7bdd79f2d2f51f2365a227105399e 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -1,53 +1,55 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Nota", "account.add_or_remove_from_list": "Agiunghe o boga dae is listas", "account.badges.bot": "Bot", "account.badges.group": "Grupu", "account.block": "Bloca @{name}", - "account.block_domain": "Bloca domìniu{domain}", + "account.block_domain": "Bloca su domìniu {domain}", "account.blocked": "Blocadu", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Esplora de prus in su profilu originale", "account.cancel_follow_request": "Annulla rechesta de sighidura", "account.direct": "Messà giu deretu a @{name}", + "account.disable_notifications": "Non mi notìfiches prus cando @{name} pùblichet messà gios", "account.domain_blocked": "Domìniu blocadu", "account.edit_profile": "Modìfica profilu", + "account.enable_notifications": "Notìfica·mi cando @{name} pùblicat messà gios", "account.endorse": "Cussìgia in su profilu tuo", "account.follow": "Sighi", "account.followers": "Sighiduras", "account.followers.empty": "Nemos sighit ancora custa persone.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} sighidura} other {{counter} sighiduras}}", + "account.following_counter": "{count, plural, one {Sighende a {counter}} other {Sighende a {counter}}}", "account.follows.empty": "Custa persone non sighit ancora a nemos.", "account.follows_you": "Ti sighit", "account.hide_reblogs": "Cua is cumpartziduras de @{name}", "account.last_status": "Ùrtima atividade", - "account.link_verified_on": "Sa propiedade de custu ligà mene est istada controllada su {date}", - "account.locked_info": "Sa persone chi tenet sa propiedade revisionat a manu chie dda podet sighire.", + "account.link_verified_on": "Sa propiedade de custu ligòngiu est istada controllada su {date}", + "account.locked_info": "S'istadu de riservadesa de custu contu est istadu cunfiguradu comente blocadu. Sa persone chi tenet sa propiedade revisionat a manu chie dda podet sighire.", "account.media": "Cuntenutu multimediale", - "account.mention": "Mentova @{name}", - "account.moved_to": "{name} est istadu trasferidu a:", - "account.mute": "Pone @name a sa muda", - "account.mute_notifications": "Notìficas disativadas dae @{name}", + "account.mention": "Mentova a @{name}", + "account.moved_to": "{name} at cambiadu a:", + "account.mute": "Pone a @{name} a sa muda", + "account.mute_notifications": "Disativa is notìficas de @{name}", "account.muted": "A sa muda", "account.never_active": "Mai", "account.posts": "Tuts", "account.posts_with_replies": "Tuts e rispostas", "account.report": "Signala @{name}", - "account.requested": "Incarca pro annullare sa rechesta de sighidura", + "account.requested": "Abetende s'aprovatzione. Incarca pro annullare sa rechesta de sighidura", "account.share": "Cumpartzi su profilu de @{name}", "account.show_reblogs": "Ammustra is cumpartziduras de @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", - "account.unblock": "Isbloca @{name}", + "account.statuses_counter": "{count, plural, one {{counter} tut} other {{counter} tuts}}", + "account.unblock": "Isbloca a @{name}", "account.unblock_domain": "Isbloca su domìniu {domain}", "account.unendorse": "Non cussiges in su profilu", "account.unfollow": "Non sigas prus", "account.unmute": "Torra a ativare @{name}", "account.unmute_notifications": "Ativa notìficas pro @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Incarca pro agiùnghere una nota", "alert.rate_limited.message": "Torra·bi a proare a pustis de {retry_time, time, medium}.", "alert.rate_limited.title": "Mà ssimu de rechestas barigadu", "alert.unexpected.message": "B'at à pidu una faddina.", - "alert.unexpected.title": "Oops!", + "alert.unexpected.title": "Oh!", "announcement.announcement": "Annùntziu", "autosuggest_hashtag.per_week": "{count} a sa chida", "boost_modal.combo": "Podes incarcare {combo} pro brincare custu sa borta chi benit", @@ -58,7 +60,7 @@ "bundle_modal_error.message": "Faddina in su carrigamentu de custu cumponente.", "bundle_modal_error.retry": "Torra·bi a proare", "column.blocks": "Persones blocadas", - "column.bookmarks": "Marcadores", + "column.bookmarks": "Sinnalibros", "column.community": "Lìnia de tempus locale", "column.direct": "Messà gios diretos", "column.directory": "Nà viga in is profilos", @@ -71,7 +73,7 @@ "column.notifications": "Notìficas", "column.pins": "Tuts apicados", "column.public": "Lìnia de tempus federada", - "column_back_button.label": "In segus", + "column_back_button.label": "A coa", "column_header.hide_settings": "Cua is cunfiguratziones", "column_header.moveLeft_settings": "Moe sa colunna a manca", "column_header.moveRight_settings": "Moe sa colunna a dereta", @@ -79,13 +81,13 @@ "column_header.show_settings": "Ammustra is cunfiguratziones", "column_header.unpin": "Boga dae pitzu", "column_subheading.settings": "Cunfiguratziones", - "community.column_settings.local_only": "Local only", - "community.column_settings.media_only": "Multimediale isceti", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.local_only": "Isceti locale", + "community.column_settings.media_only": "Isceti multimediale", + "community.column_settings.remote_only": "Isceti remotu", "compose_form.direct_message_warning": "Custu tut at a èssere imbiadu isceti a is persones mentovadas.", "compose_form.direct_message_warning_learn_more": "Àteras informatziones", - "compose_form.hashtag_warning": "Custu tut no at a èssere ammustradu in peruna eticheta, dae chi no est listadu.", - "compose_form.lock_disclaimer": "Cale si siat persone ti podet sighire pro bìdere is messà gios tuos chi imbies a is chi ti sighint.", + "compose_form.hashtag_warning": "Custu tut no at a èssere ammustradu in peruna eticheta, dae chi no est listadu. Isceti is tuts pùblicos podent èssere chircados cun etichetas.", + "compose_form.lock_disclaimer": "Su contu tuo no est {locked}. Cale si siat persone ti podet sighire pro bìdere is messà gios tuos chi imbies a sa gente chi ti sighit.", "compose_form.lock_disclaimer.lock": "blocadu", "compose_form.placeholder": "A ite ses pensende?", "compose_form.poll.add_option": "Agiunghe unu sèberu", @@ -96,10 +98,10 @@ "compose_form.poll.switch_to_single": "Muda su sondà giu pro permìtere un'optzione isceti", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Marca mèdia comente a sensìbile", - "compose_form.sensitive.marked": "Mèdia marcadu comente a sensìbile", - "compose_form.sensitive.unmarked": "Mèdia non marcadu comente a sensìbile", - "compose_form.spoiler.marked": "Su testu est cuadu dae s'avisu", + "compose_form.sensitive.hide": "{count, plural, one {Marca elementu multimediale comente a sensìbile} other {Marca elementos multimediales comente sensìbiles}}", + "compose_form.sensitive.marked": "{count, plural, one {Elementu multimediale marcadu comente a sensìbile} other {Elementos multimediales marcados comente a sensìbiles}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Elementu multimediale non marcadu comente a sensìbile} other {Elementos multimediales non marcados comente a sensìbiles}}", + "compose_form.spoiler.marked": "Su testu est cuadu in fatu de s'avisu", "compose_form.spoiler.unmarked": "Su testu no est cuadu", "compose_form.spoiler_placeholder": "Iscrie s'avisu tuo inoghe", "confirmation_modal.cancel": "Annulla", @@ -110,24 +112,24 @@ "confirmations.delete.message": "Seguru chi boles cantzellare custu tut?", "confirmations.delete_list.confirm": "Cantzella", "confirmations.delete_list.message": "Seguru chi boles cantzellare custa lista in manera permanente?", - "confirmations.domain_block.confirm": "Cua totu su domìniu", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.confirm": "Bloca totu su domìniu", + "confirmations.domain_block.message": "Boles de seguru, ma a beru a beru, blocare su {domain} intreu? In sa parte manna de is casos pagos blocos o silentziamentos de persones sunt sufitzientes e preferìbiles. No as a bìdere cuntenutos dae custu domìniu in peruna lìnia de tempus pùblica o in is notìficas tuas. Sa gente chi ti sighit dae cussu domìniu at a èssere bogada.", "confirmations.logout.confirm": "Essi·nche", "confirmations.logout.message": "Seguru chi boles essire?", "confirmations.mute.confirm": "A sa muda", "confirmations.mute.explanation": "Custu at a cuare is publicatziones issoro e is messà gios chi ddos mentovant, ma ant a pòdere bìdere is messà gios tuos e t'ant a pòdere sighire.", - "confirmations.mute.message": "Seguru chi boles pònnere {name} a sa muda?", + "confirmations.mute.message": "Seguru chi boles pònnere a {name} a sa muda?", "confirmations.redraft.confirm": "Cantzella e torra a fà ghere", - "confirmations.redraft.message": "As a pèrdere is preferidos e is cumpartziduras, e is rispostas a su messà giu originale ant a abarrare òrfanas.", + "confirmations.redraft.message": "Seguru chi boles cantzellare a torrare a fà ghere custu tut? As a pèrdere is preferidos e is cumpartziduras, e is rispostas a su messà giu originale ant a abarrare òrfanas.", "confirmations.reply.confirm": "Risponde", "confirmations.reply.message": "Rispondende immoe as a subraiscrìere su messà giu chi ses iscriende. Seguru chi boles sighire?", "confirmations.unfollow.confirm": "Non sigas prus", - "confirmations.unfollow.message": "Seguru chi non boles sighire prus {name}?", + "confirmations.unfollow.message": "Seguru chi non boles sighire prus a {name}?", "conversation.delete": "Cantzella arresonada", "conversation.mark_as_read": "Signala comente lèghidu", - "conversation.open": "Bide arresonada", + "conversation.open": "Ammsutra arresonada", "conversation.with": "Cun {names}", - "directory.federated": "Dae unu fediversu connòschidu", + "directory.federated": "Dae unu fediversu connotu", "directory.local": "Isceti dae {domain}", "directory.new_arrivals": "Arribos noos", "directory.recently_active": "Ativos dae pagu", @@ -147,14 +149,15 @@ "emoji_button.search_results": "Resurtados de sa chirca", "emoji_button.symbols": "Sìmbulos", "emoji_button.travel": "Bià gios e logos", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Perunu tut inoghe!", "empty_column.account_unavailable": "Su profilu no est a disponimentu", - "empty_column.blocks": "No as isblocadu ancora nemos.", + "empty_column.blocks": "No as blocadu ancora nemos.", "empty_column.bookmarked_statuses": "Non tenes ancora perunu tut in is marcadores. Cando nd'as a agiùnghere unu, at a èssere ammustradu inoghe.", "empty_column.community": "Sa lìnia de tempus locale est bòida. Iscrie inoghe pro cumintzare sa festa!", "empty_column.direct": "Non tenes ancora perunu messà giu deretu. Cando nd'as a imbiare o nd'as a retzire unu, at a èssere ammustradu inoghe.", "empty_column.domain_blocks": "Non tenes ancora perunu domìniu blocadu.", - "empty_column.favourited_statuses": "Non tenes ancora perunu tut in is marcadores. Cando nd'as a agiùnghere unu, at a èssere ammustradu inoghe.", + "empty_column.favourited_statuses": "Non tenes ancora perunu tut in is preferidos. Cando nd'as a agiùnghere unu, at a èssere ammustradu inoghe.", "empty_column.favourites": "Nemos at marcadu ancora custu tut comente preferidu. Cando calicunu dd'at a fà ghere, at a èssere ammustradu inoghe.", "empty_column.follow_requests": "Non tenes ancora peruna rechesta de sighidura. Cando nd'as a retzire una, at a èssere ammustrada inoghe.", "empty_column.hashtag": "Ancora nudda in custa eticheta.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Non tenes ancora peruna notìfica. Chistiona cun una persone pro cumintzare un'arresonada.", "empty_column.public": "Nudda inoghe. Iscrie calicuna cosa pùblica, o sighi à teras persones de à teros serbidores pro prenare custu ispà tziu", "error.unexpected_crash.explanation": "A cà usa de una faddina in su còdighe nostru o unu problema de cumpatibilidade de su navigadore, custa pà gina diat pòdere no èssere ammustrada in manera curreta.", - "error.unexpected_crash.next_steps": "Proa de atualizare sa pà gina. Si custu non acontza su problema, podes chircare de impreare Mastodon in unu navigadore diferente o in un'aplicatzione nativa.", + "error.unexpected_crash.explanation_addons": "Custa pà gina diat pòdere no èssere ammustrada comente si tocat. Custa faddina est probà bile chi dipendat dae un'estensione de su navigadore o dae ainas automà ticas de tradutzione.", + "error.unexpected_crash.next_steps": "Proa de torrare a carrigare sa pà gina. Si custu no acontza su problema, podes chircare de impreare Mastodon in unu navigadore diferente o in un'aplicatzione nativa.", + "error.unexpected_crash.next_steps_addons": "Proa a ddos disabilitare e torra a carrigare sa pà gina. Si custu no acontzat su problema, podes chircare de impreare Mastodon in unu navigadore diferente o in un'aplicatzione nativa.", "errors.unexpected_crash.copy_stacktrace": "Còpia stacktrace in punta de billete", "errors.unexpected_crash.report_issue": "Signala unu problema", "follow_request.authorize": "Autoriza", "follow_request.reject": "Refuda", "follow_requests.unlocked_explanation": "Fintzas si su contu tuo no est blocadu, su personale de {domain} at pensadu chi forsis bolias revisionare a manu is rechestas de custos contos.", - "generic.saved": "Saved", + "generic.saved": "Sarvadu", "getting_started.developers": "Iscuadra de isvilupu", "getting_started.directory": "Diretòriu de profilos", "getting_started.documentation": "Documentatzione", @@ -195,14 +200,14 @@ "home.column_settings.show_replies": "Ammustra rispostas", "home.hide_announcements": "Cua annùntzios", "home.show_announcements": "Ammustra annùntzios", - "intervals.full.days": "{number, plural, one {# die} other {# die}}", + "intervals.full.days": "{number, plural, one {# die} other {# dies}}", "intervals.full.hours": "{number, plural, one {# ora} other {# oras}}", "intervals.full.minutes": "{number, plural, one {# minutu} other {# minutos}}", "introduction.federation.action": "Sighi", "introduction.federation.federated.headline": "Federada", "introduction.federation.federated.text": "Is publicatziones pùblicas de à teros serbidores de su fediversu ant a aparèssere in sa lìnia de tempus federada.", "introduction.federation.home.headline": "Printzipale", - "introduction.federation.home.text": "Is messà gios de gente chi sighis ant a aparèssere in lìnia de tempus printzipale tua. Podes sighire gente de cale si siat serbidore.", + "introduction.federation.home.text": "Is messà gios de sa gente chi sighis ant a aparèssere in sa lìnia de tempus printzipale tua. Podes sighire gente de cale si siat serbidore!", "introduction.federation.local.headline": "Locale", "introduction.federation.local.text": "Is publicatziones pùblicas de sa gente de su pròpiu serbidore tuo ant a aparèssere in sa lìnia de tempus locale.", "introduction.interactions.action": "Acabba su tutoriale!", @@ -214,16 +219,16 @@ "introduction.interactions.reply.text": "Podes rispòndere a is tuts de à tera gente e a is tuos pròpios, e ant a èssere unidos in un'arresonada.", "introduction.welcome.action": "Ajò, andamus!", "introduction.welcome.headline": "Primos passos", - "introduction.welcome.text": "Ti donamus sa benebènnida a su fediversu. Dae immoe a pagu, as a pòdere publicare messà gios e chistionare cun is amistades tuas in meda serbidores. Però custu serbidore, {domain}, est ispetziale: allògiat su profilu tuo, duncas regorda·nde si nòmine.", + "introduction.welcome.text": "Ti donamus sa benebènnida a su fediversu. Dae immoe a pagu, as a pòdere publicare messà gios e chistionare cun is amistades tuas in meda serbidores. Però custu serbidore, {domain}, est ispetziale: allògiat su profilu tuo, duncas regorda·ti·nde su nòmine.", "keyboard_shortcuts.back": "pro navigare in segus", "keyboard_shortcuts.blocked": "pro abèrrere sa lista de persones blocadas", "keyboard_shortcuts.boost": "pro cumpartzire", - "keyboard_shortcuts.column": "pro atzentrare un'istadu in una de is colunnas", + "keyboard_shortcuts.column": "pro atzentrare unu tut in una de is colunnas", "keyboard_shortcuts.compose": "pro atzentrare in s'à rea de cumpositzione de testu", "keyboard_shortcuts.description": "Descritzione", "keyboard_shortcuts.direct": "pro abèrrere sa colunna de messà gios diretos", "keyboard_shortcuts.down": "pro mòere in bà sciu in sa lista", - "keyboard_shortcuts.enter": "pro abèrrere s'istadu", + "keyboard_shortcuts.enter": "pro abèrrere su tut", "keyboard_shortcuts.favourite": "pro marcare comente a preferidu", "keyboard_shortcuts.favourites": "pro abèrrere sa lista de preferidos", "keyboard_shortcuts.federated": "pro abèrrere sa lìnia de tempus federada", @@ -236,41 +241,48 @@ "keyboard_shortcuts.muted": "pro abèrrere sa lista de persones a sa muda", "keyboard_shortcuts.my_profile": "pro abèrrere su profilu tuo", "keyboard_shortcuts.notifications": "pro abèrrere sa colunna de notificatziones", - "keyboard_shortcuts.open_media": "pro abèrrere mèdia", + "keyboard_shortcuts.open_media": "pro abèrrere elementos multimediales", "keyboard_shortcuts.pinned": "pro abèrrere lista de tuts apicados", "keyboard_shortcuts.profile": "pro abèrrere su profilu de s'autore", "keyboard_shortcuts.reply": "pro rispòndere", "keyboard_shortcuts.requests": "pro abèrrere sa lista de rechestas de sighidura", "keyboard_shortcuts.search": "pro atzentrare sa chirca", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "pro ammustrare/cuare su campu AC", "keyboard_shortcuts.start": "pro abèrrere sa colunna \"Cumintza\"", - "keyboard_shortcuts.toggle_hidden": "pro ammustrare o cuare testu de is CW", - "keyboard_shortcuts.toggle_sensitivity": "pro ammustrare o cuare mèdias", + "keyboard_shortcuts.toggle_hidden": "pro ammustrare o cuare testu de is AC", + "keyboard_shortcuts.toggle_sensitivity": "pro ammustrare o cuare elementos multimediales", "keyboard_shortcuts.toot": "pro cumintzare a iscrìere unu tut nou", "keyboard_shortcuts.unfocus": "pro essire de s'à rea de cumpositzione de testu o de chirca", "keyboard_shortcuts.up": "pro mòere in susu in sa lista", "lightbox.close": "Serra", + "lightbox.compress": "Cumprime sa casella de visualizatzione de is immà gines", + "lightbox.expand": "Ismà nnia sa casella de visualizatzione de is immà gines", "lightbox.next": "Sighi", "lightbox.previous": "Pretzedente", - "lightbox.view_context": "Bide su cuntestu", - "lists.account.add": "Agiùnghe a sa lista", + "lists.account.add": "Agiunghe a sa lista", "lists.account.remove": "Boga dae sa lista", "lists.delete": "Cantzella sa lista", "lists.edit": "Modìfica sa lista", "lists.edit.submit": "Muda su tìtulu", "lists.new.create": "Agiunghe lista", - "lists.new.title_placeholder": "Lista noa", - "lists.search": "Chircare intre sa gente chi ses sighende", + "lists.new.title_placeholder": "Tìtulu de sa lista noa", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Ammustra is rispostas a:", + "lists.search": "Chirca intre sa gente chi ses sighende", "lists.subheading": "Is listas tuas", "load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}", "loading_indicator.label": "Carrighende...", - "media_gallery.toggle_visible": "Cua mèdia", + "media_gallery.toggle_visible": "Cua {number, plural, one {immà gine} other {immà gines}}", "missing_indicator.label": "Perunu resurtadu", "missing_indicator.sublabel": "Resursa no agatada", + "mute_modal.duration": "Durada", "mute_modal.hide_notifications": "Boles cuare is notìficas de custa persone?", + "mute_modal.indefinite": "Indefinida", "navigation_bar.apps": "Aplicatziones mòbiles", "navigation_bar.blocks": "Persones blocadas", - "navigation_bar.bookmarks": "Marcadores", + "navigation_bar.bookmarks": "Sinnalibros", "navigation_bar.community_timeline": "Lìnia de tempus locale", "navigation_bar.compose": "Cumpone unu tut nou", "navigation_bar.direct": "Messà gios diretos", @@ -278,7 +290,7 @@ "navigation_bar.domain_blocks": "Domìnios blocados", "navigation_bar.edit_profile": "Modìfica profilu", "navigation_bar.favourites": "Preferidos", - "navigation_bar.filters": "Parà ulas a sa muda", + "navigation_bar.filters": "Faeddos a sa muda", "navigation_bar.follow_requests": "Rechestas de sighidura", "navigation_bar.follows_and_followers": "Persones chi sighis e chi ti sighint", "navigation_bar.info": "Informatziones de su serbidore", @@ -297,7 +309,8 @@ "notification.mention": "{name} t'at mentovadu", "notification.own_poll": "Sondà giu acabbadu", "notification.poll": "Unu sondà giu in su chi as votadu est acabbadu", - "notification.reblog": "{name} at cumpartzidu s'istadu tuo", + "notification.reblog": "{name} at cumpartzidu su tut tuo", + "notification.status": "{name} at publicadu cosa", "notifications.clear": "Lìmpia notìficas", "notifications.clear_confirmation": "Seguru chi boles isboidare in manera permanente totu is notìficas tuas?", "notifications.column_settings.alert": "Notìficas de iscrivania", @@ -305,25 +318,36 @@ "notifications.column_settings.filter_bar.advanced": "Ammustra totu is categorias", "notifications.column_settings.filter_bar.category": "Barra lestra de filtros", "notifications.column_settings.filter_bar.show": "Ammustra", - "notifications.column_settings.follow": "Gente noa chi ti sighit:", - "notifications.column_settings.follow_request": "Rechesta de sighidura noa:", + "notifications.column_settings.follow": "Sighiduras noas:", + "notifications.column_settings.follow_request": "Rechestas noas de sighidura:", "notifications.column_settings.mention": "Mentovos:", "notifications.column_settings.poll": "Resurtados de su sondà giu:", "notifications.column_settings.push": "Notìficas push", "notifications.column_settings.reblog": "Cumpartziduras:", "notifications.column_settings.show": "Ammustra in sa colunna", "notifications.column_settings.sound": "Reprodue unu sonu", + "notifications.column_settings.status": "Tuts noos:", "notifications.filter.all": "Totus", "notifications.filter.boosts": "Cumpartziduras", "notifications.filter.favourites": "Preferidos", "notifications.filter.follows": "Sighende", "notifications.filter.mentions": "Mentovos", - "notifications.filter.polls": "Resurtados dae su sondà giu", + "notifications.filter.polls": "Resurtados de su sondà giu", + "notifications.filter.statuses": "Atualizatziones dae gente chi sighis", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notìficas", + "notifications.mark_as_read": "Sinnala ònnia notìfica comente lèghida", + "notifications.permission_denied": "Is notìficas de iscrivania non sunt a disponimentu pro neghe de rechestas de permissu chi sunt istadas dennegadas in antis", + "notifications.permission_denied_alert": "Is notìficas de iscrivania non podent èssere abilitadas, ca su permissu de su navigadore est istadu dennegadu in antis", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Abilita is notìficas de iscrivania", + "notifications_permission_banner.how_to_control": "Pro retzire notìficas cando Mastodon no est abertu, abilita is notìficas de iscrivania. Podes controllare cun pretzisione is castas de interatziones chi ingendrant notìficas de iscrivania pro mèdiu de su butone {icon} in subra, cando sunt abilitadas.", + "notifications_permission_banner.title": "Non ti perdas mai nudda", + "picture_in_picture.restore": "Torra·ddu a ue fiat", "poll.closed": "Serradu", "poll.refresh": "Atualiza", - "poll.total_people": "{count, plurale, one {# persone} other {# persones}}", - "poll.total_votes": "{count, plurale, one {# votu} other {# votos}}", + "poll.total_people": "{count, plural, one {# persone} other {# persones}}", + "poll.total_votes": "{count, plural, one {# votu} other {# votos}}", "poll.vote": "Vota", "poll.voted": "As votadu custa risposta", "poll_button.add_poll": "Agiunghe unu sondà giu", @@ -341,14 +365,14 @@ "regeneration_indicator.label": "Carrighende…", "regeneration_indicator.sublabel": "Preparende sa lìnia de tempus printzipale tua.", "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", + "relative_time.hours": "{number}o", "relative_time.just_now": "immoe", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "oe", "reply_indicator.cancel": "Annulla", "report.forward": "Torra a imbiare a {target}", - "report.forward_hint": "Custu contu est de un'à teru serbidore. Bi boles imbiare puru una còpia anònima de custu informe?", + "report.forward_hint": "Custu contu est de un'à teru serbidore. Ddi boles imbiare puru una còpia anònima de custu informe?", "report.hint": "S'informe at a èssere imbiadu a sa moderatzione de su serbidore. Podes frunire un'ispiegatzione de sa signalatzione tua de custu contu:", "report.placeholder": "Cummentos additzionales", "report.submit": "Imbia", @@ -357,21 +381,21 @@ "search_popout.search_format": "Formadu de chirca avantzada", "search_popout.tips.full_text": "Testu sèmplitze pro agatare istados chi as iscritu, marcadu comente a preferidos, cumpartzidu o chi t'ant mentovadu, e fintzas nòmines de utente, nòmines visualizados e etichetas chi ddu includent.", "search_popout.tips.hashtag": "eticheta", - "search_popout.tips.status": "istadu", + "search_popout.tips.status": "tut", "search_popout.tips.text": "Testu sèmplitze pro agatare nòmines visualizados, nòmines de utente e etichetas", "search_popout.tips.user": "utente", "search_results.accounts": "Gente", "search_results.hashtags": "Etichetas", "search_results.statuses": "Tuts", "search_results.statuses_fts_disabled": "Sa chirca de tuts pro su cuntenutu issoro no est abilitada in custu serbidore de Mastodon.", - "search_results.total": "{count, number} {count, plurale, one {resurtadu} other {resurtados}}", + "search_results.total": "{count, number} {count, plural, one {resurtadu} other {resurtados}}", "status.admin_account": "Aberi s'interfache de moderatzione pro @{name}", "status.admin_status": "Aberi custu istadu in s'interfache de moderatzione", "status.block": "Bloca @{name}", - "status.bookmark": "Marcadore", + "status.bookmark": "Sinnalibru", "status.cancel_reblog_private": "Iscontza sa cumpartzidura", "status.cannot_reblog": "Custa publicatzione non podet èssere cumpartzida", - "status.copy": "Còpia su ligà mene a s'istadu tuo", + "status.copy": "Còpia su ligòngiu a su tut tuo", "status.delete": "Cantzella", "status.detailed_status": "Visualizatzione de detà lliu de arresonada", "status.direct": "Messà giu deretu a @{name}", @@ -379,24 +403,24 @@ "status.favourite": "Preferidos", "status.filtered": "Filtradu", "status.load_more": "Cà rriga·nde à teros", - "status.media_hidden": "Mèdias cuados", + "status.media_hidden": "Elementos multimediales cuados", "status.mention": "Mentova @{name}", "status.more": "Àteru", - "status.mute": "Pone @name a sa muda", + "status.mute": "Pone @{name} a sa muda", "status.mute_conversation": "Pone s'arresonada a sa muda", - "status.open": "Ismà nnia custu istadu", + "status.open": "Ismà nnia custu tut", "status.pin": "Apica in su profilu", "status.pinned": "Tut apicadu", - "status.read_more": "Lèghe·nde à teru", + "status.read_more": "Leghe·nde à teru", "status.reblog": "Cumpartzi", "status.reblog_private": "Cumpartzi cun is utentes originales", "status.reblogged_by": "{name} at cumpartzidu", - "status.reblogs.empty": "No one has boosted this toot yet. Cando calicunu dd'at a fà ghere, at a èssere ammustradu inoghe.", + "status.reblogs.empty": "Nemos at ancora cumpartzidu custu tut. Cando calicunu dd'at a fà ghere, at a èssere ammustradu inoghe.", "status.redraft": "Cantzella e torra a iscrìere", - "status.remove_bookmark": "Boga su marcadore", + "status.remove_bookmark": "Boga su sinnalibru", "status.reply": "Risponde", "status.replyAll": "Risponde a su tema", - "status.report": "Signala @{name}", + "status.report": "Sinnala @{name}", "status.sensitive_warning": "Cuntenutu sensìbile", "status.share": "Cumpartzi", "status.show_less": "Ammustra·nde prus pagu", @@ -406,7 +430,7 @@ "status.show_thread": "Ammustra su tema", "status.uncached_media_warning": "No est a disponimentu", "status.unmute_conversation": "Torra a ativare s'arresonada", - "status.unpin": "Isbloca dae pitzu de su profilu", + "status.unpin": "Boga dae pitzu de su profilu", "suggestions.dismiss": "Iscarta cussìgiu", "suggestions.header": "Est possìbile chi tèngias interessu in…", "tabs_bar.federated_timeline": "Federada", @@ -419,33 +443,34 @@ "time_remaining.minutes": "{number, plural, one {abarrat # minutu} other {abarrant # minutos}}", "time_remaining.moments": "Abarrant pagu momentos", "time_remaining.seconds": "{number, plural, one {abarrat # segundu} other {abarrant # segundos}}", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "{resource} dae à teros serbidores non benint ammustrados.", + "timeline_hint.resources.followers": "Sighiduras", + "timeline_hint.resources.follows": "Sighende", + "timeline_hint.resources.statuses": "Tuts prus betzos", + "trends.counter_by_accounts": "{count, plural, one {{counter} persone} other {{counter} persones}} chistionende", "trends.trending_now": "Est tendèntzia immoe", "ui.beforeunload": "S'abbotzu tuo at a èssere pèrdidu si essis dae Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count}Mrd", + "units.short.million": "{count}Mln", + "units.short.thousand": "{count}m", "upload_area.title": "Traga pro carrigare", - "upload_button.label": "Agiunghe mèdias ({formats})", + "upload_button.label": "Agiunghe immà gines, unu vìdeu o unu documentu sonoru", "upload_error.limit": "Lìmite de cà rriga de archìvios barigadu.", "upload_error.poll": "Non si permitit s'imbiu de archìvios in is sondà gios.", "upload_form.audio_description": "Descritzione pro persones cun pèrdida auditiva", "upload_form.description": "Descritzione pro persones cun problemas visuales", "upload_form.edit": "Modìfica", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Cà mbia sa miniadura", "upload_form.undo": "Cantzella", "upload_form.video_description": "Descritzione pro persones cun pèrdida auditiva o problemas visuales", "upload_modal.analyzing_picture": "Analizende immà gine…", "upload_modal.apply": "Àplica", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Sèbera un'immà gine", "upload_modal.description_placeholder": "Su margiane castà ngiu brincat lestru a subra de su cane mandrone", "upload_modal.detect_text": "Rileva testu de s'immà gine", - "upload_modal.edit_media": "Modìfica su mèdia", - "upload_modal.hint": "Incarca o traga su tzìrculu in sa previsualizatzione pro seberare su puntu focale chi at a èssere semper visìbile in totu is miniaturas.", + "upload_modal.edit_media": "Modìfica elementu multimediale", + "upload_modal.hint": "Incarca o traga su tzìrculu in sa previsualizatzione pro seberare su puntu focale chi at a èssere semper visìbile in totu is miniaduras.", + "upload_modal.preparing_ocr": "Ammaniende s'OCR…", "upload_modal.preview_label": "Previsualiza ({ratio})", "upload_progress.label": "Carrighende...", "video.close": "Serra su vìdeu", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 4e48d53c84fe2a4df83203b83bfbcd53f51786c1..6640d54729a0726e4b45b0e78b24b10cc4c187bc 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "ZruÅ¡ žiadosÅ¥ o sledovanie", "account.direct": "Priama správa pre @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Doména ukrytá", "account.edit_profile": "Uprav profil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Zobrazuj na profile", "account.follow": "Nasleduj", "account.followers": "Sledujúci", @@ -43,7 +45,7 @@ "account.unfollow": "Prestaň následovaÅ¥", "account.unmute": "Prestaň ignorovaÅ¥ @{name}", "account.unmute_notifications": "ZruÅ¡ stĺmenie oboznámenà od @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Klikni pre vloženie poznámky", "alert.rate_limited.message": "ProsÃm, skús to znova za {retry_time, time, medium}.", "alert.rate_limited.title": "Tempo obmedzené", "alert.unexpected.message": "Vyskytla sa neÄakaná chyba.", @@ -79,7 +81,7 @@ "column_header.show_settings": "Ukáž nastavenia", "column_header.unpin": "Odopni", "column_subheading.settings": "Nastavenia", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "Iba miestna", "community.column_settings.media_only": "Iba médiá", "community.column_settings.remote_only": "Remote only", "compose_form.direct_message_warning": "Tento prÃspevok bude boslaný iba spomenutým užÃvateľom.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Nájdené", "emoji_button.symbols": "Symboly", "emoji_button.travel": "Cestovanie a miesta", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Niesú tu žiadne prÃspevky!", "empty_column.account_unavailable": "Profil nedostupný", "empty_column.blocks": "EÅ¡te si nikoho nezablokoval/a.", @@ -166,13 +169,15 @@ "empty_column.notifications": "EÅ¡te nemáš žiadne oznámenia. ZaÄni komunikovaÅ¥ s ostatnými, aby diskusia mohla zaÄaÅ¥.", "empty_column.public": "EÅ¡te tu niÄ nie je. NapÃÅ¡ nieÄo verejne, alebo zaÄni sledovaÅ¥ užÃvateľov z iných serverov, aby tu nieÄo pribudlo", "error.unexpected_crash.explanation": "Kvôli chybe v naÅ¡om kóde, alebo problému s kompatibilitou prehliadaÄa, túto stránku nebolo možné zobraziÅ¥ správne.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Skús obnoviÅ¥ stránku. Ak to nepomôže, pravdepodobne budeÅ¡ stále môcÅ¥ použÃvaÅ¥ Mastodon cez iný prehliadaÄ, alebo natÃvnu aplikáciu.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "SkopÃruj stacktrace do schránky", "errors.unexpected_crash.report_issue": "Nahlás problém", "follow_request.authorize": "Povoľ prÃstup", "follow_request.reject": "Odmietni", "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", + "generic.saved": "Uložené", "getting_started.developers": "Vývojári", "getting_started.directory": "Zoznam profilov", "getting_started.documentation": "Dokumentácia", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "nesústreÄ sa na pÃsaciu plochu, alebo hľadanie", "keyboard_shortcuts.up": "posuň sa vyššie v zozname", "lightbox.close": "Zatvor", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "ÄŽalÅ¡ie", "lightbox.previous": "Predchádzajúci", - "lightbox.view_context": "Ukáž kontext", "lists.account.add": "Pridaj do zoznamu", "lists.account.remove": "Odober zo zoznamu", "lists.delete": "Vymaž list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Zmeň názov", "lists.new.create": "Pridaj zoznam", "lists.new.title_placeholder": "Názov nového zoznamu", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Vyhľadávaj medzi užÃvateľmi, ktorých sledujeÅ¡", "lists.subheading": "Tvoje zoznamy", "load_pending": "{count, plural, one {# nová položka} other {# nových položiek}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Zapni/Vypni viditeľnosÅ¥", "missing_indicator.label": "Nenájdené", "missing_indicator.sublabel": "Tento zdroj sa eÅ¡te nepodarilo nájsÅ¥", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Skry oznámenia od tohto použÃvateľa?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Aplikácie", "navigation_bar.blocks": "Blokovanà užÃvatelia", "navigation_bar.bookmarks": "Záložky", @@ -298,6 +310,7 @@ "notification.own_poll": "Tvoja anketa sa skonÄila", "notification.poll": "Anketa v ktorej si hlasoval/a sa skonÄila", "notification.reblog": "{name} zdieľal/a tvoj prÃspevok", + "notification.status": "{name} just posted", "notifications.clear": "VyÄisti oboznámenia", "notifications.clear_confirmation": "Naozaj chceÅ¡ nenávratne preÄistiÅ¥ vÅ¡etky tvoje oboznámenia?", "notifications.column_settings.alert": "Oboznámenia na ploche", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Vyzdvihnutia:", "notifications.column_settings.show": "Ukáž v stĺpci", "notifications.column_settings.sound": "Prehraj zvuk", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "VÅ¡etky", "notifications.filter.boosts": "Vyzdvihnutia", "notifications.filter.favourites": "Obľúbené", "notifications.filter.follows": "Sledovania", "notifications.filter.mentions": "Iba spomenutia", "notifications.filter.polls": "Výsledky ankiet", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} oboznámenÃ", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Uzatvorená", "poll.refresh": "ObÄerstvi", "poll.total_people": "{count, plural, one {# Älovek} few {# ľudia} other {# ľudÃ}}", @@ -420,9 +444,9 @@ "time_remaining.moments": "Ostáva už iba chviľka", "time_remaining.seconds": "Ostáva {number, plural, one {# sekunda} few {# sekúnd} many {# sekúnd} other {# sekúnd}}", "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", + "timeline_hint.resources.followers": "Sledujúci", + "timeline_hint.resources.follows": "Následuje", + "timeline_hint.resources.statuses": "StarÅ¡ie prÃspevky", "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", "trends.trending_now": "Teraz populárne", "ui.beforeunload": "ÄŒo máš rozpÃsané sa stratÃ, ak opustÃÅ¡ Mastodon.", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Rozpoznaj text z obrázka", "upload_modal.edit_media": "Uprav médiá", "upload_modal.hint": "Klikni, alebo potiahni okruh ukážky pre zvolenie z ktorého východzieho bodu bude vždy v dohľadne na vÅ¡etkých náhľadoch.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Náhľad ({ratio})", "upload_progress.label": "Nahráva sa...", "video.close": "Zavri video", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 71ba0d1b622972753716a533949aa32f9b4cf675..ca29c4455f90a2ed6318cdfe753a67e881d376ed 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Neposredno sporoÄilo @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Skrita domena", "account.edit_profile": "Uredi profil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Zmožnost profila", "account.follow": "Sledi", "account.followers": "Sledilci", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Rezultati iskanja", "emoji_button.symbols": "Simboli", "emoji_button.travel": "Potovanja in Kraji", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Tukaj ni tutov!", "empty_column.account_unavailable": "Profil ni na voljo", "empty_column.blocks": "Niste Å¡e blokirali nobenega uporabnika.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Nimate Å¡e nobenih obvestil. Povežite se z drugimi, da zaÄnete pogovor.", "empty_column.public": "Tukaj ni niÄesar! Da ga napolnite, napiÅ¡ite nekaj javnega ali pa roÄno sledite uporabnikom iz drugih strežnikov", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Overi", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "odfokusiraj obmoÄje za sestavljanje besedila/iskanje", "keyboard_shortcuts.up": "premakni se navzgor po seznamu", "lightbox.close": "Zapri", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Naslednji", "lightbox.previous": "PrejÅ¡nji", - "lightbox.view_context": "Poglej kontekst", "lists.account.add": "Dodaj na seznam", "lists.account.remove": "Odstrani s seznama", "lists.delete": "IzbriÅ¡i seznam", @@ -260,6 +266,10 @@ "lists.edit.submit": "Spremeni naslov", "lists.new.create": "Dodaj seznam", "lists.new.title_placeholder": "Nov naslov seznama", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "IÅ¡Äi med ljudmi, katerim sledite", "lists.subheading": "VaÅ¡i seznami", "load_pending": "{count, plural, one {# nov element} other {# novih elementov}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Preklopi vidljivost", "missing_indicator.label": "Ni najdeno", "missing_indicator.sublabel": "Tega vira ni bilo mogoÄe najti", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Skrij obvestila tega uporabnika?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobilne aplikacije", "navigation_bar.blocks": "Blokirani uporabniki", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "Glasovanje, v katerem ste sodelovali, se je konÄalo", "notification.reblog": "{name} je spodbudil/a vaÅ¡ status", + "notification.status": "{name} just posted", "notifications.clear": "PoÄisti obvestila", "notifications.clear_confirmation": "Ali ste prepriÄani, da želite trajno izbrisati vsa vaÅ¡a obvestila?", "notifications.column_settings.alert": "Namizna obvestila", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Spodbude:", "notifications.column_settings.show": "Prikaži v stolpcu", "notifications.column_settings.sound": "Predvajaj zvok", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Vse", "notifications.filter.boosts": "Spodbude", "notifications.filter.favourites": "Priljubljeni", "notifications.filter.follows": "Sledi", "notifications.filter.mentions": "Omembe", "notifications.filter.polls": "Rezultati glasovanj", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} obvestil", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Zaprto", "poll.refresh": "Osveži", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -430,7 +454,7 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Za poÅ¡iljanje povlecite in spustite", - "upload_button.label": "Dodaj medije ({formats})", + "upload_button.label": "Dodaj medije", "upload_error.limit": "Omejitev prenosa datoteke je presežena.", "upload_error.poll": "Prenos datoteke z anketami ni dovoljen.", "upload_form.audio_description": "Describe for people with hearing loss", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "PoÅ¡iljanje...", "video.close": "Zapri video", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 95cadfe25bc47a51094020ca75cfcd512d0fd76d..b45f62cd5e5d8110d801f95278ecb204b5a265f3 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "Shfletoni më tepër rreth profilit origjinal", "account.cancel_follow_request": "Anulo kërkesën e ndjekjes", "account.direct": "Mesazh i drejtpërdrejtë për @{name}", + "account.disable_notifications": "Resht së njoftuari mua, kur poston @{name}", "account.domain_blocked": "Përkatësia u bllokua", "account.edit_profile": "Përpunoni profilin", + "account.enable_notifications": "Njoftomë, kur poston @{name}", "account.endorse": "Pasqyrojeni në profil", "account.follow": "Ndiqeni", "account.followers": "Ndjekës", "account.followers.empty": "Këtë përdorues ende s’e ndjek njeri.", "account.followers_counter": "{count, plural, one {{counter} Ndjekës} other {{counter} Ndjekës}}", - "account.following_counter": "{count, plural, one {} other {{counter} të Ndjekur}}", + "account.following_counter": "{count, plural, other {{counter} të Ndjekur}}", "account.follows.empty": "Ky përdorues ende s’ndjek njeri.", "account.follows_you": "Ju ndjek", "account.hide_reblogs": "Fshih përforcime nga @{name}", @@ -48,7 +50,7 @@ "alert.rate_limited.title": "Shpejtësi e kufizuar", "alert.unexpected.message": "Ndodhi një gabim të papritur.", "alert.unexpected.title": "Hëm!", - "announcement.announcement": "Njoftime", + "announcement.announcement": "Njoftim", "autosuggest_hashtag.per_week": "{count} për javë", "boost_modal.combo": "Mund të shtypni {combo}, që kjo të anashkalohet herës tjetër", "bundle_column_error.body": "Diç shkoi ters teksa ngarkohej ky përbërës.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Përfundime kërkimi", "emoji_button.symbols": "Simbole", "emoji_button.travel": "Udhëtime & Vende", + "empty_column.account_suspended": "Llogaria u pezullua", "empty_column.account_timeline": "S’ka mesazhe këtu!", "empty_column.account_unavailable": "Profil jashtë funksionimi", "empty_column.blocks": "S’keni bllokuar ende ndonjë përdorues.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Ende s’keni ndonjë njoftim. Ndërveproni me të tjerët që të nisë biseda.", "empty_column.public": "S’ka gjë këtu! Shkruani diçka publikisht, ose ndiqni dorazi përdorues prej instancash të tjera, që ta mbushni këtë zonë", "error.unexpected_crash.explanation": "Për shkak të një të mete në kodin tonë ose të një problemi përputhshmërie të shfletuesit, kjo faqe s’mund të shfaqet saktë.", + "error.unexpected_crash.explanation_addons": "Kjo faqe s’u shfaq dot saktë. Ky gabim ka gjasa të jetë shkaktuar nga një shtesë shfletuesi ose një mjet përkthimi të automatizuar.", "error.unexpected_crash.next_steps": "Provoni të freskoni faqen. Nëse kjo s’bën punë, mundeni ende të jeni në gjendje të përdorni Mastodon-in që nga një shfletues tjetër ose nga ndonjë aplikacion origjinal prej projektit.", + "error.unexpected_crash.next_steps_addons": "Provoni t’i çaktivizoni dhe të rifreskoni faqen. Nëse kjo s’bën punë, mundeni prapë të jeni në gjendje të përdorni Mastodon-in përmes një shfletuesi tjetër, apo një aplikacioni prej Mastodon-it.", "errors.unexpected_crash.copy_stacktrace": "Kopjo stacktrace-in në të papastër", "errors.unexpected_crash.report_issue": "Raportoni problemin", "follow_request.authorize": "Autorizoje", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "për heqjen e fokusit nga fusha e hartimit të mesazheve apo kërkimeve", "keyboard_shortcuts.up": "për ngjitje sipër nëpër listë", "lightbox.close": "Mbylle", + "lightbox.compress": "Ngjeshe kuadratin e parjes së figurave", + "lightbox.expand": "Zgjeroje kuadratin e parjes së figurave", "lightbox.next": "Pasuesja", "lightbox.previous": "E mëparshmja", - "lightbox.view_context": "Shihni kontekstin", "lists.account.add": "Shto në listë", "lists.account.remove": "Hiqe nga lista", "lists.delete": "Fshije listën", @@ -260,6 +266,10 @@ "lists.edit.submit": "Ndryshoni titullin", "lists.new.create": "Shtoni listë", "lists.new.title_placeholder": "Titull liste të re", + "lists.replies_policy.followed": "Cilido përdorues i ndjekur", + "lists.replies_policy.list": "Anëtarë të listës", + "lists.replies_policy.none": "Askush", + "lists.replies_policy.title": "Shfaq përgjigje për:", "lists.search": "Kërkoni mes personash që ndiqni", "lists.subheading": "Listat tuaja", "load_pending": "{count, plural,one {# objekt i ri }other {# objekte të rinj }}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Fshihni {number, plural, one {figurë} other {figura}}", "missing_indicator.label": "S’u gjet", "missing_indicator.sublabel": "Ky burim s’u gjet dot", + "mute_modal.duration": "Kohëzgjatje", "mute_modal.hide_notifications": "Të kalohen të fshehura njoftimet prej këtij përdoruesi?", + "mute_modal.indefinite": "E pacaktuar", "navigation_bar.apps": "Aplikacione për celular", "navigation_bar.blocks": "Përdorues të bllokuar", "navigation_bar.bookmarks": "Faqerojtës", @@ -298,6 +310,7 @@ "notification.own_poll": "Pyetësori juaj ka përfunduar", "notification.poll": "Ka përfunduar një pyetësor ku keni votuar", "notification.reblog": "{name} përforcoi mesazhin tuaj", + "notification.status": "{name} sapo postoi", "notifications.clear": "Spastroji njoftimet", "notifications.clear_confirmation": "Jeni i sigurt se doni të spastrohen përgjithmonë krejt njoftimet tuaja?", "notifications.column_settings.alert": "Njoftime desktopi", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Përforcime:", "notifications.column_settings.show": "Shfaq në shtylla", "notifications.column_settings.sound": "Luaj një tingull", + "notifications.column_settings.status": "Mesazhe të rinj:", "notifications.filter.all": "Krejt", "notifications.filter.boosts": "Përforcime", "notifications.filter.favourites": "Të parapëlqyer", "notifications.filter.follows": "Ndjekje", "notifications.filter.mentions": "Përmendje", "notifications.filter.polls": "Përfundime pyetësori", + "notifications.filter.statuses": "Përditësime prej personash që ndiqni", + "notifications.grant_permission": "Akordoji leje.", "notifications.group": "{count}s njoftime", + "notifications.mark_as_read": "Vëri shenjë çdo njoftimi si të lexuar", + "notifications.permission_denied": "S’mund të aktivizohen njoftime në desktop, ngaqë janë mohuar lejet për këtë.", + "notifications.permission_denied_alert": "S’mund të aktivizohen njoftimet në desktop, ngaqë lejet e shfletuesit për këtë janë mohuar më herët", + "notifications.permission_required": "S’merren dot njoftime desktop, ngaqë s’është akorduar leja përkatëse.", + "notifications_permission_banner.enable": "Aktivizo njoftime në desktop", + "notifications_permission_banner.how_to_control": "Për të marrë njoftime, kur Mastodon-i s’është i hapur, aktivizoni njoftime në desktop. Përmes butoni {icon} më sipër, mund të kontrolloni me përpikëri cilat lloje ndërveprimesh prodhojnë njoftime në dekstop, pasi të jenë aktivizuar.", + "notifications_permission_banner.title": "Mos t’ju shpëtojë gjë", + "picture_in_picture.restore": "Ktheje ku qe", "poll.closed": "I mbyllur", "poll.refresh": "Rifreskoje", "poll.total_people": "{count, plural,one {# person }other {# vetë }}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Pikase tekstin prej fotoje", "upload_modal.edit_media": "Përpunoni media", "upload_modal.hint": "Që të zgjidhni pikën vatrore e cila do të jetë përherë e dukshme në krejt miniaturat, klikojeni ose tërhiqeni rrethin te paraparja.", + "upload_modal.preparing_ocr": "Po përgatitet OCR-ja…", "upload_modal.preview_label": "Paraparje ({ratio})", "upload_progress.label": "Po ngarkohet…", "video.close": "Mbylle videon", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index d7be7380f5da7ca725c7e9755390f3164f196e88..88c9df59baf1fbcb4560a59862dbf71c89b0eb8e 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct Message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain hidden", "account.edit_profile": "Izmeni profil", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Zaprati", "account.followers": "Pratioca", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tutni", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Ovde upiÅ¡ite upozorenje", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Rezultati pretrage", "emoji_button.symbols": "Simboli", "emoji_button.travel": "Putovanja & mesta", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Trenutno nemate obaveÅ¡tenja. Družite se malo da zapoÄnete razgovore.", "empty_column.public": "Ovde nema niÄega! NapiÅ¡ite neÅ¡to javno, ili naÄ‘ite korisnike sa drugih instanci koje ćete zapratiti da popunite ovu prazninu", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Odobri", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "da ne budete viÅ¡e na pretrazi/pravljenju novog tuta", "keyboard_shortcuts.up": "da se pomerite na gore u listi", "lightbox.close": "Zatvori", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Sledeći", "lightbox.previous": "Prethodni", - "lightbox.view_context": "View context", "lists.account.add": "Dodaj na listu", "lists.account.remove": "Ukloni sa liste", "lists.delete": "ObriÅ¡i listu", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Dodaj listu", "lists.new.title_placeholder": "Naslov nove liste", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Pretraži meÄ‘u ljudima koje pratite", "lists.subheading": "VaÅ¡e liste", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "UkljuÄi/iskljuÄi vidljivost", "missing_indicator.label": "Nije pronaÄ‘eno", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Sakrij obaveÅ¡tenja od ovog korisnika?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blokirani korisnici", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} je podržao(la) VaÅ¡ status", + "notification.status": "{name} just posted", "notifications.clear": "OÄisti obaveÅ¡tenja", "notifications.clear_confirmation": "Da li ste sigurno da trajno želite da oÄistite VaÅ¡a obaveÅ¡tenja?", "notifications.column_settings.alert": "ObaveÅ¡tenja na radnoj povrÅ¡ini", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "PodrÅ¡ki:", "notifications.column_settings.show": "Prikaži u koloni", "notifications.column_settings.sound": "PuÅ¡taj zvuk", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Podrži", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} podržao(la)", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Otpremam...", "video.close": "Zatvori video", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 7c42f0e8a015e1317eaefa1e2a2390534dc37eca..2509c90856bedf1e99604eb9eb2fa90ce9085787 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Поништи захтеве за праћење", "account.direct": "Директна порука @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Домен Ñакривен", "account.edit_profile": "Измени профил", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Приказати на профилу", "account.follow": "Запрати", "account.followers": "Пратиоци", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Резултати претраге", "emoji_button.symbols": "Симболи", "emoji_button.travel": "Путовања и меÑта", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Овде нема труба!", "empty_column.account_unavailable": "Профил недоÑтупан", "empty_column.blocks": "Још увек немате блокираних кориÑника.", @@ -166,7 +169,9 @@ "empty_column.notifications": "Тренутно немате обавештења. Дружите Ñе мало да започнете разговор.", "empty_column.public": "Овде нема ничега! Ðапишите нешто јавно, или нађите кориÑнике Ñа других инÑтанци које ћете запратити да попуните ову празнину", "error.unexpected_crash.explanation": "Због грешке у нашем коду или проблема Ñа компатибилношћу прегледача, ова Ñтраница Ñе није могла правилно приказати.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Покушајте да оÑвежите Ñтраницу. Ðко то не помогне, можда ћете и даље моћи да кориÑтите МаÑтодон путем другог прегледача или матичне апликације.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Копирај \"stacktrace\" у клипборд", "errors.unexpected_crash.report_issue": "Пријави проблем", "follow_request.authorize": "Одобри", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "да одфокуÑирате/не будете више на претрази/прављењу нове трубе", "keyboard_shortcuts.up": "да Ñе померите на горе у лиÑти", "lightbox.close": "Затвори", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Следећи", "lightbox.previous": "Претходни", - "lightbox.view_context": "View context", "lists.account.add": "Додај на лиÑту", "lists.account.remove": "Уклони Ñа лиÑте", "lists.delete": "Обриши лиÑту", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Додај лиÑту", "lists.new.title_placeholder": "ÐаÑлов нове лиÑте", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Претражи међу људима које пратите", "lists.subheading": "Ваше лиÑте", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Укључи/иÑкључи видљивоÑÑ‚", "missing_indicator.label": "Ðије пронађено", "missing_indicator.sublabel": "Овај реÑÑƒÑ€Ñ Ð½Ð¸Ñ˜Ðµ пронађен", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Сакриј обавештења од овог кориÑника?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Мобилне апликације", "navigation_bar.blocks": "Блокирани кориÑници", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} је подржао/ла Ваш ÑтатуÑ", + "notification.status": "{name} just posted", "notifications.clear": "ОчиÑти обавештења", "notifications.clear_confirmation": "Да ли Ñте Ñигурно да трајно желите да очиÑтите Ваша обавештења?", "notifications.column_settings.alert": "Обавештења на радној површини", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Подршки:", "notifications.column_settings.show": "Прикажи у колони", "notifications.column_settings.sound": "Пуштај звук", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} обавештења", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Отпремам...", "video.close": "Затвори видео", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index c9251d73c53c596de47eadc50a974bbf19e4e7ca..a75cca8b5e1e81424019b96f01a5f81cecd68313 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "Anteckning", "account.add_or_remove_from_list": "Lägg till i eller ta bort frÃ¥n listor", "account.badges.bot": "Robot", "account.badges.group": "Grupp", "account.block": "Blockera @{name}", "account.block_domain": "Dölj allt frÃ¥n {domain}", "account.blocked": "Blockerad", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "Läs mer pÃ¥ original profilen", "account.cancel_follow_request": "Avbryt följarförfrÃ¥gan", "account.direct": "Skicka ett direktmeddelande till @{name}", + "account.disable_notifications": "Sluta meddela mig när @{name} tutar", "account.domain_blocked": "Domän dold", "account.edit_profile": "Redigera profil", + "account.enable_notifications": "Meddela mig när @{name} tutar", "account.endorse": "Visa pÃ¥ profil", "account.follow": "Följ", "account.followers": "Följare", "account.followers.empty": "Ingen följer denna användare än.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Följare} other {{counter} Följare}}", + "account.following_counter": "{count, plural, one {{counter} Följer} other {{counter} Följer}}", "account.follows.empty": "Denna användare följer inte nÃ¥gon än.", "account.follows_you": "Följer dig", "account.hide_reblogs": "Dölj knuffar frÃ¥n @{name}", @@ -43,12 +45,12 @@ "account.unfollow": "Sluta följ", "account.unmute": "Sluta tysta @{name}", "account.unmute_notifications": "Ã…teraktivera aviseringar frÃ¥n @{name}", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "Klicka för att lägga till anteckning", "alert.rate_limited.message": "Vänligen försök igen efter {retry_time, time, medium}.", "alert.rate_limited.title": "Mängd begränsad", "alert.unexpected.message": "Ett oväntat fel uppstod.", "alert.unexpected.title": "Hoppsan!", - "announcement.announcement": "Announcement", + "announcement.announcement": "Meddelande", "autosuggest_hashtag.per_week": "{count} per vecka", "boost_modal.combo": "Du kan trycka {combo} för att slippa detta nästa gÃ¥ng", "bundle_column_error.body": "NÃ¥got gick fel medan denna komponent laddades.", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Sökresultat", "emoji_button.symbols": "Symboler", "emoji_button.travel": "Resor & platser", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Inga inlägg här!", "empty_column.account_unavailable": "Profilen ej tillgänglig", "empty_column.blocks": "Du har ännu ej blockerat nÃ¥gra användare.", @@ -166,13 +169,15 @@ "empty_column.notifications": "Du har inga meddelanden än. Interagera med andra för att starta konversationen.", "empty_column.public": "Det finns inget här! Skriv nÃ¥got offentligt, eller följ manuellt användarna frÃ¥n andra instanser för att fylla pÃ¥ det", "error.unexpected_crash.explanation": "PÃ¥ grund av en bugg i vÃ¥r kod eller kompatiblitetsproblem i webbläsaren kan den här sidan inte visas korrekt.", + "error.unexpected_crash.explanation_addons": "Denna sida kunde inte visas korrekt. Detta beror troligen pÃ¥ ett webbläsartillägg eller ett automatiskt översättningsverktyg.", "error.unexpected_crash.next_steps": "Prova att ladda om sidan. Om det inte hjälper kan du försöka använda Mastodon med en annan webbläsare eller app.", + "error.unexpected_crash.next_steps_addons": "Prova att avaktivera dem och uppdatera sidan. Om detta inte hjälper kan du försöka använda Mastodon med en annan webbläsare eller en app.", "errors.unexpected_crash.copy_stacktrace": "Kopiera stacktrace till urklipp", "errors.unexpected_crash.report_issue": "Rapportera problem", "follow_request.authorize": "Godkänn", "follow_request.reject": "Avvisa", "follow_requests.unlocked_explanation": "Även om ditt konto inte är lÃ¥st tror {domain} personalen att du kanske vill granska dessa följares förfrÃ¥gningar manuellt.", - "generic.saved": "Saved", + "generic.saved": "Sparad", "getting_started.developers": "Utvecklare", "getting_started.directory": "Profilkatalog", "getting_started.documentation": "Dokumentation", @@ -236,13 +241,13 @@ "keyboard_shortcuts.muted": "för att öppna listan över tystade användare", "keyboard_shortcuts.my_profile": "för att öppna din profil", "keyboard_shortcuts.notifications": "för att öppna Meddelanden", - "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.open_media": "öppna media", "keyboard_shortcuts.pinned": "för att öppna NÃ¥lade toots", "keyboard_shortcuts.profile": "för att öppna skaparens profil", "keyboard_shortcuts.reply": "för att svara", "keyboard_shortcuts.requests": "för att öppna FöljförfrÃ¥gningar", "keyboard_shortcuts.search": "för att fokusera sökfältet", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "visa/dölja CW-fält", "keyboard_shortcuts.start": "för att öppna \"Kom igÃ¥ng\"-kolumnen", "keyboard_shortcuts.toggle_hidden": "för att visa/gömma text bakom CW", "keyboard_shortcuts.toggle_sensitivity": "för att visa/gömma media", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "för att avfokusera skrivfält/sökfält", "keyboard_shortcuts.up": "för att flytta uppÃ¥t i listan", "lightbox.close": "Stäng", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Nästa", "lightbox.previous": "Tidigare", - "lightbox.view_context": "Visa kontext", "lists.account.add": "Lägg till i lista", "lists.account.remove": "Ta bort frÃ¥n lista", "lists.delete": "Radera lista", @@ -260,6 +266,10 @@ "lists.edit.submit": "Ändra titel", "lists.new.create": "Lägg till lista", "lists.new.title_placeholder": "Ny listrubrik", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Sök bland personer du följer", "lists.subheading": "Dina listor", "load_pending": "{count, plural, other {# objekt}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Växla synlighet", "missing_indicator.label": "Hittades inte", "missing_indicator.sublabel": "Den här resursen kunde inte hittas", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Dölj aviseringar frÃ¥n denna användare?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobilappar", "navigation_bar.blocks": "Blockerade användare", "navigation_bar.bookmarks": "Bokmärken", @@ -298,6 +310,7 @@ "notification.own_poll": "Din röstning har avslutats", "notification.poll": "En omröstning du röstat i har avslutats", "notification.reblog": "{name} knuffade din status", + "notification.status": "{name} just posted", "notifications.clear": "Rensa aviseringar", "notifications.clear_confirmation": "Är du säker pÃ¥ att du vill rensa alla dina aviseringar permanent?", "notifications.column_settings.alert": "Skrivbordsaviseringar", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Knuffar:", "notifications.column_settings.show": "Visa i kolumnen", "notifications.column_settings.sound": "Spela upp ljud", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "Alla", "notifications.filter.boosts": "Knuffar", "notifications.filter.favourites": "Favoriter", "notifications.filter.follows": "Följer", "notifications.filter.mentions": "Omnämningar", "notifications.filter.polls": "Omröstningsresultat", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} aviseringar", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "För att ta emot aviseringar när Mastodon inte är öppet, aktivera skrivbordsaviseringar. När de är aktiverade kan du styra exakt vilka typer av interaktioner som aviseras via {icon} -knappen ovan.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Stängd", "poll.refresh": "Ladda om", "poll.total_people": "{persons, plural, one {# person} other {# personer}}", @@ -419,11 +443,11 @@ "time_remaining.minutes": "{minutes, plural, one {1 minut} other {# minuter}} kvar", "time_remaining.moments": "Ã…terstÃ¥ende tillfällen", "time_remaining.seconds": "{hours, plural, one {# sekund} other {# sekunder}} kvar", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "{resource} frÃ¥n andra servrar visas inte.", + "timeline_hint.resources.followers": "Följare", + "timeline_hint.resources.follows": "Följer", + "timeline_hint.resources.statuses": "Äldre tutningar", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} personer}} pratar", "trends.trending_now": "Trendar nu", "ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.", "units.short.billion": "{count}B", @@ -433,19 +457,20 @@ "upload_button.label": "Lägg till media", "upload_error.limit": "Filöverföringsgränsen överskriden.", "upload_error.poll": "Filuppladdning tillÃ¥ts inte med omröstningar.", - "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.audio_description": "Beskriv för personer med hörselnedsättning", "upload_form.description": "Beskriv för synskadade", "upload_form.edit": "Redigera", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Ändra miniatyr", "upload_form.undo": "Ta bort", - "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_form.video_description": "Beskriv för personer med hörsel- eller synnedsättning", "upload_modal.analyzing_picture": "Analyserar bild…", "upload_modal.apply": "Verkställ", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Välj bild", "upload_modal.description_placeholder": "En snabb brun räv hoppar över den lata hunden", "upload_modal.detect_text": "Upptäck bildens text", "upload_modal.edit_media": "Redigera meida", "upload_modal.hint": "Klicka eller dra cirkeln pÃ¥ förhandstitten för att välja den fokusering som alltid kommer synas pÃ¥ alla miniatyrer.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Förhandstitt ({ratio})", "upload_progress.label": "Laddar upp...", "video.close": "Stäng video", diff --git a/app/javascript/mastodon/locales/szl.json b/app/javascript/mastodon/locales/szl.json index e5d833fe87465898b1831bb4ceb749f69e1f8e65..70f6ab1529e76eb2ac320779468d4f934d169e1a 100644 --- a/app/javascript/mastodon/locales/szl.json +++ b/app/javascript/mastodon/locales/szl.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain blocked", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/ta.json b/app/javascript/mastodon/locales/ta.json index 28f03f7811300b8a29537bb1b51dbb4b46bd37d4..8f5f06cc487223f2663b8240e50030887faa4e66 100644 --- a/app/javascript/mastodon/locales/ta.json +++ b/app/javascript/mastodon/locales/ta.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "கà¯à®±à®¿à®ªà¯à®ªà¯", "account.add_or_remove_from_list": "படà¯à®Ÿà®¿à®¯à®²à¯à®•ளில௠சேரà¯/நீகà¯à®•à¯", "account.badges.bot": "பாடà¯", "account.badges.group": "கà¯à®´à¯", "account.block": "@{name} -à®à®¤à¯ தடà¯", "account.block_domain": "{domain} யில௠இரà¯à®¨à¯à®¤à¯ வரà¯à®®à¯ எலà¯à®²à®¾à®µà®±à¯à®±à¯ˆà®¯à¯à®®à¯ மறை", "account.blocked": "à®®à¯à®Ÿà®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "மேலà¯à®®à¯ உலாவ சà¯à®¯à®µà®¿à®µà®°à®¤à¯à®¤à®¿à®±à¯à®•à¯à®šà¯ செலà¯à®•", "account.cancel_follow_request": "பினà¯à®¤à¯Šà®Ÿà®°à¯à®®à¯ கோரிகà¯à®•ையை நிராகரி", "account.direct": "நேரடி செயà¯à®¤à®¿ @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "மறைகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ தளஙà¯à®•ளà¯", "account.edit_profile": "சà¯à®¯à®µà®¿à®µà®°à®¤à¯à®¤à¯ˆ மாறà¯à®±à¯", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "சà¯à®¯à®µà®¿à®µà®°à®¤à¯à®¤à®¿à®²à¯ வெளிபà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯", "account.follow": "பினà¯à®¤à¯Šà®Ÿà®°à¯", "account.followers": "பினà¯à®¤à¯Šà®Ÿà®°à¯à®ªà®µà®°à¯à®•ளà¯", "account.followers.empty": "இதà¯à®µà®°à¯ˆ யாரà¯à®®à¯ இநà¯à®¤ பயனரைப௠பினà¯à®¤à¯Šà®Ÿà®°à®µà®¿à®²à¯à®²à¯ˆ.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} வாசகரà¯} other {{counter} வாசகரà¯à®•ளà¯}}", + "account.following_counter": "{count, plural,one {{counter} சநà¯à®¤à®¾} other {{counter} சநà¯à®¤à®¾à®•à¯à®•ளà¯}}", "account.follows.empty": "இநà¯à®¤ பயனர௠இதà¯à®µà®°à¯ˆ யாரையà¯à®®à¯ பினà¯à®¤à¯Šà®Ÿà®°à®µà®¿à®²à¯à®²à¯ˆ.", "account.follows_you": "உஙà¯à®•ளைப௠பினà¯à®¤à¯Šà®Ÿà®°à¯à®•ிறாரà¯", "account.hide_reblogs": "இரà¯à®¨à¯à®¤à¯ ஊகà¯à®•ியாக மறை @{name}", @@ -36,14 +38,14 @@ "account.requested": "ஒபà¯à®ªà¯à®¤à®²à¯à®•à¯à®•ாகக௠காதà¯à®¤à®¿à®°à¯à®•à¯à®•ிறதà¯. பினà¯à®¤à¯Šà®Ÿà®°à¯à®®à¯ கோரிகà¯à®•ையை நீகà¯à®• à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯", "account.share": "@{name} உடைய விவரதà¯à®¤à¯ˆ பகிரà¯", "account.show_reblogs": "காடà¯à®Ÿà¯ boosts இரà¯à®¨à¯à®¤à¯ @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} டூடà¯} other {{counter} டூடà¯à®Ÿà¯à®•ளà¯}}", "account.unblock": "@{name} மீத௠தடை நீகà¯à®•à¯à®•", "account.unblock_domain": "{domain} ஠காணà¯à®ªà®¿", "account.unendorse": "சà¯à®¯à®µà®¿à®µà®°à®¤à¯à®¤à®¿à®²à¯ இடமà¯à®ªà¯†à®± வேணà¯à®Ÿà®¾à®®à¯", "account.unfollow": "பினà¯à®¤à¯Šà®Ÿà®°à¯à®µà®¤à¯ˆ நிறà¯à®¤à¯à®¤à¯à®•", "account.unmute": "@{name} இன௠மீத௠மௌனத௠தடையை நீகà¯à®•à¯à®•", "account.unmute_notifications": "@{name} இலிரà¯à®¨à¯à®¤à¯ அறிவிபà¯à®ªà¯à®•ளின௠மீத௠மௌனத௠தடையை நீகà¯à®•à¯à®•", - "account_note.placeholder": "Click to add a note", + "account_note.placeholder": "கà¯à®±à®¿à®ªà¯à®ªà¯ ஒனà¯à®±à¯ˆ சேரà¯à®•à¯à®• சொடà¯à®•à¯à®•வà¯à®®à¯", "alert.rate_limited.message": "{retry_time, time, medium} கà¯à®•௠பிறக௠மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•வà¯à®®à¯.", "alert.rate_limited.title": "பயனà¯à®ªà®¾à®Ÿà¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯", "alert.unexpected.message": "எதிரà¯à®ªà®¾à®°à®¾à®¤ பிழை à®à®±à¯à®ªà®Ÿà¯à®Ÿà¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯.", @@ -79,9 +81,9 @@ "column_header.show_settings": "அமைபà¯à®ªà¯à®•ளைக௠காடà¯à®Ÿà¯", "column_header.unpin": "கழடà¯à®Ÿà¯", "column_subheading.settings": "அமைபà¯à®ªà¯à®•ளà¯", - "community.column_settings.local_only": "Local only", + "community.column_settings.local_only": "à®…à®°à¯à®•ிலிரà¯à®¨à¯à®¤à¯ மடà¯à®Ÿà¯à®®à¯‡", "community.column_settings.media_only": "படஙà¯à®•ள௠மடà¯à®Ÿà¯à®®à¯‡", - "community.column_settings.remote_only": "Remote only", + "community.column_settings.remote_only": "தொலைவிலிரà¯à®¨à¯à®¤à¯ மடà¯à®Ÿà¯à®®à¯‡", "compose_form.direct_message_warning": "இநà¯à®¤ டூட௠இதில௠கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³ பயனரà¯à®•ளà¯à®•à¯à®•௠மடà¯à®Ÿà¯à®®à¯‡ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯.", "compose_form.direct_message_warning_learn_more": "மேலà¯à®®à¯ அறிய", "compose_form.hashtag_warning": "இத௠ஒர௠படà¯à®Ÿà®¿à®¯à®²à®¿à®Ÿà®ªà¯à®ªà®Ÿà®¾à®¤ டூட௠எனà¯à®ªà®¤à®¾à®²à¯ எநà¯à®¤ ஹேஷà¯à®Ÿà¯‡à®•ின௠கீழà¯à®®à¯ வராதà¯. ஹேஷà¯à®Ÿà¯‡à®•ின௠மூலம௠பொதà¯à®µà®¿à®²à¯ உளà¯à®³ டூடà¯à®Ÿà¯à®•ளை மடà¯à®Ÿà¯à®®à¯‡ தேட à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.", @@ -127,7 +129,7 @@ "conversation.mark_as_read": "படிகà¯à®•படà¯à®Ÿà®¤à®¾à®•க௠கà¯à®±à®¿", "conversation.open": "உரையாடலைக௠காடà¯à®Ÿà¯", "conversation.with": "{names} உடனà¯", - "directory.federated": "ஆலமரதà¯à®¤à®¿à®©à¯ அறியபà¯à®ªà®Ÿà¯à®Ÿà®ªà¯ பகà¯à®¤à®¿à®¯à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯", + "directory.federated": "அறியபà¯à®ªà®Ÿà¯à®Ÿ ஃபெடிவெரà¯à®šà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯", "directory.local": "{domain} களதà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ மடà¯à®Ÿà¯à®®à¯", "directory.new_arrivals": "பà¯à®¤à®¿à®¯ வரவà¯", "directory.recently_active": "சறà¯à®±à¯à®®à¯à®©à¯ செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯ இரà¯à®¨à¯à®¤à®µà®°à¯à®•ளà¯", @@ -139,7 +141,7 @@ "emoji_button.food": "உணவ௠மறà¯à®±à¯à®®à¯ பானமà¯", "emoji_button.label": "எமோஜியை உளà¯à®³à®¿à®Ÿà¯", "emoji_button.nature": "இயறà¯à®•ை", - "emoji_button.not_found": "வேணà¯à®Ÿà®¾à®®à¯ எமோஜோஸà¯! (╯°□°)╯︵ â”»â”â”»", + "emoji_button.not_found": "எமோஜிகà¯à®•ள௠இலà¯à®²à¯ˆ! (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "பொரà¯à®Ÿà¯à®•ளà¯", "emoji_button.people": "மகà¯à®•ளà¯", "emoji_button.recent": "அடிகà¯à®•டி பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®ªà®µà¯ˆ", @@ -147,88 +149,91 @@ "emoji_button.search_results": "தேடல௠மà¯à®Ÿà®¿à®µà¯à®•ளà¯", "emoji_button.symbols": "கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®•ளà¯", "emoji_button.travel": "சà¯à®±à¯à®±à¯à®²à®¾ மறà¯à®±à¯à®®à¯ இடஙà¯à®•ளà¯", - "empty_column.account_timeline": "இலà¯à®²à¯ˆ toots இஙà¯à®•ே!", + "empty_column.account_suspended": "Account suspended", + "empty_column.account_timeline": "டூடà¯à®Ÿà¯à®•ள௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ!", "empty_column.account_unavailable": "சà¯à®¯à®µà®¿à®µà®°à®®à¯ கிடைகà¯à®•விலà¯à®²à¯ˆ", - "empty_column.blocks": "இதà¯à®µà®°à¯ˆ எநà¯à®¤ பயனரà¯à®•ளà¯à®®à¯ தடà¯à®•à¯à®•விலà¯à®²à¯ˆ.", + "empty_column.blocks": "நீஙà¯à®•ள௠இதà¯à®µà®°à¯ˆ எநà¯à®¤à®ªà¯ பயனரà¯à®•ளையà¯à®®à¯ à®®à¯à®Ÿà®•à¯à®•ியிரà¯à®•à¯à®•விலà¯à®²à¯ˆ.", "empty_column.bookmarked_statuses": "உஙà¯à®•ளிடம௠அடையாளகà¯à®•à¯à®±à®¿à®¯à®¿à®Ÿà¯à®Ÿ டூடà¯à®Ÿà¯à®•ள௠எவையà¯à®®à¯ இலà¯à®²à¯ˆ. அடையாளகà¯à®•à¯à®±à®¿à®¯à®¿à®Ÿà¯à®Ÿ பிறக௠அவை இஙà¯à®•ே காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®®à¯.", - "empty_column.community": "உளà¯à®³à¯‚ர௠காலகà¯à®•ெட௠காலியாக உளà¯à®³à®¤à¯. பநà¯à®¤à¯ˆ உரà¯à®Ÿà¯à®Ÿà®¿à®•à¯à®•ொளà¯à®µà®¤à®±à¯à®•௠பகிரஙà¯à®•மாக ஒனà¯à®±à¯ˆ எழà¯à®¤à¯à®™à¯à®•ளà¯!", - "empty_column.direct": "உஙà¯à®•ளிடம௠நேரடியான செயà¯à®¤à®¿à®•ள௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ. நீஙà¯à®•ள௠ஒனà¯à®±à¯ˆ அனà¯à®ªà¯à®ªà®¿ அலà¯à®²à®¤à¯ பெறà¯à®®à¯ போதà¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•à¯à®®à¯.", - "empty_column.domain_blocks": "இனà¯à®©à¯à®®à¯ மறைநà¯à®¤ களஙà¯à®•ள௠இலà¯à®²à¯ˆ.", - "empty_column.favourited_statuses": "இதà¯à®µà®°à¯ˆ உஙà¯à®•ளà¯à®•à¯à®•௠பிடிதà¯à®¤ டோடà¯à®Ÿà¯à®•ள௠இலà¯à®²à¯ˆ. உஙà¯à®•ளà¯à®•à¯à®•௠பிடிதà¯à®¤ ஒர௠போதà¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•à¯à®®à¯.", - "empty_column.favourites": "இதà¯à®µà®°à¯ˆ யாரà¯à®®à¯ இநà¯à®¤à®¤à¯ தடà¯à®Ÿà¯à®•à¯à®•௠ஆதரவிலà¯à®²à¯ˆ. யாராவத௠செயà¯à®¤à®¾à®²à¯, அவரà¯à®•ள௠இஙà¯à®•ே காணà¯à®ªà®¾à®°à¯à®•ளà¯.", - "empty_column.follow_requests": "உஙà¯à®•ளà¯à®•à¯à®•௠இனà¯à®©à¯à®®à¯ எநà¯à®¤à®µà¯Šà®°à¯ கோரிகà¯à®•ைகளà¯à®®à¯ இலà¯à®²à¯ˆ. நீஙà¯à®•ள௠ஒனà¯à®±à¯ˆà®ªà¯ பெறà¯à®±à¯à®•à¯à®•ொணà¯à®Ÿà®¾à®²à¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•à¯à®®à¯.", - "empty_column.hashtag": "இனà¯à®©à¯à®®à¯ இநà¯à®¤ ஹேஸà¯à®Ÿà¯‡à®•à¯à®•ில௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ.", - "empty_column.home": "உஙà¯à®•ள௠வீடà¯à®Ÿà¯à®•௠காலம௠காலியாக உளà¯à®³à®¤à¯! வரà¯à®•ை {public} அலà¯à®²à®¤à¯ தொடஙà¯à®•à¯à®µà®¤à®±à¯à®•௠தேடலைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à®¾à®®à¯ மறà¯à®±à¯à®®à¯ பிற பயனரà¯à®•ளை சநà¯à®¤à®¿à®•à¯à®•வà¯à®®à¯.", - "empty_column.home.public_timeline": "பொத௠காலகà¯à®•ெடà¯", - "empty_column.list": "இநà¯à®¤ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ இதà¯à®µà®°à¯ˆ எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ. இநà¯à®¤ படà¯à®Ÿà®¿à®¯à®²à®¿à®©à¯ உறà¯à®ªà¯à®ªà®¿à®©à®°à¯à®•ள௠பà¯à®¤à®¿à®¯ நிலைகளை இடà¯à®•ையிடà¯à®•ையிலà¯, அவை இஙà¯à®•ே தோனà¯à®±à¯à®®à¯.", - "empty_column.lists": "உஙà¯à®•ளà¯à®•à¯à®•௠இதà¯à®µà®°à¯ˆ எநà¯à®¤ படà¯à®Ÿà®¿à®¯à®²à¯à®®à¯ இலà¯à®²à¯ˆ. நீஙà¯à®•ள௠ஒனà¯à®±à¯ˆ உரà¯à®µà®¾à®•à¯à®•ினாலà¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•à¯à®®à¯.", - "empty_column.mutes": "நீஙà¯à®•ள௠இதà¯à®µà®°à¯ˆ எநà¯à®¤ பயனரà¯à®•ளையà¯à®®à¯ à®®à¯à®Ÿà®•à¯à®•ியிரà¯à®•à¯à®•விலà¯à®²à¯ˆ.", - "empty_column.notifications": "உஙà¯à®•ளிடம௠எநà¯à®¤ அறிவிபà¯à®ªà¯à®•ளà¯à®®à¯ இலà¯à®²à¯ˆ. உரையாடலைத௠தொடஙà¯à®• பிறரà¯à®Ÿà®©à¯ தொடரà¯à®ªà¯à®•ொளà¯à®³à®µà¯à®®à¯.", - "empty_column.public": "இஙà¯à®•ே எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ! பகிரஙà¯à®•மாக ஒனà¯à®±à¯ˆ எழà¯à®¤à®µà¯à®®à¯ அலà¯à®²à®¤à¯ மறà¯à®± நிகழà¯à®µà¯à®•ளிலிரà¯à®¨à¯à®¤à¯ பயனரà¯à®•ளை அதை நிரபà¯à®ªà¯à®µà®¤à®±à¯à®•௠கைமà¯à®±à¯ˆà®¯à®¾à®• பினà¯à®ªà®±à¯à®±à®µà¯à®®à¯", - "error.unexpected_crash.explanation": "மெனà¯à®ªà¯Šà®°à¯à®³à¯ பழà¯à®¤à¯à®©à®¾à®²à¯‹ அலà¯à®²à®¤à¯ உஙà¯à®•ள௠இணை உலாவியின௠பொரà¯à®¨à¯à®¤à®¾à®¤à®©à¯à®®à¯ˆà®¯à®¿à®©à®¾à®²à¯‹ இநà¯à®¤à®ªà¯ பகà¯à®•தà¯à®¤à¯ˆ சரியாகக௠காணà¯à®ªà®¿à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ.", - "error.unexpected_crash.next_steps": "பகà¯à®•தà¯à®¤à¯ˆ பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à¯à®ªà¯ பாரà¯à®•à¯à®•வà¯à®®à¯. வேலை செயà¯à®¯à®µà®¿à®²à¯à®²à¯ˆà®¯à¯†à®©à®¿à®²à¯, வேற௠ஒர௠உலாவியில௠இரà¯à®¨à¯à®¤à¯‹ அலà¯à®²à®¤à¯ உஙà¯à®•ள௠கரà¯à®µà®¿à®•à¯à®•௠பொரà¯à®¤à¯à®¤à®®à®¾à®© வேற௠செயலியில௠இரà¯à®¨à¯à®¤à¯‹ மசà¯à®Ÿà¯‹à®Ÿà®©à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯.", - "errors.unexpected_crash.copy_stacktrace": "பழà¯à®šà¯†à®¯à¯à®¤à®¿à®¯à¯ˆ பிடிபà¯à®ªà¯à®ªà¯ பலகைகà¯à®•௠நகல௠எடà¯", + "empty_column.community": "உஙà¯à®•ள௠மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ à®®à¯à®šà¯à®šà®¨à¯à®¤à®¿à®¯à®¿à®²à¯ யாரà¯à®®à¯ இலà¯à®²à¯ˆ. எதையேனà¯à®®à¯ எழà¯à®¤à®¿ ஆடà¯à®Ÿà®¤à¯à®¤à¯ˆà®¤à¯ தà¯à®µà®•à¯à®•à¯à®™à¯à®•ளà¯!", + "empty_column.direct": "உஙà¯à®•ள௠தனிபà¯à®ªà¯†à®Ÿà¯à®Ÿà®¿à®¯à®¿à®²à¯ செயà¯à®¤à®¿à®•ள௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ. செயà¯à®¤à®¿à®¯à¯ˆ நீஙà¯à®•ள௠அனà¯à®ªà¯à®ªà¯à®®à¯à®ªà¯‹à®¤à¯‹ அலà¯à®²à®¤à¯ பெறà¯à®®à¯à®ªà¯‹à®¤à¯‹, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.domain_blocks": "தடà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®•௠களஙà¯à®•ள௠இதà¯à®µà®°à¯ˆ இலà¯à®²à¯ˆ.", + "empty_column.favourited_statuses": "உஙà¯à®•ளà¯à®•à¯à®•à¯à®ªà¯ பிடிதà¯à®¤ டூடà¯à®Ÿà¯à®•ள௠இதà¯à®µà®°à¯ˆ இலà¯à®²à¯ˆ. ஒர௠டூடà¯à®Ÿà®¿à®²à¯ நீஙà¯à®•ள௠விரà¯à®ªà¯à®ªà®•à¯à®•à¯à®±à®¿ இடà¯à®Ÿà®¾à®²à¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.favourites": "இநà¯à®¤ டூடà¯à®Ÿà®¿à®²à¯ இதà¯à®µà®°à¯ˆ யாரà¯à®®à¯ விரà¯à®ªà¯à®ªà®•à¯à®•à¯à®±à®¿ இடவிலà¯à®²à¯ˆ. யாரேனà¯à®®à¯ விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.follow_requests": "வாசகர௠கோரிகà¯à®•ைகள௠இதà¯à®µà®°à¯ˆ à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ. யாரேனà¯à®®à¯ கோரிகà¯à®•ையை அனà¯à®ªà¯à®ªà®¿à®©à®¾à®²à¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.hashtag": "இநà¯à®¤ சிடà¯à®Ÿà¯ˆà®¯à®¿à®²à¯ இதà¯à®µà®°à¯ˆ à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ.", + "empty_column.home": "உஙà¯à®•ள௠மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ வீடà¯à®Ÿà®¿à®²à¯ யாரà¯à®®à¯ இலà¯à®²à¯ˆ. {public} -இல௠செனà¯à®±à¯ பாரà¯à®•à¯à®•வà¯à®®à¯, அலà¯à®²à®¤à¯ தேடல௠கரà¯à®µà®¿à®¯à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®ªà¯ பிற பயனரà¯à®•ளைக௠கணà¯à®Ÿà®Ÿà¯ˆà®¯à®µà¯à®®à¯.", + "empty_column.home.public_timeline": "பொத௠டைமà¯à®²à¯ˆà®©à¯", + "empty_column.list": "இநà¯à®¤à®ªà¯ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ இதà¯à®µà®°à¯ˆ à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ. இபà¯à®ªà®Ÿà¯à®Ÿà®¿à®¯à®²à®¿à®©à¯ உறà¯à®ªà¯à®ªà®¿à®©à®°à¯à®•ள௠பà¯à®¤à®¿à®¯ டூடà¯à®Ÿà¯à®•ளை இடà¯à®Ÿà®¾à®²à¯. அவை இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.lists": "இதà¯à®µà®°à¯ˆ நீஙà¯à®•ள௠எநà¯à®¤à®ªà¯ படà¯à®Ÿà®¿à®¯à®²à¯ˆà®¯à¯à®®à¯ உரà¯à®µà®¾à®•à¯à®•விலà¯à®²à¯ˆ. உரà¯à®µà®¾à®•à¯à®•ினாலà¯, அத௠இஙà¯à®•ே காணà¯à®ªà®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯.", + "empty_column.mutes": "நீஙà¯à®•ள௠இதà¯à®µà®°à¯ˆ எநà¯à®¤à®ªà¯ பயனரà¯à®•ளையà¯à®®à¯ à®®à¯à®Ÿà®•à¯à®•ியிரà¯à®•à¯à®•விலà¯à®²à¯ˆ.", + "empty_column.notifications": "உஙà¯à®•ளà¯à®•à¯à®•ாக எநà¯à®¤ அறிவிபà¯à®ªà¯à®•ளà¯à®®à¯ இலà¯à®²à¯ˆ. உரையாடலைத௠தà¯à®µà®™à¯à®• பிறரைத௠தொடரà¯à®ªà¯à®•ொளà¯à®³à®µà¯à®®à¯.", + "empty_column.public": "இஙà¯à®•௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ! இவà¯à®µà®¿à®Ÿà®¤à¯à®¤à¯ˆ நிரபà¯à®ª எதையேனà¯à®®à¯ எழà¯à®¤à®µà¯à®®à¯, அலà¯à®²à®¤à¯ வேற௠சரà¯à®µà®°à¯à®•ளில௠உளà¯à®³ பயனரà¯à®•ளைப௠பினà¯à®¤à¯Šà®Ÿà®°à®µà¯à®®à¯", + "error.unexpected_crash.explanation": "இநà¯à®¤à®ªà¯ பகà¯à®•தà¯à®¤à¯ˆ சரியாகக௠காணà¯à®ªà®¿à®•à¯à®• இயலவிலà¯à®²à¯ˆ. மெனà¯à®ªà¯Šà®°à¯à®³à®¿à®²à¯ உளà¯à®³ பிழையோ அலà¯à®²à®¤à¯ பொரà¯à®¨à¯à®¤à®¾à®¤ உலாவியோ காரணமாக இரà¯à®•à¯à®•லாமà¯.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", + "error.unexpected_crash.next_steps": "பகà¯à®•தà¯à®¤à¯ˆà®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à¯à®ªà¯ பாரà¯à®•à¯à®•வà¯à®®à¯. அபà¯à®ªà®Ÿà®¿à®¯à¯à®®à¯ வேலை செயà¯à®¯à®µà®¿à®²à¯à®²à¯ˆ எனிலà¯, மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ˆ வேற௠ஒர௠உலாவியின௠மூலமோ, அலà¯à®²à®¤à¯ பொரà¯à®¤à¯à®¤à®®à®¾à®© செயலியின௠மூலமோ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®ªà¯ பாரà¯à®•à¯à®•வà¯à®®à¯.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "Stacktrace-à® clipboard-ல௠நகலெடà¯", "errors.unexpected_crash.report_issue": "பà¯à®•ாரளி", - "follow_request.authorize": "அதிகாரமளி", - "follow_request.reject": "விலகà¯à®•à¯", + "follow_request.authorize": "அனà¯à®®à®¤à®¿à®¯à®³à®¿", + "follow_request.reject": "நிராகரி", "follow_requests.unlocked_explanation": "உஙà¯à®•ள௠கணகà¯à®•௠பூடà¯à®Ÿà®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ எனà¯à®±à®¾à®²à¯à®®à¯, இநà¯à®¤à®•௠கணகà¯à®•à¯à®•ளிலிரà¯à®¨à¯à®¤à¯ உஙà¯à®•ளைப௠பினà¯à®¤à¯Šà®Ÿà®° விரà¯à®®à¯à®ªà¯à®®à¯ கோரிகà¯à®•ைகளை நீஙà¯à®•ள௠பரீசீலிபà¯à®ªà®¤à¯ நலம௠எனà¯à®±à¯ {domain} ஊழியர௠எணà¯à®£à¯à®•ிறாரà¯.", - "generic.saved": "Saved", + "generic.saved": "சேமிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯", "getting_started.developers": "உரà¯à®µà®¾à®•à¯à®•à¯à®¨à®°à¯à®•ளà¯", - "getting_started.directory": "சà¯à®¯à®µà®¿à®µà®° அடைவà¯", + "getting_started.directory": "பயனரà¯à®•ளà¯", "getting_started.documentation": "ஆவணஙà¯à®•ளà¯", - "getting_started.heading": "தொடஙà¯à®•à¯à®¤à®²à¯", - "getting_started.invite": "நபரà¯à®•ளை அழைகà¯à®•வà¯à®®à¯", - "getting_started.open_source_notice": "Mastodon திறநà¯à®¤ மூல மெனà¯à®ªà¯Šà®°à¯à®³à¯. GitHub இல௠நீஙà¯à®•ள௠பஙà¯à®•ளிகà¯à®•வோ அலà¯à®²à®¤à¯ பà¯à®•ார௠அளிகà¯à®•வோ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯ {github}.", - "getting_started.security": "பதà¯à®¤à®¿à®°à®®à¯", + "getting_started.heading": "à®®à¯à®¤à®©à¯à®®à¯ˆà®ªà¯ பகà¯à®•à®®à¯", + "getting_started.invite": "நணà¯à®ªà®°à¯à®•ளை அழைகà¯à®•", + "getting_started.open_source_notice": "மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ ஒர௠open source மெனà¯à®ªà¯Šà®°à¯à®³à¯ ஆகà¯à®®à¯. {github} -இன௠மூலம௠உஙà¯à®•ளால௠இதில௠பஙà¯à®•ளிகà¯à®•வோ, சிகà¯à®•லà¯à®•ளைத௠தெரியபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯‹ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.", + "getting_started.security": "கணகà¯à®•௠அமைபà¯à®ªà¯à®•ளà¯", "getting_started.terms": "சேவை விதிமà¯à®±à¯ˆà®•ளà¯", "hashtag.column_header.tag_mode.all": "மறà¯à®±à¯à®®à¯ {additional}", "hashtag.column_header.tag_mode.any": "அலà¯à®²à®¤à¯ {additional}", - "hashtag.column_header.tag_mode.none": "இலà¯à®²à®¾à®®à®²à¯ {additional}", - "hashtag.column_settings.select.no_options_message": "பரிநà¯à®¤à¯à®°à¯ˆà®•ள௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ", - "hashtag.column_settings.select.placeholder": "ஹாஷà¯à®Ÿà¯‡à®•à¯à®•ளை உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯ …", + "hashtag.column_header.tag_mode.none": "{additional} தவிரà¯à®¤à¯à®¤à¯", + "hashtag.column_settings.select.no_options_message": "பரிநà¯à®¤à¯à®°à¯ˆà®•ள௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ", + "hashtag.column_settings.select.placeholder": "சிடà¯à®Ÿà¯ˆà®•ளை உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯â€¦", "hashtag.column_settings.tag_mode.all": "இவை அனைதà¯à®¤à¯à®®à¯", - "hashtag.column_settings.tag_mode.any": "இவை எதையà¯à®®à¯", + "hashtag.column_settings.tag_mode.any": "இவறà¯à®±à®¿à®²à¯ எவையேனà¯à®®à¯", "hashtag.column_settings.tag_mode.none": "இவறà¯à®±à®¿à®²à¯ à®à®¤à¯à®®à®¿à®²à¯à®²à¯ˆ", - "hashtag.column_settings.tag_toggle": "இநà¯à®¤ நெடà¯à®µà®°à®¿à®šà¯ˆà®¯à®¿à®²à¯ கூடà¯à®¤à®²à¯ கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளை சேரà¯à®•à¯à®•வà¯à®®à¯", - "home.column_settings.basic": "அடிபà¯à®ªà®Ÿà¯ˆà®¯à®¾à®©", - "home.column_settings.show_reblogs": "காடà¯à®Ÿà¯ boosts", - "home.column_settings.show_replies": "பதிலà¯à®•ளைக௠காணà¯à®ªà®¿", + "hashtag.column_settings.tag_toggle": "இநà¯à®¤ நெடà¯à®µà®°à®¿à®šà¯ˆà®¯à®¿à®²à¯ கூடà¯à®¤à®²à¯ சிடà¯à®Ÿà¯ˆà®•ளைச௠சேரà¯à®•à¯à®•வà¯à®®à¯", + "home.column_settings.basic": "அடிபà¯à®ªà®Ÿà¯ˆà®¯à®¾à®©à®µà¯ˆ", + "home.column_settings.show_reblogs": "பகிரà¯à®µà¯à®•ளைக௠காணà¯à®ªà®¿", + "home.column_settings.show_replies": "மறà¯à®®à¯Šà®´à®¿à®•ளைக௠காணà¯à®ªà®¿", "home.hide_announcements": "அறிவிபà¯à®ªà¯à®•ளை மறை", "home.show_announcements": "அறிவிபà¯à®ªà¯à®•ளைக௠காடà¯à®Ÿà¯", - "intervals.full.days": "{number, plural, one {# day} மறà¯à®± {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} மறà¯à®± {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} மறà¯à®± {# minutes}}", - "introduction.federation.action": "அடà¯à®¤à¯à®¤", + "intervals.full.days": "{number, plural, one {# நாளà¯} other {# நாடà¯à®•ளà¯}}", + "intervals.full.hours": "{number, plural, one {# மணிநேரமà¯} other {# மணிநேரஙà¯à®•ளà¯}}", + "intervals.full.minutes": "{number, plural, one {# நிமிடமà¯} other {# நிமிடஙà¯à®•ளà¯}}", + "introduction.federation.action": "அடà¯à®¤à¯à®¤à¯", "introduction.federation.federated.headline": "கூடà¯à®Ÿà®®à¯ˆà®¨à¯à®¤", - "introduction.federation.federated.text": "கூடà¯à®Ÿà®®à¯ˆà®ªà¯à®ªà®¿à®©à¯ பிற சேவையகஙà¯à®•ளிலிரà¯à®¨à¯à®¤à¯ பொத௠பதிவà¯à®•ள௠கூடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ காலகà¯à®•ெடà¯à®µà®¿à®²à¯ தோனà¯à®±à¯à®®à¯.", + "introduction.federation.federated.text": "ஃபெடிவெரà¯à®šà®¿à®©à¯ மறà¯à®± சரà¯à®µà®°à¯à®•ளிலிரà¯à®¨à¯à®¤à¯ இடபà¯à®ªà®Ÿà¯à®®à¯ பொதà¯à®ªà¯ பதிவà¯à®•ள௠இநà¯à®¤ மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ ஆலமரதà¯à®¤à®¿à®²à¯ தோனà¯à®±à¯à®®à¯.", "introduction.federation.home.headline": "à®®à¯à®•பà¯à®ªà¯", - "introduction.federation.home.text": "நீஙà¯à®•ள௠பினà¯à®ªà®±à¯à®±à¯à®®à¯ நபரà¯à®•ளின௠இடà¯à®•ைகள௠உஙà¯à®•ள௠வீடà¯à®Ÿà¯ ஊடà¯à®Ÿà®¤à¯à®¤à®¿à®²à¯ தோனà¯à®±à¯à®®à¯. நீஙà¯à®•ள௠எநà¯à®¤ சரà¯à®µà®°à®¿à®²à¯ யாரையà¯à®®à¯ பினà¯à®ªà®±à¯à®± à®®à¯à®Ÿà®¿à®¯à¯à®®à¯!", + "introduction.federation.home.text": "நீஙà¯à®•ள௠பினà¯à®¤à¯Šà®Ÿà®°à¯à®®à¯ நபரà¯à®•ளின௠இடà¯à®•ைகள௠உஙà¯à®•ள௠மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ வீடà¯à®Ÿà®¿à®²à¯ தோனà¯à®±à¯à®®à¯. உஙà¯à®•ளால௠எநà¯à®¤ சரà¯à®µà®°à®¿à®²à¯ உளà¯à®³ எவரையà¯à®®à¯ பினà¯à®ªà®±à¯à®± à®®à¯à®Ÿà®¿à®¯à¯à®®à¯!", "introduction.federation.local.headline": "à®…à®°à¯à®•ாமை", - "introduction.federation.local.text": "உளà¯à®³à¯‚ர௠சேவையகதà¯à®¤à®¿à®²à¯ தோனà¯à®±à¯à®®à¯ அதே சரà¯à®µà®°à®¿à®²à¯ உளà¯à®³à®µà®°à¯à®•ளின௠பொத௠இடà¯à®•ைகளà¯.", - "introduction.interactions.action": "பயிறà¯à®šà®¿ à®®à¯à®Ÿà®¿à®•à¯à®•!", - "introduction.interactions.favourite.headline": "விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯à®•à¯à®•à¯à®•நà¯à®¤", - "introduction.interactions.favourite.text": "நீஙà¯à®•ள௠ஒர௠காபà¯à®ªà®¾à®±à¯à®± à®®à¯à®Ÿà®¿à®¯à¯à®®à¯ toot பினà¯à®©à®°à¯, மறà¯à®±à¯à®®à¯ ஆசிரியர௠அதை நீஙà¯à®•ள௠பிடிதà¯à®¤à®¿à®°à¯à®•à¯à®•ிறத௠எனà¯à®±à¯, அதை பிடிதà¯à®¤à®¿à®°à¯à®•à¯à®•ிறத௠எனà¯à®±à¯ தெரியபà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•ளà¯.", - "introduction.interactions.reblog.headline": "மதிபà¯à®ªà¯ˆ உயரà¯à®¤à¯à®¤à¯", - "introduction.interactions.reblog.text": "மறà¯à®±à®µà®°à¯à®•ளின௠பகிரà¯à®¨à¯à®¤à¯ கொளà¯à®³à®²à®¾à®®à¯ toots உஙà¯à®•ள௠ஆதரவாளரà¯à®•ளà¯à®Ÿà®©à¯ அவரà¯à®•ளை அதிகரிகà¯à®•à¯à®®à¯.", - "introduction.interactions.reply.headline": "மறà¯à®®à¯Šà®´à®¿ கூறà¯", - "introduction.interactions.reply.text": "நீஙà¯à®•ள௠மறà¯à®±à®µà®°à¯à®•ளà¯à®•à¯à®•à¯à®®à¯ உஙà¯à®•ள௠சொநà¯à®¤ டோடà¯à®Ÿà¯à®•ளிறà¯à®•à¯à®®à¯ பதிலளிபà¯à®ªà¯€à®°à¯à®•ளà¯, இத௠ஒர௠உரையாடலில௠சஙà¯à®•ிலி ஒனà¯à®±à®¾à®•ச௠சேரà¯à®®à¯.", - "introduction.welcome.action": "போகலாமà¯!", - "introduction.welcome.headline": "à®®à¯à®¤à®²à¯ படிகளà¯", - "introduction.welcome.text": "கூடà¯à®Ÿà®¾à®³à®¿à®•à¯à®•௠வரà¯à®•! ஒர௠சில நிமிடஙà¯à®•ளிலà¯, பலவிதமான சேவையகஙà¯à®•ளில௠செயà¯à®¤à®¿à®•ளை உரையாட மறà¯à®±à¯à®®à¯ உஙà¯à®•ள௠நணà¯à®ªà®°à¯à®•ளிடம௠பேச à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. ஆனால௠இநà¯à®¤ சரà¯à®µà®°à¯, {domain}, சிறபà¯à®ªà¯ - இத௠உஙà¯à®•ள௠சà¯à®¯à®µà®¿à®µà®°à®¤à¯à®¤à¯ˆ வழஙà¯à®•à¯à®•ிறதà¯, எனவே அதன௠பெயரை நினைவில௠கொளà¯à®³à¯à®™à¯à®•ளà¯.", - "keyboard_shortcuts.back": "பின௠செலà¯à®µà®¤à®±à¯à®•à¯", - "keyboard_shortcuts.blocked": "தடà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ பயனரà¯à®•ளின௠படà¯à®Ÿà®¿à®¯à®²à¯ˆà®¤à¯ திறகà¯à®•", - "keyboard_shortcuts.boost": "அதிகரிகà¯à®•à¯à®®à¯", - "keyboard_shortcuts.column": "நெடà¯à®µà®°à®¿à®šà¯ˆà®•ளில௠ஒனà¯à®±à®¿à®²à¯ நிலைகà¯à®•௠கவனம௠செலà¯à®¤à¯à®¤ வேணà¯à®Ÿà¯à®®à¯", - "keyboard_shortcuts.compose": "தொக௠உரைபà¯à®ªà®•à¯à®¤à®¿à®¯à¯ˆ கவனதà¯à®¤à®¿à®²à¯ கொளà¯à®³à®µà¯à®®à¯", + "introduction.federation.local.text": "உஙà¯à®•ள௠சரà¯à®µà®°à®¿à®²à¯ இரà¯à®•à¯à®•à¯à®®à¯ மறà¯à®± நபரà¯à®•ளின௠பொதà¯à®ªà¯ பதிவà¯à®•ள௠இநà¯à®¤ மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ à®®à¯à®šà¯à®šà®¨à¯à®¤à®¿à®¯à®¿à®²à¯ தோனà¯à®±à¯à®®à¯.", + "introduction.interactions.action": "பயிறà¯à®šà®¿à®¯à¯ˆ நிறைவ௠செயà¯!", + "introduction.interactions.favourite.headline": "விரà¯à®ªà¯à®ªà®®à¯", + "introduction.interactions.favourite.text": "ஒர௠டூடà¯à®Ÿà®¿à®²à¯ விரà¯à®ªà¯à®ªà®•à¯à®•à¯à®±à®¿ இடà¯à®µà®¤à®©à¯ மூலம௠உஙà¯à®•ள௠விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯ˆ அதை எழà¯à®¤à®¿à®¯à®µà®°à¯à®•à¯à®•à¯à®¤à¯ தெரியபà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯, மேலà¯à®®à¯ அநà¯à®¤ டூடà¯à®Ÿà¯ˆ மறà¯à®µà®¾à®šà®¿à®ªà¯à®ªà®¿à®±à¯à®•ாக சேமிகà¯à®•à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.", + "introduction.interactions.reblog.headline": "பகிரà¯", + "introduction.interactions.reblog.text": "மறà¯à®±à®µà®°à¯à®•ளின௠டூடà¯à®Ÿà¯à®•ளைப௠பகிரà¯à®µà®¤à®©à¯ மூலம௠அவறà¯à®±à¯ˆ உஙà¯à®•ள௠வாசகரà¯à®•ளà¯à®•à¯à®•à¯à®•௠காணà¯à®ªà®¿à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.", + "introduction.interactions.reply.headline": "மறà¯à®®à¯Šà®´à®¿", + "introduction.interactions.reply.text": "உஙà¯à®•ளால௠மறà¯à®±à®µà®°à¯à®•ளின௠டூடà¯à®Ÿà¯à®•ளிலà¯à®®à¯ உஙà¯à®•ள௠டூடà¯à®Ÿà¯à®•ளிலà¯à®®à¯ மறà¯à®®à¯Šà®´à®¿ இட à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. அவை ஒனà¯à®±à¯‹à®Ÿà¯ ஒனà¯à®±à®¾à®• சஙà¯à®•ிலிபோல௠பினà¯à®©à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ உரையாடலாக மாறà¯à®®à¯.", + "introduction.welcome.action": "வாரà¯à®™à¯à®•ள௠தà¯à®µà®™à¯à®•லாமà¯!", + "introduction.welcome.headline": "à®®à¯à®¤à®±à¯à®ªà®Ÿà®¿à®•ளà¯", + "introduction.welcome.text": "ஃபெடிவெரà¯à®¸à¯ உஙà¯à®•ளை அனà¯à®ªà¯à®Ÿà®©à¯ வரவேறà¯à®•ிறதà¯! இனà¯à®©à¯à®®à¯ சில நிமிடஙà¯à®•ளில௠உஙà¯à®•ளால௠செயà¯à®¤à®¿à®•ளை உலகிறà¯à®•à¯à®šà¯ சொலà¯à®²à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. பலà¯à®µà¯‡à®±à¯ சரà¯à®µà®°à¯à®•ளில௠இரà¯à®•à¯à®•à¯à®®à¯ உஙà¯à®•ள௠நணà¯à®ªà®°à¯à®•ளோட௠பேச à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. ஆனாலà¯, இநà¯à®¤ சரà¯à®µà®°à¯ {domain} மிகவà¯à®®à¯ தனிதà¯à®¤à¯à®µà®®à®¾à®©à®¤à¯, à®à®©à¯†à®©à®¿à®²à¯ உஙà¯à®•ள௠பகà¯à®•தà¯à®¤à¯ˆ இதà¯à®¤à®¾à®©à¯ வழஙà¯à®•à¯à®•ிறதà¯, எனவே இதன௠பெயரை நினைவில௠கொளà¯à®³à¯à®™à¯à®•ளà¯.", + "keyboard_shortcuts.back": "பின௠செலà¯à®²", + "keyboard_shortcuts.blocked": "தடà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ பயனரà¯à®•ள௠படà¯à®Ÿà®¿à®¯à®²à¯ˆà®¤à¯ திறகà¯à®•", + "keyboard_shortcuts.boost": "பகிர", + "keyboard_shortcuts.column": "à®à®¤à¯‡à®©à¯à®®à¯ ஒர௠நெடà¯à®µà®°à®¿à®šà¯ˆà®¯à®¿à®²à¯ உளà¯à®³ டூடà¯à®Ÿà¯à®²à¯ கவனம௠செலà¯à®¤à¯à®¤", + "keyboard_shortcuts.compose": "பதிவ௠எழà¯à®¤à¯à®®à¯ பெடà¯à®Ÿà®¿à®¯à®¿à®²à¯ கவனம௠செலà¯à®¤à¯à®¤", "keyboard_shortcuts.description": "விவரமà¯", - "keyboard_shortcuts.direct": "நேரடி செயà¯à®¤à®¿à®•ள௠பதà¯à®¤à®¿ திறகà¯à®•", - "keyboard_shortcuts.down": "படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ கீழே நகரà¯à®¤à¯à®¤", - "keyboard_shortcuts.enter": "பதிவைதà¯à®¤à®¿à®±à®•à¯à®•", - "keyboard_shortcuts.favourite": "பிடிதà¯à®¤à®¤à¯", - "keyboard_shortcuts.favourites": "பிடிதà¯à®¤à®µà¯ˆ படà¯à®Ÿà®¿à®¯à®²à¯ˆ திறகà¯à®•", - "keyboard_shortcuts.federated": "à®’à®°à¯à®™à¯à®•ிணைநà¯à®¤ நேரதà¯à®¤à¯ˆ திறகà¯à®•", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.home": "வீடà¯à®Ÿà¯ நேரதà¯à®¤à¯ˆ திறகà¯à®•", + "keyboard_shortcuts.direct": "தனிபà¯à®ªà¯†à®Ÿà¯à®Ÿà®¿à®¯à¯ˆà®¤à¯ திறகà¯à®•", + "keyboard_shortcuts.down": "படà¯à®Ÿà®¿à®¯à®²à®¿à®©à¯ கீழே செலà¯à®²", + "keyboard_shortcuts.enter": "டூடà¯à®Ÿà¯ˆà®¤à¯ திறகà¯à®•", + "keyboard_shortcuts.favourite": "விரà¯à®ªà¯à®ªà®•à¯à®•à¯à®±à®¿ இட", + "keyboard_shortcuts.favourites": "விரà¯à®ªà¯à®ªà®ªà¯ படà¯à®Ÿà®¿à®¯à®²à¯ˆà®¤à¯ திறகà¯à®•", + "keyboard_shortcuts.federated": "மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ ஆலமரதà¯à®¤à¯ˆà®¤à¯ திறகà¯à®•", + "keyboard_shortcuts.heading": "விசைபà¯à®ªà®²à®•ை கà¯à®±à¯à®•à¯à®•à¯à®µà®´à®¿à®•ளà¯", + "keyboard_shortcuts.home": "மாஸà¯à®Ÿà®Ÿà®¾à®©à¯ வீடà¯à®Ÿà¯ˆà®¤à¯ திறகà¯à®•", "keyboard_shortcuts.hotkey": "ஹாட௠கீ", "keyboard_shortcuts.legend": "இநà¯à®¤ பà¯à®°à®¾à®£à®¤à¯à®¤à¯ˆ காடà¯à®šà®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤", "keyboard_shortcuts.local": "உளà¯à®³à¯‚ர௠காலவரிசை திறகà¯à®•", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "பதிலளிகà¯à®•", "keyboard_shortcuts.requests": "கோரிகà¯à®•ைகள௠படà¯à®Ÿà®¿à®¯à®²à¯ˆà®¤à¯ திறகà¯à®•", "keyboard_shortcuts.search": "தேடல௠கவனம௠செலà¯à®¤à¯à®¤", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "உளà¯à®³à®Ÿà®•à¯à®• எசà¯à®šà®°à®¿à®•à¯à®•ை செயà¯à®¤à®¿à®¯à¯ˆà®•௠காடà¯à®Ÿ/மறைகà¯à®•", "keyboard_shortcuts.start": "'தொடஙà¯à®•à¯à®µà®¤à®±à¯à®•à¯' நெடà¯à®µà®°à®¿à®šà¯ˆ திறகà¯à®•", "keyboard_shortcuts.toggle_hidden": "CW கà¯à®•௠பினà¯à®©à®¾à®²à¯ உரையை மறைகà¯à®• / மறைகà¯à®•", "keyboard_shortcuts.toggle_sensitivity": "படிமஙà¯à®•ளைக௠காடà¯à®Ÿ/மறைகà¯à®•", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "உரை பகà¯à®¤à®¿à®¯à¯ˆ / தேடலை கவனம௠செலà¯à®¤à¯à®¤ வேணà¯à®Ÿà¯à®®à¯", "keyboard_shortcuts.up": "படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ மேலே செலà¯à®²", "lightbox.close": "நெரà¯à®•à¯à®•மாக", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "அடà¯à®¤à¯à®¤", "lightbox.previous": "செனà¯à®±", - "lightbox.view_context": "சூழலைக௠பாரà¯", "lists.account.add": "படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ சேரà¯", "lists.account.remove": "படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ அகறà¯à®±à¯", "lists.delete": "படà¯à®Ÿà®¿à®¯à®²à¯ˆ நீகà¯à®•à¯", @@ -260,6 +266,10 @@ "lists.edit.submit": "தலைபà¯à®ªà¯ மாறà¯à®±à®µà¯à®®à¯", "lists.new.create": "படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ சேரà¯", "lists.new.title_placeholder": "பà¯à®¤à®¿à®¯ படà¯à®Ÿà®¿à®¯à®²à¯ தலைபà¯à®ªà¯", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "நீஙà¯à®•ள௠பினà¯à®¤à¯†à®¾à®Ÿà®°à¯à®®à¯ நபரà¯à®•ள௠மதà¯à®¤à®¿à®¯à®¿à®²à¯ தேடà¯à®¤à®²à¯", "lists.subheading": "உஙà¯à®•ள௠படà¯à®Ÿà®¿à®¯à®²à¯à®•ளà¯", "load_pending": "{count, plural,one {# பà¯à®¤à®¿à®¯à®¤à¯}other {# பà¯à®¤à®¿à®¯à®µà¯ˆ}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "நிலைமாறà¯à®±à¯ தெரியà¯à®®à¯", "missing_indicator.label": "கிடைகà¯à®•விலà¯à®²à¯ˆ", "missing_indicator.sublabel": "இநà¯à®¤ ஆதாரதà¯à®¤à¯ˆ காண à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "இநà¯à®¤ பயனரின௠அறிவிபà¯à®ªà¯à®•ளை மறைகà¯à®•வா?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "மொபைல௠பயனà¯à®ªà®¾à®Ÿà¯à®•ளà¯", "navigation_bar.blocks": "தடà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ பயனரà¯à®•ளà¯", "navigation_bar.bookmarks": "அடையாளகà¯à®•à¯à®±à®¿à®•ளà¯", @@ -298,6 +310,7 @@ "notification.own_poll": "கரà¯à®¤à¯à®¤à¯à®•à¯à®•ணிபà¯à®ªà¯ நிறைவடைநà¯à®¤à®¤à¯", "notification.poll": "நீஙà¯à®•ள௠வாகà¯à®•ளிதà¯à®¤ வாகà¯à®•ெடà¯à®ªà¯à®ªà¯ à®®à¯à®Ÿà®¿à®µà®Ÿà¯ˆà®¨à¯à®¤à®¤à¯", "notification.reblog": "{name} உஙà¯à®•ள௠நிலை அதிகரிதà¯à®¤à®¤à¯", + "notification.status": "{name} just posted", "notifications.clear": "அறிவிபà¯à®ªà¯à®•ளை அழிகà¯à®•வà¯à®®à¯", "notifications.clear_confirmation": "உஙà¯à®•ள௠எலà¯à®²à®¾ அறிவிபà¯à®ªà¯à®•ளையà¯à®®à¯ நிரநà¯à®¤à®°à®®à®¾à®• அழிகà¯à®• விரà¯à®®à¯à®ªà¯à®•ிறீரà¯à®•ளா?", "notifications.column_settings.alert": "டெஸà¯à®•à¯à®Ÿà®¾à®ªà¯ அறிவிபà¯à®ªà¯à®•ளà¯", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "மதிபà¯à®ªà¯ˆ உயரà¯à®¤à¯à®¤à¯:", "notifications.column_settings.show": "பதà¯à®¤à®¿à®¯à®¿à®²à¯ காணà¯à®ªà®¿", "notifications.column_settings.sound": "ஒலி விளையாட", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "எலà¯à®²à®¾", "notifications.filter.boosts": "மதிபà¯à®ªà¯ˆ உயரà¯à®¤à¯à®¤à¯", "notifications.filter.favourites": "விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯à®•à¯à®•à¯à®•நà¯à®¤", "notifications.filter.follows": "பினà¯à®ªà®±à¯à®±à¯", "notifications.filter.mentions": "கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®•ிறாரà¯", "notifications.filter.polls": "கரà¯à®¤à¯à®¤à¯à®•à¯à®•ணிபà¯à®ªà¯ à®®à¯à®Ÿà®¿à®µà¯à®•ளà¯", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} அறிவிபà¯à®ªà¯à®•ளà¯", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "மூடிய", "poll.refresh": "பதà¯à®¤à¯à®¯à®¿à®°à¯à®ªà¯à®ª?டà¯à®Ÿà¯", "poll.total_people": "{count, plural, one {# நபரà¯} other {# நபரà¯à®•ளà¯}}", @@ -419,11 +443,11 @@ "time_remaining.minutes": "{number, plural, one {# minute} மறà¯à®± {# minutes}} left", "time_remaining.moments": "தரà¯à®£à®™à¯à®•ள௠மீதமà¯à®³à¯à®³à®©", "time_remaining.seconds": "{number, plural, one {# second} மறà¯à®± {# seconds}} left", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "பிற சரà¯à®µà®°à¯à®•ளிலிரà¯à®¨à¯à®¤à¯ வரà¯à®®à¯ {resource} காடà¯à®Ÿà®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ.", + "timeline_hint.resources.followers": "வாசகரà¯à®•ளà¯", + "timeline_hint.resources.follows": "வாசிகà¯à®•ிறாரà¯", + "timeline_hint.resources.statuses": "பழைய டூடà¯à®Ÿà¯à®•ளà¯", + "trends.counter_by_accounts": "{count, plural, one {{counter} நபரà¯} other {{counter} நபரà¯à®•ளà¯}} உரையாடலிலà¯", "trends.trending_now": "இபà¯à®ªà¯‹à®¤à¯ செலà¯à®¤à®¿à®šà¯ˆà®¯à®¿à®²à¯ இரà¯à®ªà¯à®ªà®µà¯ˆ", "ui.beforeunload": "நீஙà¯à®•ள௠வெளியே செனà¯à®±à®¾à®²à¯ உஙà¯à®•ள௠வரைவ௠இழகà¯à®•பà¯à®ªà®Ÿà¯à®®à¯ மஸà¯à®¤à¯‹à®Ÿà¯‹à®©à¯.", "units.short.billion": "{count}B", @@ -436,16 +460,17 @@ "upload_form.audio_description": "செவிதà¯à®¤à®¿à®±à®©à¯ கà¯à®±à¯ˆà®ªà®¾à®Ÿà¯ உளà¯à®³à®µà®°à¯à®•ளà¯à®•à¯à®•ாக விளகà¯à®•à¯à®•‌", "upload_form.description": "பாரà¯à®µà¯ˆà®¯à®±à¯à®± விவரிகà¯à®•வà¯à®®à¯", "upload_form.edit": "தொகà¯", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "சிறà¯à®ªà®Ÿà®¤à¯à®¤à¯ˆ மாறà¯à®±", "upload_form.undo": "நீகà¯à®•à¯", "upload_form.video_description": "செவிதà¯à®¤à®¿à®±à®©à¯ மறà¯à®±à¯à®®à¯ பாரà¯à®µà¯ˆà®•௠கà¯à®±à¯ˆà®ªà®¾à®Ÿà¯ உளà¯à®³à®µà®°à¯à®•ளà¯à®•à¯à®•ாக விளகà¯à®•à¯à®•‌", "upload_modal.analyzing_picture": "படம௠ஆராயபà¯à®ªà®Ÿà¯à®•ிறதà¯â€¦", "upload_modal.apply": "உபயோகி", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "படதà¯à®¤à¯ˆà®¤à¯ தேரà¯à®µà¯à®šà¯†à®¯à¯à®¯", "upload_modal.description_placeholder": "பொரà¯à®³à¯ விளகà¯à®•à®®à¯", "upload_modal.detect_text": "படதà¯à®¤à®¿à®²à¯ இரà¯à®•à¯à®•à¯à®®à¯ எழà¯à®¤à¯à®¤à¯ˆ கணà¯à®Ÿà®±à®¿", "upload_modal.edit_media": "படதà¯à®¤à¯ˆà®¤à¯ தொகà¯", "upload_modal.hint": "எலà¯à®²à®¾ விலà¯à®²à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®²à¯à®®à¯ தெரியவேணà¯à®Ÿà®¿à®¯, படதà¯à®¤à®¿à®©à¯ à®®à¯à®•à¯à®•ிய கà¯à®µà®¿à®¯à®ªà¯à®ªà¯à®³à¯à®³à®¿à®•à¯à®•à¯, வடà¯à®Ÿà®¤à¯à®¤à¯ˆ சொடà¯à®•à¯à®•ி இழà¯à®¤à¯à®¤à¯à®šà¯à®šà¯†à®²à¯à®²à®µà¯à®®à¯.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "à®®à¯à®©à¯à®©à¯‹à®Ÿà¯à®Ÿà®®à¯ ({ratio})", "upload_progress.label": "à®à®±à¯à®±à¯à®•ிறத௠...", "video.close": "வீடியோவை மூடà¯", diff --git a/app/javascript/mastodon/locales/tai.json b/app/javascript/mastodon/locales/tai.json index e5d833fe87465898b1831bb4ceb749f69e1f8e65..70f6ab1529e76eb2ac320779468d4f934d169e1a 100644 --- a/app/javascript/mastodon/locales/tai.json +++ b/app/javascript/mastodon/locales/tai.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain blocked", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index 4763dcbd309154f5ece5126e0c8c4d2f7c809ac3..994682a675c4cd184d0dbb8e34a178ab29b5fd7b 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "@{name}కౠనేరà±à°—à°¾ సందేశం పంపà±", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "డొమైనౠదాచిపెటà±à°Ÿà°¬à°¡à°¿à°¨à°¦à°¿", "account.edit_profile": "à°ªà±à°°à±Šà°«à±ˆà°²à±à°¨à°¿ సవరించండి", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "à°ªà±à°°à±Šà°«à±ˆà°²à±à°²à±‹ చూపించà±", "account.follow": "à°…à°¨à±à°¸à°°à°¿à°‚à°šà±", "account.followers": "à°…à°¨à±à°šà°°à±à°²à±", @@ -96,7 +98,7 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "టూటà±", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", "compose_form.sensitive.marked": "మీడియా à°¸à±à°¨à±à°¨à°¿à°¤à°®à±ˆà°¨à°¦à°¿à°—à°¾ à°—à±à°°à±à°¤à°¿à°‚చబడింది", "compose_form.sensitive.unmarked": "మీడియా à°¸à±à°¨à±à°¨à°¿à°¤à°®à±ˆà°¨à°¦à°¿à°—à°¾ à°—à±à°°à±à°¤à°¿à°‚చబడలేదà±", "compose_form.spoiler.marked": "హెచà±à°šà°°à°¿à°• వెనà±à°• పాఠà±à°¯à°‚ దాచబడింది", @@ -147,6 +149,7 @@ "emoji_button.search_results": "శోధన ఫలితాలà±", "emoji_button.symbols": "à°šà°¿à°¹à±à°¨à°¾à°²à±", "emoji_button.travel": "à°ªà±à°°à°¯à°¾à°£à°‚ & à°ªà±à°°à°¦à±‡à°¶à°¾à°²à±", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "ఇకà±à°•à°¡ ఠటూటà±à°²à±‚ లేవà±!No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "మీరౠఇంకా ఠవినియోగదారà±à°²à°¨à±‚ à°¬à±à°²à°¾à°•ౠచేయలేదà±.", @@ -166,7 +169,9 @@ "empty_column.notifications": "మీకౠఇంకా ఠనోటిఫికేషనà±à°²à± లేవà±. సంà°à°¾à°·à°£à°¨à± à°ªà±à°°à°¾à°°à°‚à°à°¿à°‚చడానికి ఇతరà±à°²à°¤à±‹ à°ªà±à°°à°¤à°¿à°¸à±à°ªà°‚దించండి.", "empty_column.public": "ఇకà±à°•à°¡ à°à°®à±€ లేదà±! దీనà±à°¨à°¿ నింపడానికి బహిరంగంగా à°à°¦à±ˆà°¨à°¾ à°µà±à°°à°¾à°¯à°‚à°¡à°¿, లేదా ఇతర సేవికల à°¨à±à°‚à°¡à°¿ వినియోగదారà±à°²à°¨à± à°…à°¨à±à°¸à°°à°¿à°‚à°šà°‚à°¡à°¿", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "à°…à°¨à±à°®à°¤à°¿à°‚à°šà±", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "పాఠà±à°¯à°‚ à°µà±à°°à°¾à°¸à±‡ à°à°°à°¿à°¯à°¾/శోధన పటà±à°Ÿà°¿à°• à°¨à±à°‚à°¡à°¿ బయటకౠరావడానికి", "keyboard_shortcuts.up": "జాబితాలో పైకి తరలించడానికి", "lightbox.close": "మూసివేయà±", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "తరà±à°µà°¾à°¤", "lightbox.previous": "à°®à±à°¨à±à°ªà°Ÿà°¿", - "lightbox.view_context": "View context", "lists.account.add": "జాబితాకౠజోడించà±", "lists.account.remove": "జాబితా à°¨à±à°‚à°¡à°¿ తొలగించà±", "lists.delete": "జాబితానౠతొలగించà±", @@ -260,6 +266,10 @@ "lists.edit.submit": "శీరà±à°·à°¿à°• మారà±à°šà±", "lists.new.create": "జాబితానౠజోడించà±", "lists.new.title_placeholder": "కొతà±à°¤ జాబితా శీరà±à°·à°¿à°•", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "మీరౠఅనà±à°¸à°°à°¿à°‚చే à°µà±à°¯à°•à±à°¤à±à°²à°²à±‹ శోధించండి", "lists.subheading": "మీ జాబితాలà±", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "దృశà±à°¯à°®à°¾à°¨à°¤à°¨à± టోగà±à°²à± చేయండి", "missing_indicator.label": "దొరకలేదà±", "missing_indicator.sublabel": "à°ˆ వనరౠకనà±à°—ొనబడలేదà±", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "à°ˆ వినియోగదారౠనà±à°‚à°¡à°¿ నోటిఫికేషనà±à°²à°¨à± దాచాలా?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "మొబైలౠఆపౠలà±", "navigation_bar.blocks": "à°¬à±à°²à°¾à°•ౠచేయబడిన వినియోగదారà±à°²à±", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "మీరౠపాలà±à°—ొనిన à°Žà°¨à±à°¸à°¿à°• à°®à±à°—ిసినది", "notification.reblog": "{name} మీ à°¸à±à°Ÿà±‡à°Ÿà°¸à± నౠబూసà±à°Ÿà± చేసారà±", + "notification.status": "{name} just posted", "notifications.clear": "à°ªà±à°°à°•టనలనౠతà±à°¡à°¿à°šà°¿à°µà±‡à°¯à±", "notifications.clear_confirmation": "మీరౠమీ à°…à°¨à±à°¨à°¿ నోటిఫికేషనà±à°²à°¨à± శాశà±à°µà°¤à°‚à°—à°¾ తొలగించాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?", "notifications.column_settings.alert": "డెసà±à°•à±à°Ÿà°¾à°ªà± నోటిఫికేషనà±à°²à±", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "బూసà±à°Ÿà± à°²à±:", "notifications.column_settings.show": "నిలà±à°µà± వరà±à°¸à°²à±‹ చూపà±", "notifications.column_settings.sound": "à°§à±à°µà°¨à°¿à°¨à°¿ à°ªà±à°²à±‡ చేయి", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "à°…à°¨à±à°¨à±€", "notifications.filter.boosts": "బూసà±à°Ÿà±à°²à±", "notifications.filter.favourites": "ఇషà±à°Ÿà°¾à°²à±", "notifications.filter.follows": "à°…à°¨à±à°¸à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°µà°¿", "notifications.filter.mentions": "పేరà±à°•ొనà±à°¨à°µà°¿", "notifications.filter.polls": "à°Žà°¨à±à°¨à°¿à°• ఫలితాలà±", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} à°ªà±à°°à°•టనలà±", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "మూసివేయబడినవి", "poll.refresh": "నవీకరించà±", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "à°…à°ªà±à°²à±‹à°¡à± à°…à°µà±à°¤à±‹à°‚ది...", "video.close": "వీడియోని మూసివేయి", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index a5c6b07cde64013e8e9df28e0dc8a5d9f1ffce3b..30ec26809b566e108feee5d6d27ac9daa79e410e 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -1,22 +1,24 @@ { - "account.account_note_header": "หมายเหตุขà¸à¸‡à¸„ุณสำหรับ @{name}", + "account.account_note_header": "หมายเหตุ", "account.add_or_remove_from_list": "เพิ่มหรืà¸à¹€à¸à¸²à¸à¸à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£", "account.badges.bot": "บà¸à¸•", "account.badges.group": "à¸à¸¥à¸¸à¹ˆà¸¡", "account.block": "ปิดà¸à¸±à¹‰à¸™ @{name}", "account.block_domain": "ปิดà¸à¸±à¹‰à¸™à¹‚ดเมน {domain}", "account.blocked": "ปิดà¸à¸±à¹‰à¸™à¸à¸¢à¸¹à¹ˆ", - "account.browse_more_on_origin_server": "ดูเพิ่มเติมในโปรไฟล์ต้นฉบับ", + "account.browse_more_on_origin_server": "เรียà¸à¸”ูเพิ่มเติมในโปรไฟล์ดั้งเดิม", "account.cancel_follow_request": "ยà¸à¹€à¸¥à¸´à¸à¸„ำขà¸à¸•ิดตาม", "account.direct": "ส่งข้à¸à¸„วามโดยตรงถึง @{name}", + "account.disable_notifications": "หยุดà¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸‰à¸±à¸™à¹€à¸¡à¸·à¹ˆà¸ @{name} โพสต์", "account.domain_blocked": "ปิดà¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸¢à¸¹à¹ˆ", "account.edit_profile": "à¹à¸à¹‰à¹„ขโปรไฟล์", + "account.enable_notifications": "à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸‰à¸±à¸™à¹€à¸¡à¸·à¹ˆà¸ @{name} โพสต์", "account.endorse": "à¹à¸ªà¸”งให้เห็นในโปรไฟล์", "account.follow": "ติดตาม", "account.followers": "ผู้ติดตาม", "account.followers.empty": "ยังไม่มีใครติดตามผู้ใช้นี้", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, other {{counter} ผู้ติดตาม}}", + "account.following_counter": "{count, plural, other {{counter} à¸à¸³à¸¥à¸±à¸‡à¸•ิดตาม}}", "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", "account.hide_reblogs": "ซ่à¸à¸™à¸à¸²à¸£à¸”ันจาภ@{name}", @@ -36,14 +38,14 @@ "account.requested": "à¸à¸³à¸¥à¸±à¸‡à¸£à¸à¸à¸²à¸£à¸à¸™à¸¸à¸¡à¸±à¸•ิ คลิà¸à¹€à¸žà¸·à¹ˆà¸à¸¢à¸à¹€à¸¥à¸´à¸à¸„ำขà¸à¸•ิดตาม", "account.share": "à¹à¸šà¹ˆà¸‡à¸›à¸±à¸™à¹‚ปรไฟล์ขà¸à¸‡ @{name}", "account.show_reblogs": "à¹à¸ªà¸”งà¸à¸²à¸£à¸”ันจาภ@{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, other {{counter} โพสต์}}", "account.unblock": "เลิà¸à¸›à¸´à¸”à¸à¸±à¹‰à¸™ @{name}", "account.unblock_domain": "เลิà¸à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน {domain}", "account.unendorse": "ไม่à¹à¸ªà¸”งให้เห็นในโปรไฟล์", "account.unfollow": "เลิà¸à¸•ิดตาม", "account.unmute": "เลิà¸à¸‹à¹ˆà¸à¸™ @{name}", "account.unmute_notifications": "เลิà¸à¸‹à¹ˆà¸à¸™à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸ˆà¸²à¸ @{name}", - "account_note.placeholder": "ไม่มีความคิดเห็นที่ระบุไว้", + "account_note.placeholder": "คลิà¸à¹€à¸žà¸·à¹ˆà¸à¹€à¸žà¸´à¹ˆà¸¡à¸«à¸¡à¸²à¸¢à¹€à¸«à¸•ุ", "alert.rate_limited.message": "โปรดลà¸à¸‡à¹ƒà¸«à¸¡à¹ˆà¸«à¸¥à¸±à¸‡à¸ˆà¸²à¸ {retry_time, time, medium}", "alert.rate_limited.title": "มีà¸à¸²à¸£à¸ˆà¸³à¸à¸±à¸”à¸à¸±à¸•รา", "alert.unexpected.message": "เà¸à¸´à¸”ข้à¸à¸œà¸´à¸”พลาดที่ไม่คาดคิด", @@ -82,23 +84,23 @@ "community.column_settings.local_only": "ในเซิร์ฟเวà¸à¸£à¹Œà¹€à¸—่านั้น", "community.column_settings.media_only": "สื่à¸à¹€à¸—่านั้น", "community.column_settings.remote_only": "ระยะไà¸à¸¥à¹€à¸—่านั้น", - "compose_form.direct_message_warning": "โพสต์นี้จะถูà¸à¸ªà¹ˆà¸‡à¹„ปยังผู้ใช้ที่à¸à¸¥à¹ˆà¸²à¸§à¸–ึงเท่านั้น", + "compose_form.direct_message_warning": "จะส่งโพสต์นี้ไปยังผู้ใช้ที่à¸à¸¥à¹ˆà¸²à¸§à¸–ึงเท่านั้น", "compose_form.direct_message_warning_learn_more": "เรียนรู้เพิ่มเติม", - "compose_form.hashtag_warning": "โพสต์นี้จะไม่ถูà¸à¹à¸ªà¸”งในà¹à¸®à¸Šà¹à¸—็à¸à¹ƒà¸” ๆ เนื่à¸à¸‡à¸ˆà¸²à¸à¹„ม่à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£ เฉพาะโพสต์สาธารณะเท่านั้นที่สามารถค้นหาโดยà¹à¸®à¸Šà¹à¸—็à¸", + "compose_form.hashtag_warning": "จะไม่à¹à¸ªà¸”งรายà¸à¸²à¸£à¹‚พสต์นี้ภายใต้à¹à¸®à¸Šà¹à¸—็à¸à¹ƒà¸” ๆ เนื่à¸à¸‡à¸ˆà¸²à¸à¹„ม่à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£ เฉพาะโพสต์สาธารณะเท่านั้นที่สามารถค้นหาโดยà¹à¸®à¸Šà¹à¸—็à¸", "compose_form.lock_disclaimer": "บัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณไม่ได้ {locked} ใครà¸à¹‡à¸•ามสามารถติดตามคุณเพื่à¸à¸”ูโพสต์สำหรับผู้ติดตามเท่านั้นขà¸à¸‡à¸„ุณ", "compose_form.lock_disclaimer.lock": "ล็à¸à¸„à¸à¸¢à¸¹à¹ˆ", "compose_form.placeholder": "คุณà¸à¸³à¸¥à¸±à¸‡à¸„ิดà¸à¸°à¹„รà¸à¸¢à¸¹à¹ˆ?", "compose_form.poll.add_option": "เพิ่มตัวเลืà¸à¸", - "compose_form.poll.duration": "ระยะเวลาโพล", + "compose_form.poll.duration": "ระยะเวลาà¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็น", "compose_form.poll.option_placeholder": "ตัวเลืà¸à¸ {number}", "compose_form.poll.remove_option": "เà¸à¸²à¸•ัวเลืà¸à¸à¸™à¸µà¹‰à¸à¸à¸", "compose_form.poll.switch_to_multiple": "เปลี่ยนà¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นเป็นà¸à¸™à¸¸à¸à¸²à¸•หลายตัวเลืà¸à¸", "compose_form.poll.switch_to_single": "เปลี่ยนà¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นเป็นà¸à¸™à¸¸à¸à¸²à¸•ตัวเลืà¸à¸à¹€à¸”ี่ยว", "compose_form.publish": "โพสต์", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™", - "compose_form.sensitive.marked": "มีà¸à¸²à¸£à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™", - "compose_form.sensitive.unmarked": "ไม่มีà¸à¸²à¸£à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™", + "compose_form.sensitive.hide": "{count, plural, other {ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™}}", + "compose_form.sensitive.marked": "{count, plural, other {มีà¸à¸²à¸£à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™}}", + "compose_form.sensitive.unmarked": "{count, plural, other {ไม่มีà¸à¸²à¸£à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™}}", "compose_form.spoiler.marked": "มีà¸à¸²à¸£à¸‹à¹ˆà¸à¸™à¸‚้à¸à¸„วามà¸à¸¢à¸¹à¹ˆà¸«à¸¥à¸±à¸‡à¸„ำเตืà¸à¸™", "compose_form.spoiler.unmarked": "ไม่มีà¸à¸²à¸£à¸‹à¹ˆà¸à¸™à¸‚้à¸à¸„วาม", "compose_form.spoiler_placeholder": "เขียนคำเตืà¸à¸™à¸‚à¸à¸‡à¸„ุณที่นี่", @@ -147,6 +149,7 @@ "emoji_button.search_results": "ผลลัพธ์à¸à¸²à¸£à¸„้นหา", "emoji_button.symbols": "สัà¸à¸¥à¸±à¸à¸©à¸“์", "emoji_button.travel": "à¸à¸²à¸£à¹€à¸”ินทางà¹à¸¥à¸°à¸ªà¸–านที่", + "empty_column.account_suspended": "ระงับบัà¸à¸Šà¸µà¸à¸¢à¸¹à¹ˆ", "empty_column.account_timeline": "ไม่มีโพสต์ที่นี่!", "empty_column.account_unavailable": "ไม่มีโปรไฟล์", "empty_column.blocks": "คุณยังไม่ได้ปิดà¸à¸±à¹‰à¸™à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¹ƒà¸” ๆ", @@ -166,7 +169,9 @@ "empty_column.notifications": "คุณยังไม่มีà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¹ƒà¸” ๆ โต้ตà¸à¸šà¸à¸±à¸šà¸œà¸¹à¹‰à¸à¸·à¹ˆà¸™à¹€à¸žà¸·à¹ˆà¸à¹€à¸£à¸´à¹ˆà¸¡à¸à¸²à¸£à¸ªà¸™à¸—นา", "empty_column.public": "ไม่มีสิ่งใดที่นี่! เขียนบางà¸à¸¢à¹ˆà¸²à¸‡à¹€à¸›à¹‡à¸™à¸ªà¸²à¸˜à¸²à¸£à¸“ะ หรืà¸à¸•ิดตามผู้ใช้จาà¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸à¸·à¹ˆà¸™ ๆ ด้วยตนเà¸à¸‡à¹€à¸žà¸·à¹ˆà¸à¹€à¸•ิมให้เต็ม", "error.unexpected_crash.explanation": "เนื่à¸à¸‡à¸ˆà¸²à¸à¸‚้à¸à¸šà¸à¸žà¸£à¹ˆà¸à¸‡à¹ƒà¸™à¹‚ค้ดขà¸à¸‡à¹€à¸£à¸²à¸«à¸£à¸·à¸à¸›à¸±à¸à¸«à¸²à¸„วามเข้าà¸à¸±à¸™à¹„ด้ขà¸à¸‡à¹€à¸šà¸£à¸²à¸§à¹Œà¹€à¸‹à¸à¸£à¹Œ จึงไม่สามารถà¹à¸ªà¸”งหน้านี้ได้à¸à¸¢à¹ˆà¸²à¸‡à¸–ูà¸à¸•้à¸à¸‡", + "error.unexpected_crash.explanation_addons": "ไม่สามารถà¹à¸ªà¸”งหน้านี้ได้à¸à¸¢à¹ˆà¸²à¸‡à¸–ูà¸à¸•้à¸à¸‡ ข้à¸à¸œà¸´à¸”พลาดนี้เป็นไปได้ว่าเà¸à¸´à¸”จาà¸à¸ªà¹ˆà¸§à¸™à¹€à¸ªà¸£à¸´à¸¡à¸‚à¸à¸‡à¹€à¸šà¸£à¸²à¸§à¹Œà¹€à¸‹à¸à¸£à¹Œà¸«à¸£à¸·à¸à¹€à¸„รื่à¸à¸‡à¸¡à¸·à¸à¸à¸²à¸£à¹à¸›à¸¥à¸à¸±à¸•โนมัติ", "error.unexpected_crash.next_steps": "ลà¸à¸‡à¸£à¸µà¹€à¸Ÿà¸£à¸Šà¸«à¸™à¹‰à¸² หาà¸à¸™à¸±à¹ˆà¸™à¹„ม่ช่วย คุณà¸à¸²à¸ˆà¸¢à¸±à¸‡à¸ªà¸²à¸¡à¸²à¸£à¸–ใช้ Mastodon ผ่านเบราว์เซà¸à¸£à¹Œà¸à¸·à¹ˆà¸™à¸«à¸£à¸·à¸à¹à¸à¸›", + "error.unexpected_crash.next_steps_addons": "ลà¸à¸‡à¸›à¸´à¸”ใช้งานส่วนเสริมหรืà¸à¹€à¸„รื่à¸à¸‡à¸¡à¸·à¸à¹à¸¥à¹‰à¸§à¸£à¸µà¹€à¸Ÿà¸£à¸Šà¸«à¸™à¹‰à¸² หาà¸à¸™à¸±à¹ˆà¸™à¹„ม่ช่วย คุณà¸à¸²à¸ˆà¸¢à¸±à¸‡à¸ªà¸²à¸¡à¸²à¸£à¸–ใช้ Mastodon ผ่านเบราว์เซà¸à¸£à¹Œà¸à¸·à¹ˆà¸™à¸«à¸£à¸·à¸à¹à¸à¸›", "errors.unexpected_crash.copy_stacktrace": "คัดลà¸à¸à¸à¸²à¸£à¸•ิดตามสà¹à¸•à¸à¹„ปยังคลิปบà¸à¸£à¹Œà¸”", "errors.unexpected_crash.report_issue": "รายงานปัà¸à¸«à¸²", "follow_request.authorize": "à¸à¸™à¸¸à¸à¸²à¸•", @@ -202,7 +207,7 @@ "introduction.federation.federated.headline": "ที่ติดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸", "introduction.federation.federated.text": "โพสต์สาธารณะจาà¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸à¸·à¹ˆà¸™ ๆ ขà¸à¸‡à¹€à¸Ÿà¸”ิเวิร์สจะปราà¸à¸à¹ƒà¸™à¹€à¸ªà¹‰à¸™à¹€à¸§à¸¥à¸²à¸—ี่ติดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸", "introduction.federation.home.headline": "หน้าà¹à¸£à¸", - "introduction.federation.home.text": "โพสต์จาà¸à¸œà¸¹à¹‰à¸„นที่คุณติดตามจะปราà¸à¸à¹ƒà¸™à¸Ÿà¸µà¸”หน้าà¹à¸£à¸à¸‚à¸à¸‡à¸„ุณ คุณสามารถติดตามใครà¸à¹‡à¹„ด้บนเซิร์ฟเวà¸à¸£à¹Œà¹„หนà¸à¹‡à¹„ด้!", + "introduction.federation.home.text": "โพสต์จาà¸à¸œà¸¹à¹‰à¸„นที่คุณติดตามจะปราà¸à¸à¹ƒà¸™à¸Ÿà¸µà¸”หน้าà¹à¸£à¸à¸‚à¸à¸‡à¸„ุณ คุณสามารถติดตามใครà¸à¹‡à¸•ามในเซิร์ฟเวà¸à¸£à¹Œà¹ƒà¸”à¸à¹‡à¸•าม!", "introduction.federation.local.headline": "ในเซิร์ฟเวà¸à¸£à¹Œ", "introduction.federation.local.text": "โพสต์สาธารณะจาà¸à¸œà¸¹à¹‰à¸„นในเซิร์ฟเวà¸à¸£à¹Œà¹€à¸”ียวà¸à¸±à¸™à¸à¸±à¸šà¸„ุณจะปราà¸à¸à¹ƒà¸™à¹€à¸ªà¹‰à¸™à¹€à¸§à¸¥à¸²à¹ƒà¸™à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ", "introduction.interactions.action": "เสร็จสิ้นบทช่วยสà¸à¸™!", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "เพื่à¸à¹€à¸¥à¸´à¸à¹‚ฟà¸à¸±à¸ªà¸žà¸·à¹‰à¸™à¸—ี่เขียนข้à¸à¸„วาม/à¸à¸²à¸£à¸„้นหา", "keyboard_shortcuts.up": "เพื่à¸à¸¢à¹‰à¸²à¸¢à¸‚ึ้นในรายà¸à¸²à¸£", "lightbox.close": "ปิด", + "lightbox.compress": "บีบà¸à¸±à¸”à¸à¸¥à¹ˆà¸à¸‡à¸”ูภาพ", + "lightbox.expand": "ขยายà¸à¸¥à¹ˆà¸à¸‡à¸”ูภาพ", "lightbox.next": "ถัดไป", "lightbox.previous": "à¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸²", - "lightbox.view_context": "ดูบริบท", "lists.account.add": "เพิ่มไปยังรายà¸à¸²à¸£", "lists.account.remove": "เà¸à¸²à¸à¸à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£", "lists.delete": "ลบรายà¸à¸²à¸£", @@ -260,6 +266,10 @@ "lists.edit.submit": "เปลี่ยนชื่à¸à¹€à¸£à¸·à¹ˆà¸à¸‡", "lists.new.create": "เพิ่มรายà¸à¸²à¸£", "lists.new.title_placeholder": "ชื่à¸à¹€à¸£à¸·à¹ˆà¸à¸‡à¸£à¸²à¸¢à¸à¸²à¸£à¹ƒà¸«à¸¡à¹ˆ", + "lists.replies_policy.followed": "ผู้ใช้ใด ๆ ที่ติดตาม", + "lists.replies_policy.list": "สมาชิà¸à¸‚à¸à¸‡à¸£à¸²à¸¢à¸à¸²à¸£", + "lists.replies_policy.none": "ไม่มีใคร", + "lists.replies_policy.title": "à¹à¸ªà¸”งà¸à¸²à¸£à¸•à¸à¸šà¸à¸¥à¸±à¸šà¹à¸à¹ˆ:", "lists.search": "ค้นหาในหมู่ผู้คนที่คุณติดตาม", "lists.subheading": "รายà¸à¸²à¸£à¸‚à¸à¸‡à¸„ุณ", "load_pending": "{count, plural, other {# รายà¸à¸²à¸£à¹ƒà¸«à¸¡à¹ˆ}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "ซ่à¸à¸™ {number, plural, other {ภาพ}}", "missing_indicator.label": "ไม่พบ", "missing_indicator.sublabel": "ไม่พบทรัพยาà¸à¸£à¸™à¸µà¹‰", + "mute_modal.duration": "ระยะเวลา", "mute_modal.hide_notifications": "ซ่à¸à¸™à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸ˆà¸²à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸™à¸µà¹‰?", + "mute_modal.indefinite": "ไม่มีà¸à¸³à¸«à¸™à¸”", "navigation_bar.apps": "à¹à¸à¸›à¸¡à¸·à¸à¸–ืà¸", "navigation_bar.blocks": "ผู้ใช้ที่ปิดà¸à¸±à¹‰à¸™à¸à¸¢à¸¹à¹ˆ", "navigation_bar.bookmarks": "ที่คั่นหน้า", @@ -298,6 +310,7 @@ "notification.own_poll": "à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นขà¸à¸‡à¸„ุณได้สิ้นสุดà¹à¸¥à¹‰à¸§", "notification.poll": "à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นที่คุณได้ลงคะà¹à¸™à¸™à¹„ด้สิ้นสุดà¹à¸¥à¹‰à¸§", "notification.reblog": "{name} ได้ดันโพสต์ขà¸à¸‡à¸„ุณ", + "notification.status": "{name} เพิ่งโพสต์", "notifications.clear": "ล้างà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™", "notifications.clear_confirmation": "คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸à¹„ม่ว่าต้à¸à¸‡à¸à¸²à¸£à¸¥à¹‰à¸²à¸‡à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸—ั้งหมดขà¸à¸‡à¸„ุณà¸à¸¢à¹ˆà¸²à¸‡à¸–าวร?", "notifications.column_settings.alert": "à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸šà¸™à¹€à¸”สà¸à¹Œà¸—็à¸à¸›", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "à¸à¸²à¸£à¸”ัน:", "notifications.column_settings.show": "à¹à¸ªà¸”งในคà¸à¸¥à¸±à¸¡à¸™à¹Œ", "notifications.column_settings.sound": "เล่นเสียง", + "notifications.column_settings.status": "โพสต์ใหม่:", "notifications.filter.all": "ทั้งหมด", "notifications.filter.boosts": "à¸à¸²à¸£à¸”ัน", "notifications.filter.favourites": "รายà¸à¸²à¸£à¹‚ปรด", "notifications.filter.follows": "à¸à¸²à¸£à¸•ิดตาม", "notifications.filter.mentions": "à¸à¸²à¸£à¸à¸¥à¹ˆà¸²à¸§à¸–ึง", "notifications.filter.polls": "ผลลัพธ์à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็น", + "notifications.filter.statuses": "à¸à¸²à¸£à¸à¸±à¸›à¹€à¸”ตจาà¸à¸œà¸¹à¹‰à¸„นที่คุณติดตาม", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™", + "notifications.mark_as_read": "ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸—ุà¸à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸§à¹ˆà¸²à¸à¹ˆà¸²à¸™à¹à¸¥à¹‰à¸§", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "เปิดใช้งานà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸šà¸™à¹€à¸”สà¸à¹Œà¸—็à¸à¸›", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "ไม่พลาดสิ่งต่าง ๆ", + "picture_in_picture.restore": "นำà¸à¸¥à¸±à¸šà¸¡à¸²", "poll.closed": "ปิดà¹à¸¥à¹‰à¸§", "poll.refresh": "รีเฟรช", "poll.total_people": "{count, plural, other {# คน}}", @@ -348,8 +372,8 @@ "relative_time.today": "วันนี้", "reply_indicator.cancel": "ยà¸à¹€à¸¥à¸´à¸", "report.forward": "ส่งต่à¸à¹„ปยัง {target}", - "report.forward_hint": "บัà¸à¸Šà¸µà¸¡à¸²à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸à¸·à¹ˆà¸™ ต้à¸à¸‡à¸à¸²à¸£à¸ªà¹ˆà¸‡à¸ªà¸³à¹€à¸™à¸²à¸‚à¸à¸‡à¸£à¸²à¸¢à¸‡à¸²à¸™à¸—ี่ไม่ระบุตัวตนไปที่เซิร์ฟเวà¸à¸£à¹Œà¸™à¸±à¹‰à¸™à¸”้วยหรืà¸à¹„ม่?", - "report.hint": "รายงานนี้จะถูà¸à¸ªà¹ˆà¸‡à¹„ปยังผู้ควบคุมเซิร์ฟเวà¸à¸£à¹Œà¸‚à¸à¸‡à¸„ุณ คุณสามารถà¸à¸˜à¸´à¸šà¸²à¸¢à¹€à¸«à¸•ุผลที่คุณรายงานบัà¸à¸Šà¸µà¸™à¸µà¹‰à¸”้านล่าง:", + "report.forward_hint": "บัà¸à¸Šà¸µà¸¡à¸²à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸à¸·à¹ˆà¸™ ส่งสำเนาขà¸à¸‡à¸£à¸²à¸¢à¸‡à¸²à¸™à¸—ี่ไม่ระบุตัวตนไปที่นั่นด้วย?", + "report.hint": "จะส่งรายงานไปยังผู้ควบคุมเซิร์ฟเวà¸à¸£à¹Œà¸‚à¸à¸‡à¸„ุณ คุณสามารถให้คำà¸à¸˜à¸´à¸šà¸²à¸¢à¹€à¸«à¸•ุผลที่คุณรายงานบัà¸à¸Šà¸µà¸™à¸µà¹‰à¸”้านล่าง:", "report.placeholder": "ความคิดเห็นเพิ่มเติม", "report.submit": "ส่ง", "report.target": "à¸à¸³à¸¥à¸±à¸‡à¸£à¸²à¸¢à¸‡à¸²à¸™ {target}", @@ -389,7 +413,7 @@ "status.pinned": "โพสต์ที่ปัà¸à¸«à¸¡à¸¸à¸”", "status.read_more": "à¸à¹ˆà¸²à¸™à¹€à¸žà¸´à¹ˆà¸¡à¹€à¸•ิม", "status.reblog": "ดัน", - "status.reblog_private": "ดันไปยังผู้ชมดั้งเดิม", + "status.reblog_private": "ดันด้วยà¸à¸²à¸£à¸¡à¸à¸‡à¹€à¸«à¹‡à¸™à¸”ั้งเดิม", "status.reblogged_by": "{name} ได้ดัน", "status.reblogs.empty": "ยังไม่มีใครดันโพสต์นี้ เมื่à¸à¹ƒà¸„รสัà¸à¸„นดัน เขาจะปราà¸à¸à¸—ี่นี่", "status.redraft": "ลบà¹à¸¥à¹‰à¸§à¸£à¹ˆà¸²à¸‡à¹ƒà¸«à¸¡à¹ˆ", @@ -407,7 +431,7 @@ "status.uncached_media_warning": "ไม่พร้à¸à¸¡à¹ƒà¸Šà¹‰à¸‡à¸²à¸™", "status.unmute_conversation": "เลิà¸à¸‹à¹ˆà¸à¸™à¸à¸²à¸£à¸ªà¸™à¸—นา", "status.unpin": "ถà¸à¸™à¸«à¸¡à¸¸à¸”จาà¸à¹‚ปรไฟล์", - "suggestions.dismiss": "ปิดข้à¸à¹€à¸ªà¸™à¸à¹à¸™à¸°", + "suggestions.dismiss": "ยà¸à¹€à¸¥à¸´à¸à¸‚้à¸à¹€à¸ªà¸™à¸à¹à¸™à¸°", "suggestions.header": "คุณà¸à¸²à¸ˆà¸ªà¸™à¹ƒà¸ˆâ€¦", "tabs_bar.federated_timeline": "ที่ติดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸", "tabs_bar.home": "หน้าà¹à¸£à¸", @@ -423,29 +447,30 @@ "timeline_hint.resources.followers": "ผู้ติดตาม", "timeline_hint.resources.follows": "à¸à¸²à¸£à¸•ิดตาม", "timeline_hint.resources.statuses": "โพสต์ที่เà¸à¹ˆà¸²à¸à¸§à¹ˆà¸²", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, other {{counter} คน}}à¸à¸³à¸¥à¸±à¸‡à¸žà¸¹à¸”คุย", "trends.trending_now": "à¸à¸³à¸¥à¸±à¸‡à¸™à¸´à¸¢à¸¡", "ui.beforeunload": "à¹à¸šà¸šà¸£à¹ˆà¸²à¸‡à¸‚à¸à¸‡à¸„ุณจะหายไปหาà¸à¸„ุณà¸à¸à¸à¸ˆà¸²à¸ Mastodon", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count} พันล้าน", + "units.short.million": "{count} ล้าน", + "units.short.thousand": "{count} พัน", "upload_area.title": "ลาà¸à¹à¸¥à¹‰à¸§à¸›à¸¥à¹ˆà¸à¸¢à¹€à¸žà¸·à¹ˆà¸à¸à¸±à¸›à¹‚หลด", - "upload_button.label": "เพิ่มไฟล์ภาพ วิดีโภหรืà¸à¹€à¸ªà¸µà¸¢à¸‡", + "upload_button.label": "เพิ่มไฟล์ภาพ, วิดีโภหรืà¸à¹€à¸ªà¸µà¸¢à¸‡", "upload_error.limit": "เà¸à¸´à¸™à¸‚ีดจำà¸à¸±à¸”à¸à¸²à¸£à¸à¸±à¸›à¹‚หลดไฟล์", - "upload_error.poll": "ไม่à¸à¸™à¸¸à¸à¸²à¸•ให้à¸à¸±à¸›à¹‚หลดไฟล์พร้à¸à¸¡à¹‚พล", + "upload_error.poll": "ไม่à¸à¸™à¸¸à¸à¸²à¸•ให้à¸à¸±à¸›à¹‚หลดไฟล์à¸à¸±à¸šà¸à¸²à¸£à¸¥à¸‡à¸„ะà¹à¸™à¸™", "upload_form.audio_description": "à¸à¸˜à¸´à¸šà¸²à¸¢à¸ªà¸³à¸«à¸£à¸±à¸šà¸œà¸¹à¹‰à¸ªà¸¹à¸à¹€à¸ªà¸µà¸¢à¸à¸²à¸£à¹„ด้ยิน", "upload_form.description": "à¸à¸˜à¸´à¸šà¸²à¸¢à¸ªà¸³à¸«à¸£à¸±à¸šà¸œà¸¹à¹‰à¸šà¸à¸žà¸£à¹ˆà¸à¸‡à¸—างà¸à¸²à¸£à¸¡à¸à¸‡à¹€à¸«à¹‡à¸™", "upload_form.edit": "à¹à¸à¹‰à¹„ข", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "เปลี่ยนภาพขนาดย่à¸", "upload_form.undo": "ลบ", "upload_form.video_description": "à¸à¸˜à¸´à¸šà¸²à¸¢à¸ªà¸³à¸«à¸£à¸±à¸šà¸œà¸¹à¹‰à¸ªà¸¹à¸à¹€à¸ªà¸µà¸¢à¸à¸²à¸£à¹„ด้ยินหรืà¸à¸šà¸à¸žà¸£à¹ˆà¸à¸‡à¸—างà¸à¸²à¸£à¸¡à¸à¸‡à¹€à¸«à¹‡à¸™", "upload_modal.analyzing_picture": "à¸à¸³à¸¥à¸±à¸‡à¸§à¸´à¹€à¸„ราะห์รูปภาพ…", "upload_modal.apply": "นำไปใช้", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "เลืà¸à¸à¸ าพ", "upload_modal.description_placeholder": "สุนัขจิ้งจà¸à¸à¸ªà¸µà¸™à¹‰à¸³à¸•าลที่ว่à¸à¸‡à¹„วà¸à¸£à¸°à¹‚ดดข้ามสุนัขขี้เà¸à¸µà¸¢à¸ˆ", "upload_modal.detect_text": "ตรวจหาข้à¸à¸„วามจาà¸à¸£à¸¹à¸›à¸ าพ", "upload_modal.edit_media": "à¹à¸à¹‰à¹„ขสื่à¸", "upload_modal.hint": "คลิà¸à¸«à¸£à¸·à¸à¸¥à¸²à¸à¸§à¸‡à¸à¸¥à¸¡à¹ƒà¸™à¸•ัวà¸à¸¢à¹ˆà¸²à¸‡à¹€à¸žà¸·à¹ˆà¸à¹€à¸¥à¸·à¸à¸à¸ˆà¸¸à¸”โฟà¸à¸±à¸ª ซึ่งจะà¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸¡à¸¸à¸¡à¸¡à¸à¸‡à¸‚à¸à¸‡à¸ าพขนาดย่à¸à¸—ั้งหมดเสมà¸", + "upload_modal.preparing_ocr": "à¸à¸³à¸¥à¸±à¸‡à¹€à¸•รียม OCR…", "upload_modal.preview_label": "ตัวà¸à¸¢à¹ˆà¸²à¸‡ ({ratio})", "upload_progress.label": "à¸à¸³à¸¥à¸±à¸‡à¸à¸±à¸›à¹‚หลด...", "video.close": "ปิดวิดีโà¸", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 351e80f8119d67089131940d36ef26b42efea0ee..1d56d169cdbccceead61d7887be3288bbc46cd6f 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -1,30 +1,32 @@ { - "account.account_note_header": "@{name} için notunuz", + "account.account_note_header": "Not", "account.add_or_remove_from_list": "Listelere ekle veya kaldır", "account.badges.bot": "Bot", "account.badges.group": "Grup", "account.block": "@{name} adlı kiÅŸiyi engelle", - "account.block_domain": "{domain} alanından her ÅŸeyi gizle", - "account.blocked": "EngellenmiÅŸ", + "account.block_domain": "{domain} alan adını engelle", + "account.blocked": "Engellendi", "account.browse_more_on_origin_server": "Orijinal profilde daha fazlasına göz atın", "account.cancel_follow_request": "Takip isteÄŸini iptal et", - "account.direct": "Mesaj gönder @{name}", - "account.domain_blocked": "Alan adı gizlendi", + "account.direct": "@{name} adlı kiÅŸiye mesaj gönder", + "account.disable_notifications": "@{name} gönderi yaptığında bana bildirmeyi durdur", + "account.domain_blocked": "Alan adı engellendi", "account.edit_profile": "Profili düzenle", + "account.enable_notifications": "@{name} gönderi yaptığında bana bildir", "account.endorse": "Profildeki özellik", "account.follow": "Takip et", "account.followers": "Takipçi", "account.followers.empty": "Henüz kimse bu kullanıcıyı takip etmiyor.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} Takipçi} other {{counter} Takipçi}}", + "account.following_counter": "{count, plural, one {{counter} Takip Edilen} other {{counter} Takip Edilen}}", "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.", "account.follows_you": "Seni takip ediyor", - "account.hide_reblogs": "@{name} kiÅŸisinin yinelemelerini gizle", - "account.last_status": "Son aktivite", + "account.hide_reblogs": "@{name} kiÅŸisinin boostlarını gizle", + "account.last_status": "Son etkinlik", "account.link_verified_on": "Bu baÄŸlantının sahipliÄŸi {date} tarihinde kontrol edildi", "account.locked_info": "Bu hesabın gizlilik durumu kilitli olarak ayarlanmış. Sahibi, onu kimin takip edebileceÄŸini elle inceliyor.", "account.media": "Medya", - "account.mention": "@{name} kullanıcısından bahset", + "account.mention": "@{name} kiÅŸisinden bahset", "account.moved_to": "{name} ÅŸuraya taşındı:", "account.mute": "@{name} adlı kiÅŸiyi sessize al", "account.mute_notifications": "@{name} adlı kiÅŸinin bildirimlerini kapat", @@ -33,18 +35,18 @@ "account.posts": "Toot", "account.posts_with_replies": "Tootlar ve cevaplar", "account.report": "@{name} adlı kiÅŸiyi bildir", - "account.requested": "Onay Bekleniyor. Takip isteÄŸini iptal etmek için tıklayın", - "account.share": "@{name} kullanıcısının profilini paylaÅŸ", - "account.show_reblogs": "@{name} kullanıcısının yinelemelerini göster", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.requested": "Onay bekleniyor. Takip isteÄŸini iptal etmek için tıklayın", + "account.share": "@{name} adlı kiÅŸinin profilini paylaÅŸ", + "account.show_reblogs": "@{name} kiÅŸisinin boostlarını göster", + "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toot}}", "account.unblock": "@{name} adlı kiÅŸinin engelini kaldır", - "account.unblock_domain": "{domain} göster", - "account.unendorse": "Profilde özellik yok", + "account.unblock_domain": "{domain} alan adının engelini kaldır", + "account.unendorse": "Profilde gösterme", "account.unfollow": "Takibi bırak", "account.unmute": "@{name} adlı kiÅŸinin sesini aç", "account.unmute_notifications": "@{name} adlı kiÅŸinin bildirimlerini aç", - "account_note.placeholder": "Yorum yapılmamış", - "alert.rate_limited.message": "Lütfen sonra tekrar deneyin {retry_time, time, medium}.", + "account_note.placeholder": "Not eklemek için tıklayın", + "alert.rate_limited.message": "Lütfen {retry_time, time, medium} süresinden sonra tekrar deneyin.", "alert.rate_limited.title": "Oran sınırlıdır", "alert.unexpected.message": "Beklenmedik bir hata oluÅŸtu.", "alert.unexpected.title": "Hay aksi!", @@ -58,16 +60,16 @@ "bundle_modal_error.message": "Bu bileÅŸen yüklenirken bir ÅŸeyler ters gitti.", "bundle_modal_error.retry": "Tekrar deneyin", "column.blocks": "Engellenen kullanıcılar", - "column.bookmarks": "Yer imleri", + "column.bookmarks": "Yer İmleri", "column.community": "Yerel zaman tüneli", - "column.direct": "DoÄŸrudan mesajlar", + "column.direct": "Direkt Mesajlar", "column.directory": "Profillere göz at", - "column.domain_blocks": "Gizli alan adları", + "column.domain_blocks": "Engellenen alan adları", "column.favourites": "Favoriler", "column.follow_requests": "Takip istekleri", - "column.home": "Anasayfa", + "column.home": "Ana Sayfa", "column.lists": "Listeler", - "column.mutes": "SusturulmuÅŸ kullanıcılar", + "column.mutes": "Sessize alınmış kullanıcılar", "column.notifications": "Bildirimler", "column.pins": "SabitlenmiÅŸ tootlar", "column.public": "Federe zaman tüneli", @@ -87,45 +89,45 @@ "compose_form.hashtag_warning": "Bu toot liste dışı olduÄŸu için hiç bir etikette yer almayacak. Sadece herkese açık tootlar etiketlerde bulunabilir.", "compose_form.lock_disclaimer": "Hesabınız {locked} deÄŸil. Sadece takipçilerle paylaÅŸtığınız gönderileri görebilmek için sizi herhangi bir kullanıcı takip edebilir.", "compose_form.lock_disclaimer.lock": "kilitli", - "compose_form.placeholder": "Aklınızdan ne geçiyor?", + "compose_form.placeholder": "Aklında ne var?", "compose_form.poll.add_option": "Bir seçenek ekleyin", "compose_form.poll.duration": "Anket süresi", - "compose_form.poll.option_placeholder": "Seçim {number}", - "compose_form.poll.remove_option": "Bu seçimi kaldır", + "compose_form.poll.option_placeholder": "{number}.seçenek", + "compose_form.poll.remove_option": "Bu seçeneÄŸi kaldır", "compose_form.poll.switch_to_multiple": "Birden çok seçeneÄŸe izin vermek için anketi deÄŸiÅŸtir", "compose_form.poll.switch_to_single": "Tek bir seçeneÄŸe izin vermek için anketi deÄŸiÅŸtir", "compose_form.publish": "Tootla", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Medyayı hassas olarak iÅŸaretle", - "compose_form.sensitive.marked": "Medya hassas olarak iÅŸaretlendi", - "compose_form.sensitive.unmarked": "Medya hassas olarak iÅŸaretlenmemiÅŸ", + "compose_form.sensitive.hide": "{count, plural, one {Medyayı hassas olarak iÅŸaretle} other {Medyayı hassas olarak iÅŸaretle}}", + "compose_form.sensitive.marked": "{count, plural, one {Medya hassas olarak iÅŸaretlendi} other {Medya hassas olarak iÅŸaretlendi}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Medya hassas olarak iÅŸaretlenmemiÅŸ} other {Medya hassas olarak iÅŸaretlenmemiÅŸ}}", "compose_form.spoiler.marked": "Metin uyarının arkasına gizlenir", "compose_form.spoiler.unmarked": "Metin gizli deÄŸil", - "compose_form.spoiler_placeholder": "İçerik uyarısı", + "compose_form.spoiler_placeholder": "Uyarınızı buraya yazın", "confirmation_modal.cancel": "İptal", - "confirmations.block.block_and_report": "Engelle & Bildir", + "confirmations.block.block_and_report": "Engelle ve Bildir", "confirmations.block.confirm": "Engelle", - "confirmations.block.message": "{name} kullanıcısını engellemek istiyor musunuz?", + "confirmations.block.message": "{name} adlı kullanıcıyı engellemek istediÄŸinizden emin misiniz?", "confirmations.delete.confirm": "Sil", - "confirmations.delete.message": "Bu gönderiyi silmek istiyor musunuz?", + "confirmations.delete.message": "Bu tootu silmek istediÄŸinizden emin misiniz?", "confirmations.delete_list.confirm": "Sil", "confirmations.delete_list.message": "Bu listeyi kalıcı olarak silmek istediÄŸinize emin misiniz?", - "confirmations.domain_block.confirm": "Alan adının tamamını gizle", + "confirmations.domain_block.confirm": "Alanın tamamını engelle", "confirmations.domain_block.message": "tüm {domain} alan adını engellemek istediÄŸinizden emin misiniz? Genellikle birkaç hedefli engel ve susturma iÅŸi görür ve tercih edilir.", - "confirmations.logout.confirm": "Çıkış Yap", - "confirmations.logout.message": "Çıkış yapmak istediÄŸinize emin misiniz?", + "confirmations.logout.confirm": "Oturumu kapat", + "confirmations.logout.message": "Oturumu kapatmak istediÄŸinizden emin misiniz?", "confirmations.mute.confirm": "Sessize al", "confirmations.mute.explanation": "Bu onlardan gelen ve onlardan bahseden gönderileri gizleyecek, fakat yine de onların gönderilerinizi görmelerine ve sizi takip etmelerine izin verecektir.", - "confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?", - "confirmations.redraft.confirm": "Sil ve yeniden tasarla", - "confirmations.redraft.message": "Bu durumu silip tekrar taslaklaÅŸtırmak istediÄŸinizden emin misiniz? Tüm cevapları, boostları ve favorileri kaybedeceksiniz.", + "confirmations.mute.message": "{name} kullanıcısını sessize almak istediÄŸinizden emin misiniz?", + "confirmations.redraft.confirm": "Sil ve yeniden taslak yap", + "confirmations.redraft.message": "Bu toot'u silmek ve yeniden taslak yapmak istediÄŸinizden emin misiniz? Favoriler, boostlar kaybolacak ve orijinal gönderiye verilen yanıtlar sahipsiz kalacak.", "confirmations.reply.confirm": "Yanıtla", "confirmations.reply.message": "Åžimdi yanıtlarken o an oluÅŸturduÄŸunuz mesajın üzerine yazılır. Devam etmek istediÄŸinize emin misiniz?", - "confirmations.unfollow.confirm": "Takibi kaldır", - "confirmations.unfollow.message": "{name}'yi takipten çıkarmak istediÄŸinizden emin misiniz?", - "conversation.delete": "KonuÅŸmayı sil", - "conversation.mark_as_read": "OkunmuÅŸ olarak iÅŸaretle", - "conversation.open": "KonuÅŸmayı görüntüle", + "confirmations.unfollow.confirm": "Takibi bırak", + "confirmations.unfollow.message": "{name} adlı kullanıcıyı takibi bırakmak istediÄŸinizden emin misiniz?", + "conversation.delete": "Sohbeti sil", + "conversation.mark_as_read": "Okundu olarak iÅŸaretle", + "conversation.open": "Sohbeti görüntüle", "conversation.with": "{names} ile", "directory.federated": "Bilinen fediverse'lerden", "directory.local": "Yalnızca {domain} adresinden", @@ -137,7 +139,7 @@ "emoji_button.custom": "Özel", "emoji_button.flags": "Bayraklar", "emoji_button.food": "Yiyecek ve İçecek", - "emoji_button.label": "Emoji ekle", + "emoji_button.label": "İfade ekle", "emoji_button.nature": "DoÄŸa", "emoji_button.not_found": "İfade yok!! (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "Nesneler", @@ -147,52 +149,55 @@ "emoji_button.search_results": "Arama sonuçları", "emoji_button.symbols": "Semboller", "emoji_button.travel": "Seyahat ve Yerler", + "empty_column.account_suspended": "Hesap askıya alındı", "empty_column.account_timeline": "Burada hiç toot yok!", "empty_column.account_unavailable": "Profil kullanılamıyor", "empty_column.blocks": "Henüz bir kullanıcıyı engellemediniz.", - "empty_column.bookmarked_statuses": "Hiç iÅŸaretlediÄŸiniz tootunuz yok. Bir tane olduÄŸunda burada görünecek.", + "empty_column.bookmarked_statuses": "Henüz yer imine eklediÄŸiniz toot yok. Yer imine eklendiÄŸinde burada görünecek.", "empty_column.community": "Yerel zaman çizelgesi boÅŸ. Daha fazla eÄŸlence için herkese açık bir gönderi paylaşın!", - "empty_column.direct": "Henüz doÄŸrudan mesajınız yok. Bir tane gönderdiÄŸinizde veya aldığınızda burada görünecektir.", + "empty_column.direct": "Henüz direkt mesajınız yok. Bir tane gönderdiÄŸinizde veya aldığınızda burada görünecektir.", "empty_column.domain_blocks": "Henüz hiçbir gizli alan adı yok.", - "empty_column.favourited_statuses": "Hiç favori tootunuz yok. Bir tane olduÄŸunda burada görünecek.", + "empty_column.favourited_statuses": "Hiç favori tootunuz yok. Favori olduÄŸunda burada görünecek.", "empty_column.favourites": "Kimse bu tootu favorilerine eklememiÅŸ. Biri eklediÄŸinde burada görünecek.", "empty_column.follow_requests": "Hiç takip isteÄŸiniz yok. Bir tane aldığınızda burada görünecek.", "empty_column.hashtag": "Henüz bu hashtag’e sahip hiçbir gönderi yok.", "empty_column.home": "Henüz kimseyi takip etmiyorsunuz. {public} ziyaret edebilir veya arama kısmını kullanarak diÄŸer kullanıcılarla iletiÅŸime geçebilirsiniz.", "empty_column.home.public_timeline": "herkese açık zaman tüneli", "empty_column.list": "Bu listede henüz hiçbir ÅŸey yok.", - "empty_column.lists": "Henüz hiç listeniz yok. Bir tane oluÅŸturduÄŸunuzda burada görünecek.", - "empty_column.mutes": "Henüz hiçbir kullanıcıyı sessize almadınız.", - "empty_column.notifications": "Henüz hiçbir bildiriminiz yok. DiÄŸer insanlarla sobhet edebilmek için etkileÅŸime geçebilirsiniz.", + "empty_column.lists": "Henüz listeniz yok. Liste oluÅŸturduÄŸunuzda burada görünecek.", + "empty_column.mutes": "Henüz bir kullanıcıyı sessize almadınız.", + "empty_column.notifications": "Henüz bildiriminiz yok. Sohbete baÅŸlamak için baÅŸkalarıyla etkileÅŸim kurun.", "empty_column.public": "Burada hiçbir ÅŸey yok! Herkese açık bir ÅŸeyler yazın veya burayı doldurmak için diÄŸer sunuculardaki kullanıcıları takip edin", "error.unexpected_crash.explanation": "Bizim kodumuzdaki bir hatadan ya da tarayıcı uyumluluk sorunundan dolayı, bu sayfa düzgün görüntülenemedi.", + "error.unexpected_crash.explanation_addons": "Bu sayfa doÄŸru görüntülenemedi. Bu hata büyük olasılıkla bir tarayıcı eklentisinden veya otomatik çeviri araçlarından kaynaklanır.", "error.unexpected_crash.next_steps": "Sayfayı yenilemeyi deneyin. EÄŸer bu yardımcı olmazsa, Mastodon'u farklı bir tarayıcı ya da yerel uygulama üzerinden kullanabilirsiniz.", + "error.unexpected_crash.next_steps_addons": "Bunları devre dışı bırakmayı ve sayfayı yenilemeyi deneyin. Bu yardımcı olmazsa, Mastodon'u baÅŸka bir tarayıcı veya yerel uygulama aracılığıyla kullanabilirsiniz.", "errors.unexpected_crash.copy_stacktrace": "Yığın izlemeyi (stacktrace) panoya kopyala", "errors.unexpected_crash.report_issue": "Sorun bildir", - "follow_request.authorize": "Yetkilendir", + "follow_request.authorize": "İzin Ver", "follow_request.reject": "Reddet", - "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "Hesabınız kilitli olmasa bile, {domain} personeli bu hesaplardan gelen takip isteklerini gözden geçirmek isteyebileceÄŸinizi düşündü.", + "generic.saved": "Kaydedildi", "getting_started.developers": "GeliÅŸtiriciler", - "getting_started.directory": "Profil dizini", + "getting_started.directory": "Profil Dizini", "getting_started.documentation": "Belgeler", - "getting_started.heading": "BaÅŸlangıç", - "getting_started.invite": "İnsanları davet edin", - "getting_started.open_source_notice": "Mastodon açık kaynaklı bir yazılımdır. Github {github}. {apps} üzerinden katkıda bulunabilir, hata raporlayabilirsiniz.", - "getting_started.security": "Güvenlik", - "getting_started.terms": "Hizmet koÅŸulları", + "getting_started.heading": "BaÅŸlarken", + "getting_started.invite": "İnsanları davet et", + "getting_started.open_source_notice": "Mastodon açık kaynaklı bir yazılımdır. GitHub'taki {github} üzerinden katkıda bulunabilir veya sorunları bildirebilirsiniz.", + "getting_started.security": "Hesap ayarları", + "getting_started.terms": "Kullanım ÅŸartları", "hashtag.column_header.tag_mode.all": "ve {additional}", "hashtag.column_header.tag_mode.any": "ya da {additional}", "hashtag.column_header.tag_mode.none": "{additional} olmadan", - "hashtag.column_settings.select.no_options_message": "Hiç öneri bulunamadı", - "hashtag.column_settings.select.placeholder": "Hashtagler girin…", + "hashtag.column_settings.select.no_options_message": "Öneri bulunamadı", + "hashtag.column_settings.select.placeholder": "Etiketler girin…", "hashtag.column_settings.tag_mode.all": "Bunların hepsi", - "hashtag.column_settings.tag_mode.any": "Bunların hiçbiri", + "hashtag.column_settings.tag_mode.any": "Herhangi biri", "hashtag.column_settings.tag_mode.none": "Bunların hiçbiri", "hashtag.column_settings.tag_toggle": "Bu sütundaki ek etiketleri içer", "home.column_settings.basic": "Temel", - "home.column_settings.show_reblogs": "Boost edilenleri göster", - "home.column_settings.show_replies": "Cevapları göster", + "home.column_settings.show_reblogs": "Boostları göster", + "home.column_settings.show_replies": "Yanıtları göster", "home.hide_announcements": "Duyuruları gizle", "home.show_announcements": "Duyuruları göster", "intervals.full.days": "{number, plural, one {# gün} other {# gün}}", @@ -201,22 +206,22 @@ "introduction.federation.action": "İleri", "introduction.federation.federated.headline": "BirleÅŸik", "introduction.federation.federated.text": "DiÄŸer dosya sunucularından gelen genel gönderiler, birleÅŸik zaman çizelgesinde görünecektir.", - "introduction.federation.home.headline": "Ana sayfa", + "introduction.federation.home.headline": "Ana Sayfa", "introduction.federation.home.text": "Takip ettiÄŸiniz kiÅŸilerin yayınları ana sayfada gösterilecek. Herhangi bir sunucudaki herkesi takip edebilirsiniz!", "introduction.federation.local.headline": "Yerel", "introduction.federation.local.text": "Aynı sunucudaki kiÅŸilerin gönderileri yerel zaman tünelinde gözükecektir.", - "introduction.interactions.action": "Öğreticiyi bitirin!", - "introduction.interactions.favourite.headline": "Favori", + "introduction.interactions.action": "Öğreticiyi bitir!", + "introduction.interactions.favourite.headline": "BeÄŸeni", "introduction.interactions.favourite.text": "Bir tootu favorilerinize alarak sonrası için saklayabilirsiniz ve yazara tootu beÄŸendiÄŸinizi söyleyebilirsiniz.", - "introduction.interactions.reblog.headline": "Yinele", - "introduction.interactions.reblog.text": "BaÅŸkalarının tootlarını yineleyerek onları kendi takipçilerinizle paylaÅŸabillirsiniz.", + "introduction.interactions.reblog.headline": "Boostla", + "introduction.interactions.reblog.text": "BaÅŸkalarının tootlarını boostlayarak onları kendi takipçilerinizle paylaÅŸabillirsiniz.", "introduction.interactions.reply.headline": "Yanıt", "introduction.interactions.reply.text": "BaÅŸkalarının ve kendinizin tootlarına cevap verebilirsiniz. Bu, onları bir konuÅŸmada zincirli bir ÅŸekilde gösterecektir.", - "introduction.welcome.action": "Hadi gidelim!", + "introduction.welcome.action": "Hadi baÅŸlayalım!", "introduction.welcome.headline": "İlk adımlar", "introduction.welcome.text": "Krallığa hoÅŸ geldiniz! Az sonra, geniÅŸ bir sunucu yelpazesinde mesaj gönderip arkadaÅŸlarınızla konuÅŸabileceksiniz. Ama bu sunucu, {domain}, özel (profilinizi barındırır, bu yüzden adresini hatırlayın).", "keyboard_shortcuts.back": "geriye gitmek için", - "keyboard_shortcuts.blocked": "engelli kullanıcılar listesini açmak için", + "keyboard_shortcuts.blocked": "engellenen kullanıcılar listesini açmak için", "keyboard_shortcuts.boost": "boostlamak için", "keyboard_shortcuts.column": "sütunlardan birindeki duruma odaklanmak için", "keyboard_shortcuts.compose": "yazma alanına odaklanmak için", @@ -224,102 +229,121 @@ "keyboard_shortcuts.direct": "direkt mesajlar sütununu açmak için", "keyboard_shortcuts.down": "listede aÅŸağıya inmek için", "keyboard_shortcuts.enter": "durumu açmak için", - "keyboard_shortcuts.favourite": "favorilere eklemek için", + "keyboard_shortcuts.favourite": "beÄŸenmek için", "keyboard_shortcuts.favourites": "favoriler listesini açmak için", "keyboard_shortcuts.federated": "federe edilmiÅŸ zaman tünelini açmak için", "keyboard_shortcuts.heading": "Klavye kısayolları", - "keyboard_shortcuts.home": "ana sayfa zaman çizelgesini açmak için", - "keyboard_shortcuts.hotkey": "KısatuÅŸ", + "keyboard_shortcuts.home": "anasayfa zaman çizelgesini açmak için", + "keyboard_shortcuts.hotkey": "Kısayol tuÅŸu", "keyboard_shortcuts.legend": "bu efsaneyi görüntülemek için", "keyboard_shortcuts.local": "yerel zaman tünelini açmak için", "keyboard_shortcuts.mention": "yazardan bahsetmek için", - "keyboard_shortcuts.muted": "susturulmuÅŸ kullanıcı listesini açmak için", + "keyboard_shortcuts.muted": "sessize alınmış kullanıcı listesini açmak için", "keyboard_shortcuts.my_profile": "profilinizi açmak için", "keyboard_shortcuts.notifications": "bildirimler sütununu açmak için", "keyboard_shortcuts.open_media": "medyayı açmak için", "keyboard_shortcuts.pinned": "sabitlenmiÅŸ tootların listesini açmak için", "keyboard_shortcuts.profile": "yazarın profilini açmak için", - "keyboard_shortcuts.reply": "cevaplamak için", + "keyboard_shortcuts.reply": "yanıtlamak için", "keyboard_shortcuts.requests": "takip istekleri listesini açmak için", "keyboard_shortcuts.search": "aramaya odaklanmak için", - "keyboard_shortcuts.spoilers": "to show/hide CW field", - "keyboard_shortcuts.start": "\"baÅŸlayın\" sütununu açmak için", + "keyboard_shortcuts.spoilers": "CW alanını göstermek/gizlemek için", + "keyboard_shortcuts.start": "\"baÅŸlarken\" sütununu açmak için", "keyboard_shortcuts.toggle_hidden": "CW'den önceki yazıyı göstermek/gizlemek için", "keyboard_shortcuts.toggle_sensitivity": "medyayı göstermek/gizlemek için", - "keyboard_shortcuts.toot": "yeni bir toot baÅŸlatmak için", + "keyboard_shortcuts.toot": "yepyeni bir toot baÅŸlatmak için", "keyboard_shortcuts.unfocus": "aramada bir gönderiye odaklanmamak için", "keyboard_shortcuts.up": "listede yukarıya çıkmak için", "lightbox.close": "Kapat", + "lightbox.compress": "Resim görüntüleme kutusunu sıkıştır", + "lightbox.expand": "Resim görüntüleme kutusunu geniÅŸlet", "lightbox.next": "Sonraki", - "lightbox.previous": "Önceli", - "lightbox.view_context": "İçeriÄŸi göster", + "lightbox.previous": "Önceki", "lists.account.add": "Listeye ekle", "lists.account.remove": "Listeden kaldır", "lists.delete": "Listeyi sil", - "lists.edit": "listeyi düzenle", + "lists.edit": "Listeleri düzenle", "lists.edit.submit": "BaÅŸlığı deÄŸiÅŸtir", "lists.new.create": "Liste ekle", "lists.new.title_placeholder": "Yeni liste baÅŸlığı", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Listenin üyeleri", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Yanıtları göster:", "lists.search": "Takip ettiÄŸiniz kiÅŸiler arasından arayın", "lists.subheading": "Listeleriniz", "load_pending": "{count, plural, one {# yeni öğe} other {# yeni öğe}}", "loading_indicator.label": "Yükleniyor...", - "media_gallery.toggle_visible": "Görünürlüğü deÄŸiÅŸtir", + "media_gallery.toggle_visible": "{number, plural, one {Resmi} other {Resimleri}} gizle", "missing_indicator.label": "Bulunamadı", "missing_indicator.sublabel": "Bu kaynak bulunamadı", + "mute_modal.duration": "Süre", "mute_modal.hide_notifications": "Bu kullanıcıdan bildirimler gizlensin mı?", + "mute_modal.indefinite": "Belirsiz", "navigation_bar.apps": "Mobil uygulamalar", "navigation_bar.blocks": "Engellenen kullanıcılar", - "navigation_bar.bookmarks": "Yer imleri", - "navigation_bar.community_timeline": "Yerel zaman tüneli", + "navigation_bar.bookmarks": "Yer İmleri", + "navigation_bar.community_timeline": "Yerel Zaman Tüneli", "navigation_bar.compose": "Yeni toot oluÅŸtur", "navigation_bar.direct": "Direkt Mesajlar", "navigation_bar.discover": "KeÅŸfet", - "navigation_bar.domain_blocks": "Gizli alan adları", + "navigation_bar.domain_blocks": "Engellenen alan adları", "navigation_bar.edit_profile": "Profili düzenle", "navigation_bar.favourites": "Favoriler", - "navigation_bar.filters": "SusturulmuÅŸ kelimeler", + "navigation_bar.filters": "Sessize alınmış kelimeler", "navigation_bar.follow_requests": "Takip istekleri", "navigation_bar.follows_and_followers": "Takip edilenler ve takipçiler", - "navigation_bar.info": "GeniÅŸletilmiÅŸ bilgi", + "navigation_bar.info": "Bu sunucu hakkında", "navigation_bar.keyboard_shortcuts": "Klavye kısayolları", "navigation_bar.lists": "Listeler", - "navigation_bar.logout": "Çıkış", + "navigation_bar.logout": "Oturumu kapat", "navigation_bar.mutes": "Sessize alınmış kullanıcılar", "navigation_bar.personal": "KiÅŸisel", "navigation_bar.pins": "SabitlenmiÅŸ tootlar", "navigation_bar.preferences": "Tercihler", "navigation_bar.public_timeline": "Federe zaman tüneli", "navigation_bar.security": "Güvenlik", - "notification.favourite": "{name} senin durumunu favorilere ekledi", - "notification.follow": "{name} seni takip ediyor", - "notification.follow_request": "{name} sizi takip etme isteÄŸi gönderdi", + "notification.favourite": "{name} tootunu beÄŸendi", + "notification.follow": "{name} seni takip etti", + "notification.follow_request": "{name} size takip isteÄŸi gönderdi", "notification.mention": "{name} senden bahsetti", "notification.own_poll": "Anketiniz sona erdi", - "notification.poll": "Oy verdiÄŸiniz bir anket bitti", - "notification.reblog": "{name} senin durumunu boost etti", + "notification.poll": "Oy verdiÄŸiniz bir anket sona erdi", + "notification.reblog": "{name} tootunu boostladı", + "notification.status": "{name} az önce gönderdi", "notifications.clear": "Bildirimleri temizle", "notifications.clear_confirmation": "Tüm bildirimlerinizi kalıcı olarak temizlemek ister misiniz?", "notifications.column_settings.alert": "Masaüstü bildirimleri", - "notifications.column_settings.favourite": "Favoriler:", - "notifications.column_settings.filter_bar.advanced": "Tüm kategorileri göster", + "notifications.column_settings.favourite": "BeÄŸeniler:", + "notifications.column_settings.filter_bar.advanced": "Tüm kategorileri görüntüle", "notifications.column_settings.filter_bar.category": "Hızlı filtre çubuÄŸu", "notifications.column_settings.filter_bar.show": "Göster", "notifications.column_settings.follow": "Yeni takipçiler:", "notifications.column_settings.follow_request": "Yeni takip istekleri:", - "notifications.column_settings.mention": "Bahsedilenler:", + "notifications.column_settings.mention": "Bahsetmeler:", "notifications.column_settings.poll": "Anket sonuçları:", - "notifications.column_settings.push": "Push bildirimleri", + "notifications.column_settings.push": "Anlık bildirimler", "notifications.column_settings.reblog": "Boostlar:", - "notifications.column_settings.show": "Bildirimlerde göster", + "notifications.column_settings.show": "Sütunda göster", "notifications.column_settings.sound": "Ses çal", + "notifications.column_settings.status": "Yeni tootlar:", "notifications.filter.all": "Tümü", "notifications.filter.boosts": "Boostlar", - "notifications.filter.favourites": "Favoriler", + "notifications.filter.favourites": "BeÄŸeniler", "notifications.filter.follows": "Takip edilenler", "notifications.filter.mentions": "Bahsetmeler", "notifications.filter.polls": "Anket sonuçları", + "notifications.filter.statuses": "Takip ettiÄŸiniz kiÅŸilerden gelen güncellemeler", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} bildirim", + "notifications.mark_as_read": "Her bildirimi okundu olarak iÅŸaretle", + "notifications.permission_denied": "Daha önce reddedilen tarayıcı izinleri isteÄŸi nedeniyle masaüstü bildirimleri kullanılamıyor", + "notifications.permission_denied_alert": "Tarayıcı izni daha önce reddedildiÄŸinden, masaüstü bildirimleri etkinleÅŸtirilemez", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Masaüstü bildirimlerini etkinleÅŸtir", + "notifications_permission_banner.how_to_control": "Mastodon açık olmadığında bildirim almak için masaüstü bildirimlerini etkinleÅŸtirin. EtkinleÅŸtirildikten sonra yukarıdaki {icon} düğmesini kullanarak hangi etkileÅŸim türlerinin masaüstü bildirimleri oluÅŸturduÄŸunu tam olarak kontrol edebilirsiniz.", + "notifications_permission_banner.title": "Hiçbir ÅŸeyi kaçırmayın", + "picture_in_picture.restore": "Onu geri koy", "poll.closed": "Kapandı", "poll.refresh": "Yenile", "poll.total_people": "{count, plural, one {# kiÅŸi} other {# kiÅŸi}}", @@ -327,90 +351,90 @@ "poll.vote": "Oy ver", "poll.voted": "Bu cevap için oy kullandınız", "poll_button.add_poll": "Bir anket ekleyin", - "poll_button.remove_poll": "Anket kaldır", - "privacy.change": "Gönderi gizliliÄŸini ayarla", - "privacy.direct.long": "Sadece bahsedilen kiÅŸilere gönder", + "poll_button.remove_poll": "Anketi kaldır", + "privacy.change": "Toot gizliliÄŸini ayarlayın", + "privacy.direct.long": "Sadece bahsedilen kullanıcılar için görünür", "privacy.direct.short": "Direkt", - "privacy.private.long": "Sadece takipçilerime gönder", + "privacy.private.long": "Sadece takipçiler için görünür", "privacy.private.short": "Sadece takipçiler", - "privacy.public.long": "Herkese açık zaman tüneline gönder", + "privacy.public.long": "Herkese görünür, herkese açık zaman çizelgelerinde gösterilir", "privacy.public.short": "Herkese açık", - "privacy.unlisted.long": "Herkese açık zaman tüneline gönderme", + "privacy.unlisted.long": "Herkese görünür, ancak genel zaman çizelgelerinde gösterilmez", "privacy.unlisted.short": "ListelenmemiÅŸ", "refresh": "Yenile", "regeneration_indicator.label": "Yükleniyor…", - "regeneration_indicator.sublabel": "Ev akışınız hazırlanıyor!", + "regeneration_indicator.sublabel": "Ana akışınız hazırlanıyor!", "relative_time.days": "{number}g", - "relative_time.hours": "{number}s", + "relative_time.hours": "{number}sa", "relative_time.just_now": "ÅŸimdi", "relative_time.minutes": "{number}dk", "relative_time.seconds": "{number}sn", "relative_time.today": "bugün", "reply_indicator.cancel": "İptal", - "report.forward": "Åžu kiÅŸiye ilet : {target}", - "report.forward_hint": "Bu hesap baÅŸka bir sunucudan. AnonimleÅŸtirilmiÅŸ bir rapor oraya da gönderilsin mi?", + "report.forward": "{target} ilet", + "report.forward_hint": "Hesap baÅŸka bir sunucudan. Raporun anonim bir kopyası da oraya gönderilsin mi?", "report.hint": "Bu rapor sunucu moderatörlerine gönderilecek. Bu hesabı neden bildirdiÄŸiniz hakkında bilgi verebirsiniz:", "report.placeholder": "Ek yorumlar", "report.submit": "Gönder", - "report.target": "Raporlama", + "report.target": "{target} Bildiriliyor", "search.placeholder": "Ara", - "search_popout.search_format": "GeliÅŸmiÅŸ arama formatı", - "search_popout.tips.full_text": "Basit metin yazdığınız, tercih ettiÄŸiniz, yinelediÄŸiniz veya bunlardan bahsettiÄŸiniz durumların yanı sıra kullanıcı adlarını, görünen adları ve hashtag'leri eÅŸleÅŸtiren durumları döndürür.", - "search_popout.tips.hashtag": "etiketler", - "search_popout.tips.status": "durum", + "search_popout.search_format": "GeliÅŸmiÅŸ arama biçimi", + "search_popout.tips.full_text": "Basit metin yazdığınız, tercih ettiÄŸiniz, boostladığınız veya bunlardan bahsettiÄŸiniz tootların yanı sıra kullanıcı adlarını, görünen adları ve hashtag'leri eÅŸleÅŸtiren tootları döndürür.", + "search_popout.tips.hashtag": "etiket", + "search_popout.tips.status": "toot", "search_popout.tips.text": "Basit metin, eÅŸleÅŸen görünen adları, kullanıcı adlarını ve hashtag'leri döndürür", "search_popout.tips.user": "kullanıcı", "search_results.accounts": "İnsanlar", - "search_results.hashtags": "Hashtagler", + "search_results.hashtags": "Etiketler", "search_results.statuses": "Tootlar", "search_results.statuses_fts_disabled": "Bu Mastodon sunucusunda toot içeriÄŸine göre arama etkin deÄŸil.", - "search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuçlar}}", + "search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuç}}", "status.admin_account": "@{name} için denetim arayüzünü açın", "status.admin_status": "Denetim arayüzünde bu durumu açın", - "status.block": "Engelle : @{name}", + "status.block": "@{name} adlı kiÅŸiyi engelle", "status.bookmark": "Yer imlerine ekle", - "status.cancel_reblog_private": "Boost'u geri al", + "status.cancel_reblog_private": "Boostu geri al", "status.cannot_reblog": "Bu gönderi boost edilemez", "status.copy": "BaÄŸlantı durumunu kopyala", "status.delete": "Sil", - "status.detailed_status": "Detaylı yazışma dökümü", - "status.direct": "@{name}'e gönder", + "status.detailed_status": "Ayrıntılı sohbet görünümü", + "status.direct": "@{name} adlı kiÅŸiye direkt mesaj", "status.embed": "Gömülü", - "status.favourite": "Favorilere ekle", + "status.favourite": "BeÄŸen", "status.filtered": "FiltrelenmiÅŸ", - "status.load_more": "Daha fazla", + "status.load_more": "Daha fazlasını yükle", "status.media_hidden": "Gizli görsel", - "status.mention": "Bahset : @{name}", + "status.mention": "@{name} kiÅŸisinden bahset", "status.more": "Daha fazla", - "status.mute": "Sustur : @{name}", - "status.mute_conversation": "Yazışmayı sustur", - "status.open": "Bu gönderiyi geniÅŸlet", + "status.mute": "@{name} kiÅŸisini sessize al", + "status.mute_conversation": "Sohbeti sessize al", + "status.open": "Bu tootu geniÅŸlet", "status.pin": "Profile sabitle", "status.pinned": "SabitlenmiÅŸ toot", - "status.read_more": "Daha dazla oku", + "status.read_more": "Devamını okuyun", "status.reblog": "Boostla", - "status.reblog_private": "Orjinal kitleye yinele", - "status.reblogged_by": "{name} boost etti", - "status.reblogs.empty": "Henüz kimse bu tootu yinelemedi. Biri yaptığında burada görünecek.", - "status.redraft": "Sil & tekrar taslakla", + "status.reblog_private": "Orijinal görünürlük ile boostla", + "status.reblogged_by": "{name} boostladı", + "status.reblogs.empty": "Henüz kimse bu tootu boostlamadı. Biri yaptığında burada görünecek.", + "status.redraft": "Sil ve yeniden taslak yap", "status.remove_bookmark": "Yer imini kaldır", - "status.reply": "Cevapla", - "status.replyAll": "Mesaj dizisini cevapla", - "status.report": "@{name}'i raporla", + "status.reply": "Yanıtla", + "status.replyAll": "Konuyu yanıtla", + "status.report": "@{name} adlı kiÅŸiyi bildir", "status.sensitive_warning": "Hassas içerik", "status.share": "PaylaÅŸ", "status.show_less": "Daha az göster", "status.show_less_all": "Hepsi için daha az göster", - "status.show_more": "Daha fazla göster", + "status.show_more": "Daha fazlasını göster", "status.show_more_all": "Hepsi için daha fazla göster", - "status.show_thread": "Mesaj dizisini göster", + "status.show_thread": "Konuyu göster", "status.uncached_media_warning": "Mevcut deÄŸil", - "status.unmute_conversation": "Sohbeti aç", + "status.unmute_conversation": "Sohbet sesini aç", "status.unpin": "Profilden sabitlemeyi kaldır", "suggestions.dismiss": "Öneriyi görmezden gel", "suggestions.header": "Åžuna ilgi duyuyor olabilirsiniz…", "tabs_bar.federated_timeline": "Federe", - "tabs_bar.home": "Ana sayfa", + "tabs_bar.home": "Ana Sayfa", "tabs_bar.local_timeline": "Yerel", "tabs_bar.notifications": "Bildirimler", "tabs_bar.search": "Ara", @@ -419,33 +443,34 @@ "time_remaining.minutes": "{number, plural, one {# dakika} other {# dakika}} kaldı", "time_remaining.moments": "Sadece birkaç dakika kaldı", "time_remaining.seconds": "{number, plural, one {# saniye} other {# saniye}} kaldı", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", + "timeline_hint.remote_resource_not_displayed": "diÄŸer sunucudaki {resource} gösterilemiyor.", "timeline_hint.resources.followers": "Takipçiler", "timeline_hint.resources.follows": "Takip Edilenler", "timeline_hint.resources.statuses": "Eski tootlar", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", - "trends.trending_now": "Åžu an popüler", - "ui.beforeunload": "Mastodon'dan ayrılırsanız taslağınız kaybolacak.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "trends.counter_by_accounts": "{count, plural, one {{counter} kiÅŸi} other {{counter} kiÅŸi}} konuÅŸuyor", + "trends.trending_now": "Åžu an gündemde", + "ui.beforeunload": "Mastodon'u terk ederseniz taslağınız kaybolacak.", + "units.short.billion": "{count}Mr", + "units.short.million": "{count}Mn", + "units.short.thousand": "{count}Mn", "upload_area.title": "Karşıya yükleme için sürükle bırak yapınız", - "upload_button.label": "Görsel ekle", + "upload_button.label": "Resim, video veya ses dosyası ekleyin", "upload_error.limit": "Dosya yükleme sınırı aşıldı.", "upload_error.poll": "Anketlerde dosya yüklemesine izin verilmez.", "upload_form.audio_description": "İşitme kaybı olan kiÅŸiler için tarif edin", "upload_form.description": "Görme engelliler için açıklama", "upload_form.edit": "Düzenle", - "upload_form.thumbnail": "Change thumbnail", - "upload_form.undo": "Geri al", + "upload_form.thumbnail": "Küçük resmi deÄŸiÅŸtir", + "upload_form.undo": "Sil", "upload_form.video_description": "İşitme kaybı veya görme engeli olan kiÅŸiler için tarif edin", - "upload_modal.analyzing_picture": "Resmi analiz ediyor…", + "upload_modal.analyzing_picture": "Resim analiz ediliyor…", "upload_modal.apply": "Uygula", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Resim seç", "upload_modal.description_placeholder": "Pijamalı hasta yağız ÅŸoföre çabucak güvendi", "upload_modal.detect_text": "Resimdeki metni algıla", "upload_modal.edit_media": "Medyayı düzenle", "upload_modal.hint": "Her zaman tüm küçük resimlerde görüntülenecek odak noktasını seçmek için ön izlemedeki daireyi tıklayın veya sürükleyin.", + "upload_modal.preparing_ocr": "OCR hazırlanıyor…", "upload_modal.preview_label": "Ön izleme ({ratio})", "upload_progress.label": "Yükleniyor...", "video.close": "Videoyu kapat", @@ -454,7 +479,7 @@ "video.expand": "Videoyu geniÅŸlet", "video.fullscreen": "Tam ekran", "video.hide": "Videoyu gizle", - "video.mute": "Sesi kıs", + "video.mute": "Sesi sustur", "video.pause": "Duraklat", "video.play": "Oynat", "video.unmute": "Sesi aç" diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json new file mode 100644 index 0000000000000000000000000000000000000000..224c51301448e390f1f25e2b2d01518107380f5e --- /dev/null +++ b/app/javascript/mastodon/locales/tt.json @@ -0,0 +1,486 @@ +{ + "account.account_note_header": "Язма", + "account.add_or_remove_from_list": "ИÑемлеккә кертү Ñ Ð±ÐµÑ‚ÐµÑ€Ò¯", + "account.badges.bot": "Бот", + "account.badges.group": "Төркем", + "account.block": "Block @{name}", + "account.block_domain": "Block domain {domain}", + "account.blocked": "Blocked", + "account.browse_more_on_origin_server": "Тулырак оригинал профилендә карап була", + "account.cancel_follow_request": "Cancel follow request", + "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", + "account.domain_blocked": "Domain blocked", + "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", + "account.endorse": "Feature on profile", + "account.follow": "Follow", + "account.followers": "Followers", + "account.followers.empty": "No one follows this user yet.", + "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.follows.empty": "This user doesn't follow anyone yet.", + "account.follows_you": "Follows you", + "account.hide_reblogs": "Hide boosts from @{name}", + "account.last_status": "Last active", + "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", + "account.media": "Media", + "account.mention": "Mention @{name}", + "account.moved_to": "{name} has moved to:", + "account.mute": "Mute @{name}", + "account.mute_notifications": "Mute notifications from @{name}", + "account.muted": "Muted", + "account.never_active": "Never", + "account.posts": "Toots", + "account.posts_with_replies": "Toots and replies", + "account.report": "Report @{name}", + "account.requested": "Awaiting approval", + "account.share": "Share @{name}'s profile", + "account.show_reblogs": "Show boosts from @{name}", + "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.unblock": "Unblock @{name}", + "account.unblock_domain": "Unblock domain {domain}", + "account.unendorse": "Don't feature on profile", + "account.unfollow": "Unfollow", + "account.unmute": "Unmute @{name}", + "account.unmute_notifications": "Unmute notifications from @{name}", + "account_note.placeholder": "Click to add a note", + "alert.rate_limited.message": "Please retry after {retry_time, time, medium}.", + "alert.rate_limited.title": "Rate limited", + "alert.unexpected.message": "An unexpected error occurred.", + "alert.unexpected.title": "Oops!", + "announcement.announcement": "Announcement", + "autosuggest_hashtag.per_week": "{count} per week", + "boost_modal.combo": "You can press {combo} to skip this next time", + "bundle_column_error.body": "Something went wrong while loading this component.", + "bundle_column_error.retry": "Try again", + "bundle_column_error.title": "Network error", + "bundle_modal_error.close": "Close", + "bundle_modal_error.message": "Something went wrong while loading this component.", + "bundle_modal_error.retry": "Try again", + "column.blocks": "Blocked users", + "column.bookmarks": "Bookmarks", + "column.community": "Local timeline", + "column.direct": "Direct messages", + "column.directory": "Browse profiles", + "column.domain_blocks": "Blocked domains", + "column.favourites": "Favourites", + "column.follow_requests": "Follow requests", + "column.home": "Home", + "column.lists": "Lists", + "column.mutes": "Muted users", + "column.notifications": "Notifications", + "column.pins": "Pinned toot", + "column.public": "Federated timeline", + "column_back_button.label": "Back", + "column_header.hide_settings": "Hide settings", + "column_header.moveLeft_settings": "Move column to the left", + "column_header.moveRight_settings": "Move column to the right", + "column_header.pin": "Pin", + "column_header.show_settings": "Show settings", + "column_header.unpin": "Unpin", + "column_subheading.settings": "Settings", + "community.column_settings.local_only": "Local only", + "community.column_settings.media_only": "Media only", + "community.column_settings.remote_only": "Remote only", + "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.", + "compose_form.direct_message_warning_learn_more": "Learn more", + "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", + "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", + "compose_form.lock_disclaimer.lock": "locked", + "compose_form.placeholder": "What is on your mind?", + "compose_form.poll.add_option": "Add a choice", + "compose_form.poll.duration": "Poll duration", + "compose_form.poll.option_placeholder": "Choice {number}", + "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.publish": "Toot", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", + "compose_form.spoiler.marked": "Text is hidden behind warning", + "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler_placeholder": "Write your warning here", + "confirmation_modal.cancel": "Cancel", + "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.confirm": "Block", + "confirmations.block.message": "Are you sure you want to block {name}?", + "confirmations.delete.confirm": "Delete", + "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.delete_list.confirm": "Delete", + "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.logout.confirm": "Log out", + "confirmations.logout.message": "Are you sure you want to log out?", + "confirmations.mute.confirm": "Mute", + "confirmations.mute.explanation": "This will hide posts from them and posts mentioning them, but it will still allow them to see your posts and follow you.", + "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.", + "confirmations.reply.confirm": "Reply", + "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "confirmations.unfollow.confirm": "Unfollow", + "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", + "conversation.delete": "Delete conversation", + "conversation.mark_as_read": "Mark as read", + "conversation.open": "View conversation", + "conversation.with": "With {names}", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", + "embed.instructions": "Embed this status on your website by copying the code below.", + "embed.preview": "Here is what it will look like:", + "emoji_button.activity": "Activity", + "emoji_button.custom": "Custom", + "emoji_button.flags": "Flags", + "emoji_button.food": "Food & Drink", + "emoji_button.label": "Insert emoji", + "emoji_button.nature": "Nature", + "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ â”»â”â”»", + "emoji_button.objects": "Objects", + "emoji_button.people": "People", + "emoji_button.recent": "Frequently used", + "emoji_button.search": "Search...", + "emoji_button.search_results": "Search results", + "emoji_button.symbols": "Symbols", + "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", + "empty_column.account_timeline": "No toots here!", + "empty_column.account_unavailable": "Profile unavailable", + "empty_column.blocks": "You haven't blocked any users yet.", + "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", + "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", + "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.domain_blocks": "There are no blocked domains yet.", + "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", + "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", + "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", + "empty_column.hashtag": "There is nothing in this hashtag yet.", + "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", + "empty_column.home.public_timeline": "the public timeline", + "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", + "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", + "empty_column.mutes": "You haven't muted any users yet.", + "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", + "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", + "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", + "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", + "errors.unexpected_crash.report_issue": "Report issue", + "follow_request.authorize": "Authorize", + "follow_request.reject": "Reject", + "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", + "generic.saved": "Saved", + "getting_started.developers": "Developers", + "getting_started.directory": "Profile directory", + "getting_started.documentation": "Documentation", + "getting_started.heading": "Getting started", + "getting_started.invite": "Invite people", + "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", + "getting_started.security": "Security", + "getting_started.terms": "Terms of service", + "hashtag.column_header.tag_mode.all": "and {additional}", + "hashtag.column_header.tag_mode.any": "or {additional}", + "hashtag.column_header.tag_mode.none": "without {additional}", + "hashtag.column_settings.select.no_options_message": "No suggestions found", + "hashtag.column_settings.select.placeholder": "Enter hashtags…", + "hashtag.column_settings.tag_mode.all": "All of these", + "hashtag.column_settings.tag_mode.any": "Any of these", + "hashtag.column_settings.tag_mode.none": "None of these", + "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "home.column_settings.basic": "Basic", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Show replies", + "home.hide_announcements": "Hide announcements", + "home.show_announcements": "Show announcements", + "intervals.full.days": "{number, plural, one {# day} other {# days}}", + "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "introduction.federation.action": "Next", + "introduction.federation.federated.headline": "Federated", + "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.home.headline": "Home", + "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", + "introduction.federation.local.headline": "Local", + "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", + "introduction.interactions.action": "Finish toot-orial!", + "introduction.interactions.favourite.headline": "Favourite", + "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", + "introduction.interactions.reblog.headline": "Boost", + "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", + "introduction.interactions.reply.headline": "Reply", + "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", + "introduction.welcome.action": "Let's go!", + "introduction.welcome.headline": "First steps", + "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "keyboard_shortcuts.back": "to navigate back", + "keyboard_shortcuts.blocked": "to open blocked users list", + "keyboard_shortcuts.boost": "to boost", + "keyboard_shortcuts.column": "to focus a status in one of the columns", + "keyboard_shortcuts.compose": "to focus the compose textarea", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.direct": "to open direct messages column", + "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.favourites": "to open favourites list", + "keyboard_shortcuts.federated": "to open federated timeline", + "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.local": "to open local timeline", + "keyboard_shortcuts.mention": "to mention author", + "keyboard_shortcuts.muted": "to open muted users list", + "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.notifications": "to open notifications column", + "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.pinned": "to open pinned toots list", + "keyboard_shortcuts.profile": "to open author's profile", + "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.search": "to focus search", + "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.start": "to open \"get started\" column", + "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", + "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.up": "to move up in the list", + "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "Next", + "lightbox.previous": "Previous", + "lists.account.add": "Add to list", + "lists.account.remove": "Remove from list", + "lists.delete": "Delete list", + "lists.edit": "Edit list", + "lists.edit.submit": "Change title", + "lists.new.create": "Add list", + "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", + "lists.search": "Search among people you follow", + "lists.subheading": "Your lists", + "load_pending": "{count, plural, one {# new item} other {# new items}}", + "loading_indicator.label": "Loading...", + "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", + "missing_indicator.label": "Not found", + "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", + "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", + "navigation_bar.apps": "Mobile apps", + "navigation_bar.blocks": "Blocked users", + "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.compose": "Compose new toot", + "navigation_bar.direct": "Direct messages", + "navigation_bar.discover": "Discover", + "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.favourites": "Favourites", + "navigation_bar.filters": "Muted words", + "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.follows_and_followers": "Follows and followers", + "navigation_bar.info": "About this server", + "navigation_bar.keyboard_shortcuts": "Hotkeys", + "navigation_bar.lists": "Lists", + "navigation_bar.logout": "Logout", + "navigation_bar.mutes": "Muted users", + "navigation_bar.personal": "Personal", + "navigation_bar.pins": "Pinned toots", + "navigation_bar.preferences": "Preferences", + "navigation_bar.public_timeline": "Federated timeline", + "navigation_bar.security": "Security", + "notification.favourite": "{name} favourited your status", + "notification.follow": "{name} followed you", + "notification.follow_request": "{name} has requested to follow you", + "notification.mention": "{name} mentioned you", + "notification.own_poll": "Your poll has ended", + "notification.poll": "A poll you have voted in has ended", + "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", + "notifications.clear": "Clear notifications", + "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.column_settings.alert": "Desktop notifications", + "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notifications.column_settings.filter_bar.category": "Quick filter bar", + "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.follow": "New followers:", + "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Show in column", + "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", + "notifications.filter.all": "All", + "notifications.filter.boosts": "Boosts", + "notifications.filter.favourites": "Favourites", + "notifications.filter.follows": "Follows", + "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", + "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", + "poll.closed": "Closed", + "poll.refresh": "Refresh", + "poll.total_people": "{count, plural, one {# person} other {# people}}", + "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", + "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll_button.add_poll": "Add a poll", + "poll_button.remove_poll": "Remove poll", + "privacy.change": "Adjust status privacy", + "privacy.direct.long": "Visible for mentioned users only", + "privacy.direct.short": "Direct", + "privacy.private.long": "Visible for followers only", + "privacy.private.short": "Followers-only", + "privacy.public.long": "Visible for all, shown in public timelines", + "privacy.public.short": "Public", + "privacy.unlisted.long": "Visible for all, but not in public timelines", + "privacy.unlisted.short": "Unlisted", + "refresh": "Refresh", + "regeneration_indicator.label": "Loading…", + "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "now", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "relative_time.today": "today", + "reply_indicator.cancel": "Cancel", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Additional comments", + "report.submit": "Submit", + "report.target": "Report {target}", + "search.placeholder": "Search", + "search_popout.search_format": "Advanced search format", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "search_popout.tips.status": "status", + "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", + "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", + "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "status.admin_account": "Open moderation interface for @{name}", + "status.admin_status": "Open this status in the moderation interface", + "status.block": "Block @{name}", + "status.bookmark": "Bookmark", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "This post cannot be boosted", + "status.copy": "Copy link to status", + "status.delete": "Delete", + "status.detailed_status": "Detailed conversation view", + "status.direct": "Direct message @{name}", + "status.embed": "Embed", + "status.favourite": "Favourite", + "status.filtered": "Filtered", + "status.load_more": "Load more", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "More", + "status.mute": "Mute @{name}", + "status.mute_conversation": "Mute conversation", + "status.open": "Expand this status", + "status.pin": "Pin on profile", + "status.pinned": "Pinned toot", + "status.read_more": "Read more", + "status.reblog": "Boost", + "status.reblog_private": "Boost with original visibility", + "status.reblogged_by": "{name} boosted", + "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", + "status.redraft": "Delete & re-draft", + "status.remove_bookmark": "Remove bookmark", + "status.reply": "Reply", + "status.replyAll": "Reply to thread", + "status.report": "Report @{name}", + "status.sensitive_warning": "Sensitive content", + "status.share": "Share", + "status.show_less": "Show less", + "status.show_less_all": "Show less for all", + "status.show_more": "Show more", + "status.show_more_all": "Show more for all", + "status.show_thread": "Show thread", + "status.uncached_media_warning": "Not available", + "status.unmute_conversation": "Unmute conversation", + "status.unpin": "Unpin from profile", + "suggestions.dismiss": "Dismiss suggestion", + "suggestions.header": "You might be interested in…", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "Home", + "tabs_bar.local_timeline": "Local", + "tabs_bar.notifications": "Notifications", + "tabs_bar.search": "Search", + "time_remaining.days": "{number, plural, one {# day} other {# days}} left", + "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", + "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", + "time_remaining.moments": "Moments remaining", + "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", + "timeline_hint.resources.followers": "Followers", + "timeline_hint.resources.follows": "Follows", + "timeline_hint.resources.statuses": "Older toots", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.trending_now": "Trending now", + "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "units.short.billion": "{count}B", + "units.short.million": "{count}M", + "units.short.thousand": "{count}K", + "upload_area.title": "Drag & drop to upload", + "upload_button.label": "Add images, a video or an audio file", + "upload_error.limit": "File upload limit exceeded.", + "upload_error.poll": "File upload not allowed with polls.", + "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.description": "Describe for the visually impaired", + "upload_form.edit": "Edit", + "upload_form.thumbnail": "Change thumbnail", + "upload_form.undo": "Delete", + "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_modal.analyzing_picture": "Analyzing picture…", + "upload_modal.apply": "Apply", + "upload_modal.choose_image": "Choose image", + "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", + "upload_modal.detect_text": "Detect text from picture", + "upload_modal.edit_media": "Edit media", + "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", + "upload_modal.preview_label": "Preview ({ratio})", + "upload_progress.label": "Uploading…", + "video.close": "Close video", + "video.download": "Download file", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound" +} diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json index e5d833fe87465898b1831bb4ceb749f69e1f8e65..70f6ab1529e76eb2ac320779468d4f934d169e1a 100644 --- a/app/javascript/mastodon/locales/ug.json +++ b/app/javascript/mastodon/locales/ug.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Domain blocked", "account.edit_profile": "Edit profile", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Feature on profile", "account.follow": "Follow", "account.followers": "Followers", @@ -96,9 +98,9 @@ "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No toots here!", "empty_column.account_unavailable": "Profile unavailable", "empty_column.blocks": "You haven't blocked any users yet.", @@ -166,7 +169,9 @@ "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Report issue", "follow_request.authorize": "Authorize", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 244f04a9e87f831c181e327bb3213a3559333d00..941e43c9995b790037f0ed6bb64237c7ff1d24dd 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "ПереглÑнути більше в оригіналі", "account.cancel_follow_request": "СкаÑувати запит на підпиÑку", "account.direct": "ПрÑме Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Домен приховано", "account.edit_profile": "Редагувати профіль", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "Публікувати у профілі", "account.follow": "ПідпиÑатиÑÑ", "account.followers": "ПідпиÑники", "account.followers.empty": "Ðіхто ще не підпиÑавÑÑ Ð½Ð° цього кориÑтувача.", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.followers_counter": "{count, plural, one {{counter} ПідпиÑник} few {{counter} ПідпиÑники} many {{counter} ПідпиÑників} other {{counter} ПідпиÑники}}", + "account.following_counter": "{count, plural, one {{counter} ПідпиÑка} few {{counter} ПідпиÑки} many {{counter} ПідпиÑок} other {{counter} ПідпиÑки}}", "account.follows.empty": "Цей кориÑтувач ще ні на кого не підпиÑавÑÑ.", "account.follows_you": "ПідпиÑаний(-а) на ваÑ", "account.hide_reblogs": "Сховати передмухи від @{name}", @@ -36,7 +38,7 @@ "account.requested": "Очікує підтвердженнÑ. ÐатиÑніть щоб відмінити запит", "account.share": "ПоділитиÑÑ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÐµÐ¼ @{name}", "account.show_reblogs": "Показати передмухи від @{name}", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural, one {{counter} ПоÑÑ‚} few {{counter} ПоÑти} many {{counter} ПоÑтів} other {{counter} ПоÑти}}", "account.unblock": "Розблокувати @{name}", "account.unblock_domain": "Розблокувати {domain}", "account.unendorse": "Ðе публікувати у профілі", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Результати пошуку", "emoji_button.symbols": "Символи", "emoji_button.travel": "Подорожі", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "Тут дмухалок немає!", "empty_column.account_unavailable": "Профіль недоÑтупний", "empty_column.blocks": "Ви ще не заблокували жодного кориÑтувача.", @@ -166,13 +169,15 @@ "empty_column.notifications": "У Ð²Ð°Ñ Ñ‰Ðµ немає Ñповіщень. ПерепиÑуйтеÑÑŒ з іншими кориÑтувачами, щоб почати розмову.", "empty_column.public": "Тут поки нічого немає! Опублікуйте щоÑÑŒ, або вручну підпишітьÑÑ Ð½Ð° кориÑтувачів інших інÑтанцій, щоб заповнити Ñтрічку", "error.unexpected_crash.explanation": "Ð¦Ñ Ñторінка не може бути коректно відображена через баґ у нашому коді або через проблему ÑуміÑноÑті браузера.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "Спробуйте перезавантажити Ñторінку. Якщо це не допоможе, ви вÑе ще зможете викориÑтовувати Mastodon через інший браузер або рідний додаток.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Скопіювати траÑÑƒÐ²Ð°Ð½Ð½Ñ Ñтека у буфер обміну", "errors.unexpected_crash.report_issue": "Повідомити про проблему", "follow_request.authorize": "Ðвторизувати", "follow_request.reject": "Відмовити", "follow_requests.unlocked_explanation": "Хоча ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ðµ заблоковано, працівники {domain} припуÑкають, що, можливо, ви хотіли б переглÑнути ці запити на підпиÑку.", - "generic.saved": "Saved", + "generic.saved": "Збережено", "getting_started.developers": "Розробникам", "getting_started.directory": "Каталог профілів", "getting_started.documentation": "ДокументаціÑ", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "розфокуÑуватиÑÑ Ð· нового допиÑу чи пошуку", "keyboard_shortcuts.up": "рухатиÑÑ Ð²Ð²ÐµÑ€Ñ… ÑпиÑком", "lightbox.close": "Закрити", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Далі", "lightbox.previous": "Ðазад", - "lightbox.view_context": "ПереглÑнути контекÑÑ‚", "lists.account.add": "Додати до ÑпиÑку", "lists.account.remove": "Видалити зі ÑпиÑку", "lists.delete": "Видалити ÑпиÑок", @@ -260,6 +266,10 @@ "lists.edit.submit": "Змінити назву", "lists.new.create": "Додати ÑпиÑок", "lists.new.title_placeholder": "Ðова назва ÑпиÑку", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Шукати Ñеред людей, на Ñких ви підпиÑані", "lists.subheading": "Ваші ÑпиÑки", "load_pending": "{count, plural, one {# новий елемент} other {# нових елементів}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Показати/приховати", "missing_indicator.label": "Ðе знайдено", "missing_indicator.sublabel": "РеÑÑƒÑ€Ñ Ð½Ðµ знайдений", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Приховати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ кориÑтувача?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Мобільні додатки", "navigation_bar.blocks": "Заблоковані кориÑтувачі", "navigation_bar.bookmarks": "Закладки", @@ -298,6 +310,7 @@ "notification.own_poll": "Ваше Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾", "notification.poll": "ОпитуваннÑ, у Ñкому ви голоÑували, закінчилоÑÑ", "notification.reblog": "{name} передмухнув(-ла) Ваш допиÑ", + "notification.status": "{name} just posted", "notifications.clear": "ОчиÑтити ÑповіщеннÑ", "notifications.clear_confirmation": "Ви впевнені, що хочете назавжди видалити вÑÑ– ÑповіщенÑ?", "notifications.column_settings.alert": "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð½Ð° комп'ютері", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Передмухи:", "notifications.column_settings.show": "Показати в колонці", "notifications.column_settings.sound": "Відтворювати звуки", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "УÑÑ–", "notifications.filter.boosts": "Передмухи", "notifications.filter.favourites": "Улюблені", "notifications.filter.follows": "ПідпиÑки", "notifications.filter.mentions": "Згадки", "notifications.filter.polls": "Результати опитуваннÑ", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} Ñповіщень", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Закрито", "poll.refresh": "Оновити", "poll.total_people": "{count, plural, one {# оÑоба} other {# оÑіб}}", @@ -423,29 +447,30 @@ "timeline_hint.resources.followers": "ПідпиÑники", "timeline_hint.resources.follows": "ПідпиÑки", "timeline_hint.resources.statuses": "Старіші дмухи", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.counter_by_accounts": "{count, plural, one {{counter} оÑоба обговорює} few {{counter} оÑоби обговорюють} many {{counter} оÑіб обговорюють} other {{counter} оÑоби обговорюють}}", "trends.trending_now": "Ðктуальні", "ui.beforeunload": "Вашу чернетку буде втрачено, Ñкщо ви покинете Mastodon.", - "units.short.billion": "{count}B", - "units.short.million": "{count}M", - "units.short.thousand": "{count}K", + "units.short.billion": "{count} млрд", + "units.short.million": "{count} млн", + "units.short.thousand": "{count} тиÑ", "upload_area.title": "ПеретÑгніть Ñюди, щоб завантажити", - "upload_button.label": "Додати медіа ({formats})", + "upload_button.label": "Додати медіа", "upload_error.limit": "Ліміт Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² перевищено.", "upload_error.poll": "Ðе можна завантажувати файли до опитувань.", "upload_form.audio_description": "Опишіть Ð´Ð»Ñ Ð»ÑŽÐ´ÐµÐ¹ із вадами Ñлуху", "upload_form.description": "Опишіть Ð´Ð»Ñ Ð»ÑŽÐ´ÐµÐ¹ з вадами зору", "upload_form.edit": "Змінити", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "Змінити мініатюру", "upload_form.undo": "Видалити", "upload_form.video_description": "Опишіть Ð´Ð»Ñ Ð»ÑŽÐ´ÐµÐ¹ із вадами Ñлуху або зору", "upload_modal.analyzing_picture": "Ðналізуємо малюнок…", "upload_modal.apply": "ЗаÑтоÑувати", - "upload_modal.choose_image": "Choose image", + "upload_modal.choose_image": "Вибрати зображеннÑ", "upload_modal.description_placeholder": "ЩурÑчий бугай із їжаком-харцизом в'ючиÑÑŒ підпиÑали ґешефт у єнах", "upload_modal.detect_text": "ВиÑвити текÑÑ‚ на малюнку", "upload_modal.edit_media": "Редагувати медіа", "upload_modal.hint": "Клацніть або перетÑгніть коло на превью, щоб обрати точку, Ñку буде завжди видно на мініатюрах.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "ПереглÑнути ({ratio})", "upload_progress.label": "ЗавантаженнÑ...", "video.close": "Закрити відео", diff --git a/app/javascript/mastodon/locales/ur.json b/app/javascript/mastodon/locales/ur.json index b94b7c16200664e7fe4709fdf69aeb6961382edf..aaccf1d8381e057fa365c723f18520074fe7b6be 100644 --- a/app/javascript/mastodon/locales/ur.json +++ b/app/javascript/mastodon/locales/ur.json @@ -9,8 +9,10 @@ "account.browse_more_on_origin_server": "Browse more on the original profile", "account.cancel_follow_request": "درخواست٠پیروی منسوخ کریں", "account.direct": "راست پیغام @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", "account.domain_blocked": "Ù¾ÙˆØ´ÛŒØ¯Û ÚˆÙˆÙ…ÛŒÙ†", "account.edit_profile": "مشخص ترمیم کریں", + "account.enable_notifications": "Notify me when @{name} posts", "account.endorse": "مشکص پر نمایاں کریں", "account.follow": "پیروی کریں", "account.followers": "پیروکار", @@ -98,7 +100,7 @@ "compose_form.publish_loud": "{publish}!", "compose_form.sensitive.hide": "وسائل Ú©Ùˆ ØØ³Ø§Ø³ Ù†Ø´Ø§Ù†Ø¯Û Ú©Ø±ÛŒÚº", "compose_form.sensitive.marked": "وسائل ØØ³Ø§Ø³ Ù†Ø´Ø§Ù†Ø¯Û ÛÛ’", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", "compose_form.spoiler_placeholder": "Write your warning here", @@ -147,6 +149,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "ÛŒÛØ§Úº کوئی نوٹس Ù†Ûیں Ûیں!", "empty_column.account_unavailable": "مشخص دستیاب Ù†Ûیں ÛÛ’", "empty_column.blocks": "آپ Ù†Û’ ابھی کسی صار٠کو مسدود Ù†Ûیں کیا ÛÛ’.", @@ -166,7 +169,9 @@ "empty_column.notifications": "ابھی آپ کیلئے کوئی اطلاعات Ù†Ûیں Ûیں. Ú¯ÙØªÚ¯Ùˆ شروع کرنے Ú©Û’ لئے دیگر صارÙین سے متعامل ÛÙˆÚº.", "empty_column.public": "ÛŒÛØ§Úº Ú©Ú†Ú¾ بھی Ù†Ûیں ÛÛ’! Ú©Ú†Ú¾ عمومی ØªØØ±ÛŒØ± کریں یا اس Ø¬Ú¯Û Ú©Ùˆ Ù¾ÙØ± کرنے Ú©Û’ لئے از خود دیگر سرورس Ú©Û’ صارÙین Ú©ÛŒ پیروی کریں", "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", "error.unexpected_crash.next_steps": "ØµÙØÛ’ Ú©Ùˆ ØªØ§Ø²Û Ú©Ø±Ù†Û’ Ú©ÛŒ کوشش کریں. اگر کارآمد Ù†Û ÛÙˆ تو آپ کسی دیگر براؤزر یا مقامی ایپ سے Ûنوز ماسٹوڈون استعمال کر سکتے Ûیں.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", "errors.unexpected_crash.report_issue": "Ù…Ø³Ø¦Ù„Û Ú©ÛŒ اطلاع کریں", "follow_request.authorize": "اجازت دیں", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", "lightbox.next": "Next", "lightbox.previous": "Previous", - "lightbox.view_context": "View context", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", "lists.delete": "Delete list", @@ -260,6 +266,10 @@ "lists.edit.submit": "Change title", "lists.new.create": "Add list", "lists.new.title_placeholder": "New list title", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", "lists.search": "Search among people you follow", "lists.subheading": "Your lists", "load_pending": "{count, plural, one {# new item} other {# new items}}", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "Hide {number, plural, one {image} other {images}}", "missing_indicator.label": "Not found", "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", "navigation_bar.apps": "Mobile apps", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -298,6 +310,7 @@ "notification.own_poll": "Your poll has ended", "notification.poll": "A poll you have voted in has ended", "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", "notifications.clear": "Clear notifications", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.show": "Show in column", "notifications.column_settings.sound": "Play sound", + "notifications.column_settings.status": "New toots:", "notifications.filter.all": "All", "notifications.filter.boosts": "Boosts", "notifications.filter.favourites": "Favourites", "notifications.filter.follows": "Follows", "notifications.filter.mentions": "Mentions", "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", "notifications.group": "{count} notifications", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", "poll.closed": "Closed", "poll.refresh": "Refresh", "poll.total_people": "{count, plural, one {# person} other {# people}}", @@ -389,7 +413,7 @@ "status.pinned": "Pinned toot", "status.read_more": "Read more", "status.reblog": "Boost", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "Detect text from picture", "upload_modal.edit_media": "Edit media", "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", "upload_modal.preview_label": "Preview ({ratio})", "upload_progress.label": "Uploading…", "video.close": "Close video", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 17c4302c268a92524fde3a9cd994578c6f8f53d2..d22b8d7045413fa422af4eec8b3177616e3059c8 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -1,28 +1,30 @@ { - "account.account_note_header": "Ghi chú cá»§a bạn cho @{name}", + "account.account_note_header": "Ghi chú", "account.add_or_remove_from_list": "Thêm hoặc Xóa khá»i danh sách", "account.badges.bot": "Bot", "account.badges.group": "Nhóm", "account.block": "Chặn @{name}", "account.block_domain": "Ẩn má»i thứ từ {domain}", "account.blocked": "Äã chặn", - "account.browse_more_on_origin_server": "Tìm những tà i khoản có liên quan", + "account.browse_more_on_origin_server": "Truy cáºp trang cá»§a ngưá»i nà y", "account.cancel_follow_request": "Há»§y yêu cầu theo dõi", - "account.direct": "Nhắn tin cho @{name}", - "account.domain_blocked": "Äã chặn ngưá»i dùng", + "account.direct": "Nhắn tin @{name}", + "account.disable_notifications": "Không thông báo khi @{name} đăng tút", + "account.domain_blocked": "Ngưá»i đã chặn", "account.edit_profile": "Chỉnh sá»a trang cá nhân", - "account.endorse": "Hiển thị trên trang cá nhân", + "account.enable_notifications": "Thông báo khi @{name} đăng tút", + "account.endorse": "Vinh danh ngưá»i nà y", "account.follow": "Theo dõi", "account.followers": "Ngưá»i theo dõi", "account.followers.empty": "Chưa có ngưá»i theo dõi nà o.", "account.followers_counter": "{count, plural, one {{counter} Ngưá»i theo dõi} other {{counter} Ngưá»i theo dõi}}", - "account.following_counter": "{count, plural, other {{counter} Äang theo dõi}}", - "account.follows.empty": "Ngưá»i dùng nà y chưa theo dõi ai.", + "account.following_counter": "{count, plural, one {{counter} Theo dõi} other {{counter} Theo dõi}}", + "account.follows.empty": "Ngưá»i nà y chưa theo dõi ai.", "account.follows_you": "Äang theo dõi bạn", "account.hide_reblogs": "Ẩn chia sẻ từ @{name}", - "account.last_status": "Hoạt động gần đây", + "account.last_status": "Online", "account.link_verified_on": "Liên kết nà y đã được xác thá»±c và o {date}", - "account.locked_info": "Ngưá»i dùng nà y thiết láºp trạng thái ẩn. Há» sẽ tá»± mình xét duyệt các yêu cầu theo dõi.", + "account.locked_info": "Äây là tà i khoản riêng tư. Há» sẽ tá»± mình xét duyệt các yêu cầu theo dõi.", "account.media": "Bá»™ sưu táºp", "account.mention": "Nhắc đến @{name}", "account.moved_to": "{name} đã dá»i sang:", @@ -31,52 +33,52 @@ "account.muted": "Äã ẩn", "account.never_active": "Chưa có bất cứ hoạt động nà o", "account.posts": "Tút", - "account.posts_with_replies": "Trả lá»i", + "account.posts_with_replies": "Tương tác", "account.report": "Báo cáo @{name}", "account.requested": "Äang chá» chấp thuáºn. Nhấp và o đây để há»§y yêu cầu theo dõi", "account.share": "Chia sẻ hồ sÆ¡ @{name}", "account.show_reblogs": "Hiện chia sẻ từ @{name}", - "account.statuses_counter": "{count, plural, other {{counter} Tút}}", + "account.statuses_counter": "{count, plural, one {{counter} Tút} other {{counter} Tút}}", "account.unblock": "Bá» chặn @{name}", "account.unblock_domain": "BỠẩn {domain}", - "account.unendorse": "Không hiện trên trang cá nhân", + "account.unendorse": "Ngưng vinh danh ngưá»i nà y", "account.unfollow": "Ngưng theo dõi", "account.unmute": "BỠẩn @{name}", "account.unmute_notifications": "Hiển lại thông báo từ @{name}", - "account_note.placeholder": "Nhấn để thêm ghi chú", + "account_note.placeholder": "Bạn có Ä‘iá»u gì thú vị muốn nói vá» ngưá»i nà y?", "alert.rate_limited.message": "Vui lòng thá» lại sau {retry_time, time, medium}.", "alert.rate_limited.title": "Vượt giá»›i hạn", "alert.unexpected.message": "Äã xảy ra lá»—i không mong muốn.", "alert.unexpected.title": "á»iii!", - "announcement.announcement": "Thông báo", + "announcement.announcement": "Thông báo chung", "autosuggest_hashtag.per_week": "{count} má»—i tuần", - "boost_modal.combo": "Bạn có thể nhấn {combo} để bá» qua", + "boost_modal.combo": "Nhấn {combo} để chia sẻ nhanh hÆ¡n", "bundle_column_error.body": "Äã có lá»—i xảy ra trong khi tải ná»™i dung nà y.", "bundle_column_error.retry": "Thá» lại", "bundle_column_error.title": "Không có kết nối internet", "bundle_modal_error.close": "Äóng", "bundle_modal_error.message": "Äã có lá»—i xảy ra trong khi tải ná»™i dung nà y.", "bundle_modal_error.retry": "Thá» lại", - "column.blocks": "Ngưá»i dùng đã chặn", - "column.bookmarks": "Tút đã lưu", + "column.blocks": "Ngưá»i đã chặn", + "column.bookmarks": "Äã lưu", "column.community": "Máy chá»§ cá»§a bạn", - "column.direct": "Nhắn tin", - "column.directory": "Tìm má»™t ai đó", + "column.direct": "Tin nhắn", + "column.directory": "Tìm ngưá»i cùng sở thÃch", "column.domain_blocks": "Máy chá»§ đã chặn", - "column.favourites": "Tâm đắc", + "column.favourites": "Lượt thÃch", "column.follow_requests": "Yêu cầu theo dõi", "column.home": "Bảng tin", "column.lists": "Danh sách", - "column.mutes": "Ngưá»i dùng đã chặn", + "column.mutes": "Ngưá»i đã ẩn", "column.notifications": "Thông báo", "column.pins": "Tút ghim", - "column.public": "Mạng liên kết", + "column.public": "Mạng liên hợp", "column_back_button.label": "Quay lại", - "column_header.hide_settings": "Ẩn cà i đặt", + "column_header.hide_settings": "Ẩn bá»™ lá»c", "column_header.moveLeft_settings": "Dá»i cá»™t sang bên trái", "column_header.moveRight_settings": "Dá»i cá»™t sang bên phải", "column_header.pin": "Ghim", - "column_header.show_settings": "Hiển thị cà i đặt", + "column_header.show_settings": "Hiện bá»™ lá»c", "column_header.unpin": "Không ghim", "column_subheading.settings": "Cà i đặt", "community.column_settings.local_only": "Chỉ máy chá»§ cá»§a bạn", @@ -96,11 +98,11 @@ "compose_form.poll.switch_to_single": "Chỉ cho phép chá»n duy nhất má»™t lá»±a chá»n", "compose_form.publish": "Tút", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.hide": "Ná»™i dung nhạy cảm", - "compose_form.sensitive.marked": "Ná»™i dung đã đánh dấu nhạy cảm", - "compose_form.sensitive.unmarked": "Ná»™i dung không đánh dấu nhạy cảm", - "compose_form.spoiler.marked": "Văn bản bị ẩn", - "compose_form.spoiler.unmarked": "Văn bản không ẩn sau spoil", + "compose_form.sensitive.hide": "{count, plural, one {Ná»™i dung là nhạy cảm} other {Ná»™i dung là nhạy cảm}}", + "compose_form.sensitive.marked": "{count, plural, one {Ná»™i dung đã đánh dấu là nhạy cảm} other {Ná»™i dung đã đánh dấu là nhạy cảm}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Ná»™i dung nà y bình thưá»ng} other {Ná»™i dung nà y bình thưá»ng}}", + "compose_form.spoiler.marked": "Há»§y ná»™i dung ẩn", + "compose_form.spoiler.unmarked": "Tạo ná»™i dung ẩn", "compose_form.spoiler_placeholder": "Viết ná»™i dung ẩn cá»§a bạn ở đây", "confirmation_modal.cancel": "Há»§y bá»", "confirmations.block.block_and_report": "Chặn & Báo cáo", @@ -115,58 +117,61 @@ "confirmations.logout.confirm": "Äăng xuất", "confirmations.logout.message": "Bạn có tháºt sá»± muốn thoát?", "confirmations.mute.confirm": "Ẩn", - "confirmations.mute.explanation": "Äiá»u nà y sẽ khiến tút cá»§a ngưá»i đó và những tút có đỠcáºp đến há» bị ẩn, tuy nhiên vẫn cho phép há» xem bà i đăng cá»§a bạn và theo dõi bạn.", + "confirmations.mute.explanation": "Äiá»u nà y sẽ khiến tút cá»§a há» và những tút có nhắc đến há» bị ẩn, tuy nhiên há» vẫn có thể xem tút cá»§a bạn và theo dõi bạn.", "confirmations.mute.message": "Bạn có chắc chắn muốn ẩn {name}?", "confirmations.redraft.confirm": "Xóa & viết lại", - "confirmations.redraft.message": "Bạn có chắc chắn muốn xóa tút và viết lại? Äiá»u nà y sẽ xóa mất những lượt tâm đắc và chia sẻ cá»§a tút, cÅ©ng như những trả lá»i sẽ không còn ná»™i dung gốc.", + "confirmations.redraft.message": "Bạn có chắc chắn muốn xóa tút và viết lại? Äiá»u nà y sẽ xóa mất những lượt thÃch và chia sẻ cá»§a tút, cÅ©ng như những trả lá»i sẽ không còn ná»™i dung gốc.", "confirmations.reply.confirm": "Trả lá»i", "confirmations.reply.message": "Ná»™i dung bạn Ä‘ang soạn thảo sẽ bị ghi đè, bạn có tiếp tục?", "confirmations.unfollow.confirm": "Ngưng theo dõi", "confirmations.unfollow.message": "Bạn có chắc chắn muốn ngưng theo dõi {name}?", "conversation.delete": "Xóa tin nhắn nà y", "conversation.mark_as_read": "Äánh dấu là đã Ä‘á»c", - "conversation.open": "Xem tin nhắn", + "conversation.open": "Xem toà n bá»™ tin nhắn", "conversation.with": "Vá»›i {names}", - "directory.federated": "Từ mạng liên kết", - "directory.local": "Chỉ từ {domain}", - "directory.new_arrivals": "Gia nháºp gần đây", + "directory.federated": "Từ mạng liên hợp", + "directory.local": "Từ {domain}", + "directory.new_arrivals": "Má»›i tham gia", "directory.recently_active": "Hoạt động gần đây", "embed.instructions": "Sao chép Ä‘oạn mã dưới đây và chèn và o trang web cá»§a bạn.", "embed.preview": "Nó sẽ hiển thị như vầy:", "emoji_button.activity": "Hoạt động", - "emoji_button.custom": "Riêng", + "emoji_button.custom": "Äá»™c đáo", "emoji_button.flags": "Cá»", "emoji_button.food": "Ä‚n uống", "emoji_button.label": "Chèn emoji", "emoji_button.nature": "Thiên nhiên", "emoji_button.not_found": "Không tìm thấy emoji! (°□°)", "emoji_button.objects": "Äồ váºt", - "emoji_button.people": "Ngưá»i", + "emoji_button.people": "Mặt cưá»i", "emoji_button.recent": "Thưá»ng dùng", "emoji_button.search": "Tìm kiếm...", "emoji_button.search_results": "Kết quả tìm kiếm", "emoji_button.symbols": "Biểu tượng", "emoji_button.travel": "Du lịch", + "empty_column.account_suspended": "Tà i khoản vô hiệu hóa", "empty_column.account_timeline": "Chưa có tút nà o!", - "empty_column.account_unavailable": "Tà i khoản không còn nữa", + "empty_column.account_unavailable": "Tà i khoản bị đình chỉ", "empty_column.blocks": "Bạn chưa chặn bất cứ ai.", "empty_column.bookmarked_statuses": "Bạn chưa lưu tút nà o. Nếu có, nó sẽ hiển thị ở đây.", "empty_column.community": "Máy chá»§ cá»§a bạn chưa có tút nà o công khai. Bạn hãy thá» viết gì đó Ä‘i!", "empty_column.direct": "Bạn chưa có tin nhắn nà o. Khi bạn gá»i hoặc nháºn tin nhắn, nó sẽ hiển thị ở đây.", "empty_column.domain_blocks": "Chưa ẩn bất kỳ máy chá»§ nà o.", - "empty_column.favourited_statuses": "Bạn chưa tâm đắc tút nà o. Hãy thá» Ä‘i, nó sẽ xuất hiện ở đây.", - "empty_column.favourites": "Chưa có ai tâm đắc tút nà y.", + "empty_column.favourited_statuses": "Bạn chưa thÃch tút nà o. Hãy thá» Ä‘i, nó sẽ xuất hiện ở đây.", + "empty_column.favourites": "Chưa có ai thÃch tút nà y.", "empty_column.follow_requests": "Bạn chưa có yêu cầu theo dõi nà o.", - "empty_column.hashtag": "Chưa có bà i đăng nà o sá» dụng hashtag nà y.", + "empty_column.hashtag": "Chưa có bà i đăng nà o dùng hashtag nà y.", "empty_column.home": "Chưa có bất cứ gì! Hãy bắt đầu bằng cách tìm kiếm hoặc truy cáºp {public} để theo dõi những ngưá»i bạn quan tâm.", "empty_column.home.public_timeline": "tút công khai", - "empty_column.list": "Chưa có gì trong danh sách. Khi thà nh viên cá»§a danh sách nà y đăng tút má»›i, chúng má»›i xuất hiện ở đây.", - "empty_column.lists": "Bạn không có danh sách nà o.", - "empty_column.mutes": "Bạn chưa ẩn ngưá»i dùng nà o.", + "empty_column.list": "Chưa có tút. Khi những ngưá»i trong danh sách nà y đăng tút má»›i, chúng sẽ xuất hiện ở đây.", + "empty_column.lists": "Bạn chưa tạo danh sách nà o.", + "empty_column.mutes": "Bạn chưa ẩn bất kỳ ai.", "empty_column.notifications": "Bạn chưa có thông báo nà o. Hãy thá» theo dõi hoặc nhắn tin cho má»™t ai đó.", - "empty_column.public": "Trống trÆ¡n! Bạn hãy viết gì đó hoặc bắt đầu theo dõi ngưá»i dùng khác", + "empty_column.public": "Trống trÆ¡n! Bạn hãy viết gì đó hoặc bắt đầu theo dõi những ngưá»i khác", "error.unexpected_crash.explanation": "Trang nà y có thể không hiển thị chÃnh xác do lá»—i láºp trình Mastodon hoặc vấn đỠtương thÃch trình duyệt.", + "error.unexpected_crash.explanation_addons": "Trang nà y không thể hiển thị do xung khắc vá»›i add-on cá»§a trình duyệt hoặc công cụ tá»± động dịch ngôn ngữ.", "error.unexpected_crash.next_steps": "Hãy thá» là m má»›i trang. Nếu vẫn không được, bạn hãy và o Mastodon bằng má»™t ứng dụng di động hoặc trình duyệt khác.", + "error.unexpected_crash.next_steps_addons": "Hãy tắt add-on và là m tươi trang. Nếu vẫn không được, bạn nên thỠđăng nháºp Mastodon trên trình duyệt khác hoặc app khác.", "errors.unexpected_crash.copy_stacktrace": "Sao chép stacktrace và o clipboard", "errors.unexpected_crash.report_issue": "Báo cáo lá»—i", "follow_request.authorize": "Cho phép", @@ -174,9 +179,9 @@ "follow_requests.unlocked_explanation": "Mặc dù tà i khoản cá»§a bạn Ä‘ang ở chế độ công khai, quản trị viên cá»§a {domain} vẫn tin rằng bạn sẽ muốn xem lại yêu cầu theo dõi từ những ngưá»i khác.", "generic.saved": "Äã lưu", "getting_started.developers": "Nhà phát triển", - "getting_started.directory": "Danh sách ngưá»i dùng", + "getting_started.directory": "Mạng lưới", "getting_started.documentation": "Tà i liệu", - "getting_started.heading": "Dà nh cho ngưá»i má»›i", + "getting_started.heading": "Quản lý", "getting_started.invite": "Má»i bạn bè", "getting_started.open_source_notice": "Mastodon là phần má»m mã nguồn mở. Bạn có thể đóng góp hoặc báo lá»—i trên GitHub tại {github}.", "getting_started.security": "Bảo máºt", @@ -190,24 +195,24 @@ "hashtag.column_settings.tag_mode.any": "Má»™t phần", "hashtag.column_settings.tag_mode.none": "Không chá»n", "hashtag.column_settings.tag_toggle": "Bao gồm thêm hashtag cho cá»™t nà y", - "home.column_settings.basic": "CÆ¡ bản", - "home.column_settings.show_reblogs": "Hiện tút chia sẻ", - "home.column_settings.show_replies": "Hiện trả lá»i", + "home.column_settings.basic": "Tùy chỉnh", + "home.column_settings.show_reblogs": "Hiện những lượt chia sẻ", + "home.column_settings.show_replies": "Hiện những tút dạng trả lá»i", "home.hide_announcements": "Ẩn thông báo", "home.show_announcements": "Hiện thông báo", - "intervals.full.days": "{number} days", - "intervals.full.hours": "{number} hours", - "intervals.full.minutes": "{number} minutes", + "intervals.full.days": "{number, plural, other {# ngà y}}", + "intervals.full.hours": "{number, plural, other {# giá»}}", + "intervals.full.minutes": "{number, plural, other {# phút}}", "introduction.federation.action": "Tiếp theo", - "introduction.federation.federated.headline": "Mạng liên kết", - "introduction.federation.federated.text": "Nếu máy chá»§ cá»§a bạn có liên kết vá»›i các máy chá»§ khác, bà i đăng công khai từ há» sẽ xuất hiện ở Mạng liên kết.", + "introduction.federation.federated.headline": "Mạng liên hợp", + "introduction.federation.federated.text": "Nếu máy chá»§ cá»§a bạn có liên kết vá»›i các máy chá»§ khác, bà i đăng công khai từ há» sẽ xuất hiện ở Thế giá»›i.", "introduction.federation.home.headline": "Bảng tin", "introduction.federation.home.text": "Bảng tin là nÆ¡i hiển thị bà i đăng từ những ngưá»i bạn theo dõi. Bạn có thể theo dõi bất cứ ai trên bất cứ máy chá»§ nà o!", - "introduction.federation.local.headline": "Máy chá»§ cá»§a bạn", - "introduction.federation.local.text": "Máy chá»§ cá»§a bạn là nÆ¡i hiển thị bà i đăng công khai từ những ngưá»i thuá»™c cùng má»™t máy chá»§ cá»§a bạn.", + "introduction.federation.local.headline": "Cá»™ng đồng", + "introduction.federation.local.text": "Cá»™ng đồng là nÆ¡i hiển thị bà i đăng công khai từ những ngưá»i thuá»™c cùng má»™t máy chá»§ cá»§a bạn.", "introduction.interactions.action": "Tôi đã hiểu rồi!", - "introduction.interactions.favourite.headline": "Tâm đắc", - "introduction.interactions.favourite.text": "Tâm đắc má»™t tút có nghÄ©a là bạn thÃch tút đó và lưu giữ để sau nà y xem lại.", + "introduction.interactions.favourite.headline": "ThÃch", + "introduction.interactions.favourite.text": "ThÃch má»™t tút có nghÄ©a là bạn tâm đắc ná»™i dung cá»§a tút và muốn lưu giữ để sau nà y xem lại.", "introduction.interactions.reblog.headline": "Chia sẻ", "introduction.interactions.reblog.text": "Vá»›i tÃnh năng chia sẻ, bạn có thể chia sẻ tút cá»§a ngưá»i khác cho những ngưá»i theo dõi bạn.", "introduction.interactions.reply.headline": "Trả lá»i", @@ -216,7 +221,7 @@ "introduction.welcome.headline": "Hướng dẫn ngưá»i má»›i", "introduction.welcome.text": "Chà o mừng bạn đến mạng xã há»™i liên hợp! Tại đây bạn có thể đăng tải ná»™i dung và trao đổi vá»›i bạn bè cá»§a mình trên các máy chá»§ khác nhau. Máy chá»§ {domain} là nÆ¡i lưu trữ trang cá nhân cá»§a bạn.", "keyboard_shortcuts.back": "trở lại", - "keyboard_shortcuts.blocked": "mở danh sách ngưá»i dùng đã chặn", + "keyboard_shortcuts.blocked": "mở danh sách ngưá»i đã chặn", "keyboard_shortcuts.boost": "chia sẻ", "keyboard_shortcuts.column": "mở các mục", "keyboard_shortcuts.compose": "mở khung soạn tút", @@ -224,16 +229,16 @@ "keyboard_shortcuts.direct": "mở mục tin nhắn", "keyboard_shortcuts.down": "di chuyển xuống dưới danh sách", "keyboard_shortcuts.enter": "viết tút má»›i", - "keyboard_shortcuts.favourite": "tâm đắc", - "keyboard_shortcuts.favourites": "mở danh sách tâm đắc", - "keyboard_shortcuts.federated": "mở mạng liên kết", + "keyboard_shortcuts.favourite": "thÃch", + "keyboard_shortcuts.favourites": "mở lượt thÃch", + "keyboard_shortcuts.federated": "mở mạng liên hợp", "keyboard_shortcuts.heading": "Các phÃm tắt", "keyboard_shortcuts.home": "mở bảng tin", "keyboard_shortcuts.hotkey": "PhÃm tắt", "keyboard_shortcuts.legend": "hiện bảng hướng dẫn nà y", "keyboard_shortcuts.local": "mở máy chá»§ cá»§a bạn", - "keyboard_shortcuts.mention": "nhắc đến ngưá»i dùng", - "keyboard_shortcuts.muted": "mở danh sách ngưá»i dùng đã ẩn", + "keyboard_shortcuts.mention": "nhắc đến ai đó", + "keyboard_shortcuts.muted": "mở danh sách ngưá»i đã ẩn", "keyboard_shortcuts.my_profile": "mở trang cá nhân cá»§a bạn", "keyboard_shortcuts.notifications": "mở mục thông báo", "keyboard_shortcuts.open_media": "mở ảnh hoặc video", @@ -242,7 +247,7 @@ "keyboard_shortcuts.reply": "trả lá»i", "keyboard_shortcuts.requests": "mở danh sách yêu cầu theo dõi", "keyboard_shortcuts.search": "mở tìm kiếm", - "keyboard_shortcuts.spoilers": "Hiện/ẩn ná»™i dung nhạy cảm", + "keyboard_shortcuts.spoilers": "hiện/ẩn ná»™i dung nhạy cảm", "keyboard_shortcuts.start": "mở mục \"Dà nh cho ngưá»i má»›i\"", "keyboard_shortcuts.toggle_hidden": "ẩn/hiện văn bản bên dưới spoil", "keyboard_shortcuts.toggle_sensitivity": "ẩn/hiện ảnh hoặc video", @@ -250,34 +255,41 @@ "keyboard_shortcuts.unfocus": "đưa con trá» ra khá»i ô soạn thảo hoặc ô tìm kiếm", "keyboard_shortcuts.up": "di chuyển lên trên danh sách", "lightbox.close": "Äóng", + "lightbox.compress": "Thu nhá» hình", + "lightbox.expand": "Phóng to hình", "lightbox.next": "Tiếp", "lightbox.previous": "Trước", - "lightbox.view_context": "Xem ná»™i dung", "lists.account.add": "Thêm và o danh sách", "lists.account.remove": "Xóa khá»i danh sách", "lists.delete": "Xóa danh sách", "lists.edit": "Sá»a danh sách", "lists.edit.submit": "Thay đổi tiêu Ä‘á»", - "lists.new.create": "Thêm và o danh sách", + "lists.new.create": "Tạo danh sách má»›i", "lists.new.title_placeholder": "Tên danh sách má»›i", + "lists.replies_policy.followed": "Ngưá»i theo dõi", + "lists.replies_policy.list": "Ngưá»i trong danh sách", + "lists.replies_policy.none": "Không ai", + "lists.replies_policy.title": "Cho phép bình luáºn vá»›i:", "lists.search": "Tìm kiếm những ngưá»i mà bạn quan tâm", "lists.subheading": "Danh sách cá»§a bạn", - "load_pending": "{count, plural, one {# new item} other {# new items}}", + "load_pending": "{count, plural, one {# tút má»›i} other {# tút má»›i}}", "loading_indicator.label": "Äang tải...", - "media_gallery.toggle_visible": "Ẩn {number, plural, one {image} other {images}}", + "media_gallery.toggle_visible": "Ẩn {number, plural, one {hình ảnh} other {hình ảnh}}", "missing_indicator.label": "Không tìm thấy", - "missing_indicator.sublabel": "Không tìm thấy cái nà y", - "mute_modal.hide_notifications": "Ẩn thông báo từ ngưá»i dùng nà y?", + "missing_indicator.sublabel": "Ná»™i dung nà y không còn tồn tại", + "mute_modal.duration": "Thá»i hạn", + "mute_modal.hide_notifications": "Ẩn thông báo từ ngưá»i nà y?", + "mute_modal.indefinite": "VÄ©nh viá»…n", "navigation_bar.apps": "Apps", - "navigation_bar.blocks": "Ngưá»i dùng đã chặn", + "navigation_bar.blocks": "Ngưá»i đã chặn", "navigation_bar.bookmarks": "Äã lưu", - "navigation_bar.community_timeline": "Máy chá»§ cá»§a bạn", - "navigation_bar.compose": "Soạn tút má»›i", + "navigation_bar.community_timeline": "Cá»™ng đồng", + "navigation_bar.compose": "Viết tút má»›i", "navigation_bar.direct": "Tin nhắn", - "navigation_bar.discover": "Cá»™ng đồng", + "navigation_bar.discover": "Khám phá", "navigation_bar.domain_blocks": "Máy chá»§ đã ẩn", - "navigation_bar.edit_profile": "Chỉnh sá»a trang cá nhân", - "navigation_bar.favourites": "Những thứ tâm đắc", + "navigation_bar.edit_profile": "Trang cá nhân", + "navigation_bar.favourites": "Lượt thÃch", "navigation_bar.filters": "Bá»™ lá»c từ ngữ", "navigation_bar.follow_requests": "Yêu cầu theo dõi", "navigation_bar.follows_and_followers": "Lượt theo dõi", @@ -285,98 +297,110 @@ "navigation_bar.keyboard_shortcuts": "PhÃm tắt", "navigation_bar.lists": "Danh sách", "navigation_bar.logout": "Äăng xuất", - "navigation_bar.mutes": "Ngưá»i dùng đã chặn", + "navigation_bar.mutes": "Ngưá»i đã ẩn", "navigation_bar.personal": "Cá nhân", "navigation_bar.pins": "Tút ghim", - "navigation_bar.preferences": "Tùy chỉnh", - "navigation_bar.public_timeline": "Dòng thá»i gian liên kết", + "navigation_bar.preferences": "Cà i đặt", + "navigation_bar.public_timeline": "Thế giá»›i", "navigation_bar.security": "Bảo máºt", - "notification.favourite": "{name} vừa tâm đắc tút cá»§a bạn", - "notification.follow": "{name} vừa theo dõi bạn", - "notification.follow_request": "{name} vừa yêu cầu theo dõi bạn", + "notification.favourite": "{name} thÃch tút cá»§a bạn", + "notification.follow": "{name} theo dõi bạn", + "notification.follow_request": "{name} yêu cầu theo dõi bạn", "notification.mention": "{name} nhắc đến bạn", - "notification.own_poll": "Cuá»™c thăm dò cá»§a bạn đã kết thúc", - "notification.poll": "Má»™t cuá»™c thăm dò mà bạn tham gia đã kết thúc", + "notification.own_poll": "Cuá»™c bình chá»n bạn tạo đã kết thúc", + "notification.poll": "Cuá»™c bình chá»n cá»§a bạn đã kết thúc", "notification.reblog": "{name} chia sẻ tút cá»§a bạn", - "notifications.clear": "Xóa thông báo", + "notification.status": "{name} vừa đăng", + "notifications.clear": "Xóa hết thông báo", "notifications.clear_confirmation": "Bạn có chắc chắn muốn xóa vÄ©nh viá»…n tất cả thông báo cá»§a mình?", "notifications.column_settings.alert": "Thông báo trên máy tÃnh", - "notifications.column_settings.favourite": "Tâm đắc:", - "notifications.column_settings.filter_bar.advanced": "Hiển thị toà n bá»™", - "notifications.column_settings.filter_bar.category": "Lá»c nhanh", - "notifications.column_settings.filter_bar.show": "Hiện", + "notifications.column_settings.favourite": "Lượt thÃch:", + "notifications.column_settings.filter_bar.advanced": "Toà n bá»™", + "notifications.column_settings.filter_bar.category": "Phân loại", + "notifications.column_settings.filter_bar.show": "Lượt nhắc", "notifications.column_settings.follow": "Ngưá»i theo dõi má»›i:", "notifications.column_settings.follow_request": "Yêu cầu theo dõi má»›i:", - "notifications.column_settings.mention": "Nhắc đến:", - "notifications.column_settings.poll": "Kết quả cuá»™c thăm dò:", + "notifications.column_settings.mention": "Lượt nhắc đến:", + "notifications.column_settings.poll": "Kết quả:", "notifications.column_settings.push": "Thông báo đẩy", - "notifications.column_settings.reblog": "Chia sẻ:", - "notifications.column_settings.show": "Hiện trong cá»™t", - "notifications.column_settings.sound": "Mở tiếng", + "notifications.column_settings.reblog": "Lượt chia sẻ má»›i:", + "notifications.column_settings.show": "Thông báo trên thanh menu", + "notifications.column_settings.sound": "Kèm theo tiếng \"bÃp\"", + "notifications.column_settings.status": "Tút má»›i:", "notifications.filter.all": "Toà n bá»™", "notifications.filter.boosts": "Chia sẻ", - "notifications.filter.favourites": "Tâm đắc", + "notifications.filter.favourites": "ThÃch", "notifications.filter.follows": "Äang theo dõi", - "notifications.filter.mentions": "Nhắc đến", - "notifications.filter.polls": "Kết quả cuá»™c thăm dò", + "notifications.filter.mentions": "Lượt nhắc đến", + "notifications.filter.polls": "Kết quả bình chá»n", + "notifications.filter.statuses": "Cáºp nháºt từ những ngưá»i bạn theo dõi", + "notifications.grant_permission": "Cho phép.", "notifications.group": "{count} thông báo", - "poll.closed": "Cuá»™c thăm dò đã kết thúc", + "notifications.mark_as_read": "Äánh dấu tất cả thông báo là đã Ä‘á»c", + "notifications.permission_denied": "Trình duyệt không cho phép hiển thị thông báo trên mà n hình.", + "notifications.permission_denied_alert": "Không thể báºt thông báo trên mà n hình bởi vì trình duyệt đã cấm trước đó", + "notifications.permission_required": "Không hiện thông báo trên mà n hình bởi vì chưa cho phép.", + "notifications_permission_banner.enable": "Cho phép thông báo trên mà n hình", + "notifications_permission_banner.how_to_control": "Hãy báºt thông báo trên mà n hình để không bá» lỡ những thông báo từ Mastodon. Má»™t khi đã báºt, bạn có thể lá»±a chá»n từng loại thông báo khác nhau thông qua {icon} nút bên dưới.", + "notifications_permission_banner.title": "Không bá» lỡ Ä‘iá»u thú vị nà o", + "picture_in_picture.restore": "Hiển thị bình thưá»ng", + "poll.closed": "Kết thúc", "poll.refresh": "Là m má»›i", - "poll.total_people": "{count, plural, one {# ngưá»i đã bình chá»n} other {# ngưá»i đã bình chá»n}}", - "poll.total_votes": "{count, plural, one {# bình chá»n} other {# bình chá»n}}", - "poll.vote": "Cuá»™c thăm dò", - "poll.voted": "Bạn đã bình chá»n câu trả lá»i nà y", - "poll_button.add_poll": "Tạo thăm dò", - "poll_button.remove_poll": "Há»§y thăm dò", + "poll.total_people": "{count, plural, one {# ngưá»i} other {# ngưá»i}}", + "poll.total_votes": "{count, plural, one {# ngưá»i} other {# ngưá»i}}", + "poll.vote": "Bình chá»n", + "poll.voted": "Bạn đã bình chá»n rồi", + "poll_button.add_poll": "Tạo bình chá»n", + "poll_button.remove_poll": "Há»§y cuá»™c bình chá»n", "privacy.change": "Thay đổi quyá»n riêng tư", "privacy.direct.long": "Chỉ ngưá»i được nhắc đến má»›i thấy", "privacy.direct.short": "Tin nhắn", "privacy.private.long": "Chỉ dà nh cho ngưá»i theo dõi", - "privacy.private.short": "Chỉ ngưá»i theo dõi", + "privacy.private.short": "Ngưá»i theo dõi", "privacy.public.long": "Hiện trên bảng tin máy chá»§", "privacy.public.short": "Công khai", - "privacy.unlisted.long": "Ai cÅ©ng có thể xem nhưng không hiện trên bảng tin máy chá»§", - "privacy.unlisted.short": "Mở", + "privacy.unlisted.long": "Không hiện trên bảng tin máy chá»§", + "privacy.unlisted.short": "Riêng tư", "refresh": "Là m má»›i", "regeneration_indicator.label": "Äang tải…", "regeneration_indicator.sublabel": "Bảng tin cá»§a bạn Ä‘ang được cáºp nháºt!", "relative_time.days": "{number} ngà y", - "relative_time.hours": "{number} giá»", - "relative_time.just_now": "vừa xong", - "relative_time.minutes": "{number}p", + "relative_time.hours": "{number}h", + "relative_time.just_now": "má»›i", + "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "hôm nay", "reply_indicator.cancel": "Há»§y bá»", "report.forward": "Chuyển đến {target}", - "report.forward_hint": "Ngưá»i dùng nà y ở máy chá»§ khác. Gá»i má»™t báo xấu ẩn danh tá»›i máy chá»§ đó?", - "report.hint": "Hãy cho quản trị viên biết lý do tại sao bạn lại báo xấu tà i khoản nà y:", + "report.forward_hint": "Ngưá»i nà y thuá»™c máy chá»§ khác. Gá»i má»™t báo cáo ẩn danh tá»›i máy chá»§ đó?", + "report.hint": "Hãy cho quản trị viên biết lý do vì sao bạn báo cáo ngưá»i nà y:", "report.placeholder": "Bổ sung thêm", "report.submit": "Gá»i Ä‘i", - "report.target": "Báo xấu {target}", + "report.target": "Báo cáo {target}", "search.placeholder": "Tìm kiếm", - "search_popout.search_format": "Tìm kiếm nâng cao", - "search_popout.tips.full_text": "Ná»™i dung trả vá» bao gồm các tút do bạn viết, yêu thÃch, đã chia sẻ hoặc được nhắc đến. CÅ©ng như địa chỉ ngưá»i dùng, tên hiển thị lẫn hashtag.", + "search_popout.search_format": "Gợi ý", + "search_popout.tips.full_text": "Ná»™i dung trả vá» bao gồm những tút mà bạn đã viết, thÃch, chia sẻ hoặc những tút có nhắc đến bạn. Bạn cÅ©ng có thể tìm địa chỉ ngưá»i dùng, tên hiển thị và hashtag.", "search_popout.tips.hashtag": "hashtag", "search_popout.tips.status": "tút", - "search_popout.tips.text": "Ná»™i dung trả vá» là địa chỉ ngưá»i dùng, tên hiển thị và hashtag", + "search_popout.tips.text": "Ná»™i dung trả vá» là tên ngưá»i dùng, tên hiển thị và hashtag", "search_popout.tips.user": "ngưá»i dùng", "search_results.accounts": "Ngưá»i dùng", "search_results.hashtags": "Hashtags", "search_results.statuses": "Tút", - "search_results.statuses_fts_disabled": "Máy chá»§ cá»§a bạn không báºt chức năng tìm kiếm tút.", - "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "search_results.statuses_fts_disabled": "Máy chá»§ cá»§a bạn không báºt tÃnh năng tìm kiếm tút.", + "search_results.total": "{count, number} {count, plural, one {kết quả} other {kết quả}}", "status.admin_account": "Mở giao diện quản trị @{name}", "status.admin_status": "Mở tút nà y trong giao diện quản trị", "status.block": "Chặn @{name}", "status.bookmark": "Lưu", "status.cancel_reblog_private": "Há»§y chia sẻ", "status.cannot_reblog": "Không thể chia sẻ tút nà y", - "status.copy": "Sao chép URL tút", + "status.copy": "Sao chép URL", "status.delete": "Xóa", "status.detailed_status": "Xem chi tiết thêm", - "status.direct": "Nhắn riêng @{name}", + "status.direct": "Nhắn tin @{name}", "status.embed": "Nhúng", - "status.favourite": "Tâm đắc", + "status.favourite": "ThÃch", "status.filtered": "Bá»™ lá»c", "status.load_more": "Xem thêm", "status.media_hidden": "Ảnh/video đã ẩn", @@ -387,36 +411,36 @@ "status.open": "Xem nguyên văn", "status.pin": "Ghim lên trang cá nhân", "status.pinned": "Tút đã ghim", - "status.read_more": "Äá»c thêm", + "status.read_more": "Äá»c tiếp", "status.reblog": "Chia sẻ", - "status.reblog_private": "Chia sẻ vá»›i ngưá»i viết tút gốc", + "status.reblog_private": "Chia sẻ vá»›i ngưá»i có thể xem", "status.reblogged_by": "{name} chia sẻ", "status.reblogs.empty": "Tút nà y chưa có ai chia sẻ. Nếu có, nó sẽ hiển thị ở đây.", "status.redraft": "Xóa và viết lại", "status.remove_bookmark": "Há»§y lưu", "status.reply": "Trả lá»i", "status.replyAll": "Trả lá»i tất cả", - "status.report": "Báo xấu @{name}", - "status.sensitive_warning": "Ná»™i dung nhạy cảm", + "status.report": "Báo cáo @{name}", + "status.sensitive_warning": "Nhạy cảm", "status.share": "Chia sẻ", "status.show_less": "Thu gá»n", - "status.show_less_all": "Thu gá»n tất cả", - "status.show_more": "Mở rá»™ng", + "status.show_less_all": "Thu gá»n toà n bá»™", + "status.show_more": "Xem thêm", "status.show_more_all": "Hiển thị tất cả", - "status.show_thread": "Hiện thêm", - "status.uncached_media_warning": "N/A", + "status.show_thread": "Toà n bá»™ chá»§ Ä‘á»", + "status.uncached_media_warning": "Uncached", "status.unmute_conversation": "Quan tâm", "status.unpin": "Bá» ghim trên trang cá nhân", "suggestions.dismiss": "Tắt đỠxuất", "suggestions.header": "Có thể bạn quan tâm…", - "tabs_bar.federated_timeline": "Mạng liên kết", + "tabs_bar.federated_timeline": "Thế giá»›i", "tabs_bar.home": "Bảng tin", - "tabs_bar.local_timeline": "Máy chá»§ cá»§a bạn", + "tabs_bar.local_timeline": "Cá»™ng đồng", "tabs_bar.notifications": "Thông báo", "tabs_bar.search": "Tìm kiếm", - "time_remaining.days": "Thá»i hạn còn {number, plural, other {# ngà y}}", - "time_remaining.hours": "Thá»i hạn còn {number, plural, other {# giá»}}", - "time_remaining.minutes": "Thá»i hạn còn {number, plural, other {# phút}}", + "time_remaining.days": "Kết thúc sau {number, plural, other {# ngà y}}", + "time_remaining.hours": "Kết thúc sau {number, plural, other {# giá»}}", + "time_remaining.minutes": "Kết thúc sau {number, plural, other {# phút}}", "time_remaining.moments": "Còn lại", "time_remaining.seconds": "Chỉ còn {number, plural, other {# giây}}", "timeline_hint.remote_resource_not_displayed": "{resource} từ máy chá»§ khác sẽ không hiển thị.", @@ -432,24 +456,25 @@ "upload_area.title": "Kéo và thả để tải lên", "upload_button.label": "Thêm media (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "Táºp tin tải lên vượt quá giá»›i hạn cho phép.", - "upload_error.poll": "Cuá»™c thăm dò không được tải táºp tin.", - "upload_form.audio_description": "Mô tả cho ngưá»i thÃnh giác kém", + "upload_error.poll": "Không cho phép Ä‘Ãnh kèm táºp tin.", + "upload_form.audio_description": "Mô tả cho ngưá»i mất thÃnh giác", "upload_form.description": "Mô tả cho ngưá»i khiếm thị", "upload_form.edit": "Biên táºp", "upload_form.thumbnail": "Äổi ảnh thumbnail", "upload_form.undo": "Xóa bá»", - "upload_form.video_description": "Mô tả cho ngưá»i có vấn đỠvá» thÃnh giác", + "upload_form.video_description": "Mô tả cho ngưá»i mất thị lá»±c hoặc không thể nghe", "upload_modal.analyzing_picture": "Phân tÃch hình ảnh", "upload_modal.apply": "Ãp dụng", - "upload_modal.choose_image": "Chá»n hình", + "upload_modal.choose_image": "Chá»n ảnh", "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", - "upload_modal.detect_text": "Phát hiện văn bản trong hình ảnh", - "upload_modal.edit_media": "Chỉnh sá»a ảnh/video", + "upload_modal.detect_text": "TrÃch văn bản từ trong ảnh", + "upload_modal.edit_media": "Biên táºp", "upload_modal.hint": "Nhấp hoặc kéo vòng tròn trên bản xem trước để chá»n phần hiển thị trên hình thu nhá».", + "upload_modal.preparing_ocr": "Äang nháºn dạng ký tự…", "upload_modal.preview_label": "Xem trước ({ratio})", "upload_progress.label": "Äang tải lên...", "video.close": "Äóng video", - "video.download": "Tải táºp tin", + "video.download": "Lưu vá» máy", "video.exit_fullscreen": "Thoát toà n mà n hình", "video.expand": "Mở rá»™ng video", "video.fullscreen": "Toà n mà n hình", diff --git a/app/javascript/mastodon/locales/whitelist_sa.json b/app/javascript/mastodon/locales/whitelist_sa.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_sa.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/locales/whitelist_tt.json b/app/javascript/mastodon/locales/whitelist_tt.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_tt.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/locales/whitelist_zgh.json b/app/javascript/mastodon/locales/whitelist_zgh.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_zgh.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/locales/zgh.json b/app/javascript/mastodon/locales/zgh.json new file mode 100644 index 0000000000000000000000000000000000000000..e2c69c11685cb81337d32e5d36ea5cf660e3fdd7 --- /dev/null +++ b/app/javascript/mastodon/locales/zgh.json @@ -0,0 +1,486 @@ +{ + "account.account_note_header": "âµâµŽâ´· ⵓⴳⴳⴰⵔ", + "account.add_or_remove_from_list": "âµ”âµâµ“ âµâµ– ⵙⵉⵜⵜⵢ ⵙⴳ ⵜâµâ´³â´°âµŽâµœ", + "account.badges.bot": "ⴰⴱⵓⵜ", + "account.badges.group": "ⵜⴰⵔⴰⴱⴱⵓⵜ", + "account.block": "ⴳⴷⵠ@{name}", + "account.block_domain": "ⴳⴷⵠⵉⴳⵔ {domain}", + "account.blocked": "ⵉⵜⵜⵓⴳⴷâµ", + "account.browse_more_on_origin_server": "ⵙⵜⴰⵔⴰ ⵓⴳⴳⴰⵔ â´³ ⵉⴼⵔⵙ â´°âµâµšâµâµ‰", + "account.cancel_follow_request": "ⵙⵔ ⵜⵓⵜⵔⴰ ⵠⵓⴹⴼⵕ", + "account.direct": "ⵜⵓⵣⵉâµâµœ ⵜⵓⵙⵔⵉⴷⵜ @{name}", + "account.disable_notifications": "Stop notifying me when @{name} posts", + "account.domain_blocked": "ⵉⵜⵜⵓⴳⴷⵠⵉⴳⵔ", + "account.edit_profile": "âµ™âµâ´¼âµ ⵉⴼⵔⵙ", + "account.enable_notifications": "Notify me when @{name} posts", + "account.endorse": "Feature on profile", + "account.follow": "ⴹⴼⵕ", + "account.followers": "ⵉⵎⴹⴼⴰⵕâµ", + "account.followers.empty": "No one follows this user yet.", + "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", + "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", + "account.follows.empty": "This user doesn't follow anyone yet.", + "account.follows_you": "ⴹⴼⵕⵠⴽⵯâµ", + "account.hide_reblogs": "Hide boosts from @{name}", + "account.last_status": "Last active", + "account.link_verified_on": "Ownership of this link was checked on {date}", + "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", + "account.media": "â´°âµ™âµâµ–ⵎⵉⵙ", + "account.mention": "Mention @{name}", + "account.moved_to": "{name} has moved to:", + "account.mute": "Mute @{name}", + "account.mute_notifications": "Mute notifications from @{name}", + "account.muted": "Muted", + "account.never_active": "ⵓⵙⴰⵔ", + "account.posts": "Toots", + "account.posts_with_replies": "Toots and replies", + "account.report": "Report @{name}", + "account.requested": "Awaiting approval", + "account.share": "ⴱⴹⵓ ⵉⴼⵔⵙ âµ @{name}", + "account.show_reblogs": "Show boosts from @{name}", + "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.unblock": "Unblock @{name}", + "account.unblock_domain": "Unblock domain {domain}", + "account.unendorse": "Don't feature on profile", + "account.unfollow": "ⴽⴽⵙ ⴰⴹⴼⴼⵓⵕ", + "account.unmute": "Unmute @{name}", + "account.unmute_notifications": "Unmute notifications from @{name}", + "account_note.placeholder": "Click to add a note", + "alert.rate_limited.message": "Please retry after {retry_time, time, medium}.", + "alert.rate_limited.title": "Rate limited", + "alert.unexpected.message": "An unexpected error occurred.", + "alert.unexpected.title": "Oops!", + "announcement.announcement": "Announcement", + "autosuggest_hashtag.per_week": "{count} âµ™ ⵉⵎⴰâµâ´°âµ™âµ™", + "boost_modal.combo": "You can press {combo} to skip this next time", + "bundle_column_error.body": "Something went wrong while loading this component.", + "bundle_column_error.retry": "â´°âµâµ™ ⴰⵔⵎ", + "bundle_column_error.title": "ⴰⵣⴳⴰⵠⵠⵓⵥⵟⵟⴰ", + "bundle_modal_error.close": "ⵔⴳâµ", + "bundle_modal_error.message": "Something went wrong while loading this component.", + "bundle_modal_error.retry": "â´°âµâµ™ ⴰⵔⵎ", + "column.blocks": "ⵉâµâµ™âµ™âµŽâµ”ⵙⵠⵜⵜⵓⴳⴷâµâµâµ‰âµ", + "column.bookmarks": "Bookmarks", + "column.community": "Local timeline", + "column.direct": "Direct messages", + "column.directory": "Browse profiles", + "column.domain_blocks": "Blocked domains", + "column.favourites": "ⵜⵓⴼⵓⵜⵉâµ", + "column.follow_requests": "Follow requests", + "column.home": "â´°âµ™âµâµ“ⴱⴳ", + "column.lists": "ⵜⵉâµâ´³â´°âµŽâµ‰âµ", + "column.mutes": "Muted users", + "column.notifications": "ⵜⵉâµâµ–ⵎⵉⵙⵉâµ", + "column.pins": "Pinned toot", + "column.public": "Federated timeline", + "column_back_button.label": "ⴰⵖⵓâµ", + "column_header.hide_settings": "âµ™âµâµœâµ ⵜⵉⵙⵖⴰâµ", + "column_header.moveLeft_settings": "Move column to the left", + "column_header.moveRight_settings": "Move column to the right", + "column_header.pin": "âµ–âµâµ™", + "column_header.show_settings": "ⵙⵎⴰⵠⵜⵉⵙⵖⴰâµ", + "column_header.unpin": "ⴽⴽⵙ â´°âµ–âµâ´°âµ™", + "column_subheading.settings": "ⵜⵉⵙⵖⴰâµ", + "community.column_settings.local_only": "âµ–â´°âµ™ ⴰⴷⵖⴰⵔⴰâµ", + "community.column_settings.media_only": "âµ–â´°âµ™ ⵉⵙâµâµ–ⵎⵉⵙâµ", + "community.column_settings.remote_only": "Remote only", + "compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.", + "compose_form.direct_message_warning_learn_more": "ⵙⵙⵠⵓⴳⴳⴰⵔ", + "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", + "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", + "compose_form.lock_disclaimer.lock": "locked", + "compose_form.placeholder": "ⵎⴰⵢⴷ ⵉâµâµâ´°âµ â´³ ⵉⵅⴼ âµâµâ´½?", + "compose_form.poll.add_option": "Add a choice", + "compose_form.poll.duration": "Poll duration", + "compose_form.poll.option_placeholder": "ⴰⵙⵜⵜⴰⵢ {number}", + "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.publish": "Toot", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.hide": "{count, plural, one {Mark media as sensitive} other {Mark media as sensitive}}", + "compose_form.sensitive.marked": "{count, plural, one {Media is marked as sensitive} other {Media is marked as sensitive}}", + "compose_form.sensitive.unmarked": "{count, plural, one {Media is not marked as sensitive} other {Media is not marked as sensitive}}", + "compose_form.spoiler.marked": "Text is hidden behind warning", + "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler_placeholder": "Write your warning here", + "confirmation_modal.cancel": "ⵙⵔ", + "confirmations.block.block_and_report": "Block & Report", + "confirmations.block.confirm": "ⴳⴷâµ", + "confirmations.block.message": "ⵉⵙ âµâµ‰âµœ ⵜⵅⵙⴷ â´°â´· ⵜⴳⴷâµâ´· {name}?", + "confirmations.delete.confirm": "ⴽⴽⵙ", + "confirmations.delete.message": "ⵉⵙ âµâµ‰âµœ ⵜⵅⵙⴷ â´°â´· ⵜⴽⴽⵙⴷ ⵜⴰⵥⵕⵉⴳⵜ â´°?", + "confirmations.delete_list.confirm": "ⴽⴽⵙ", + "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.logout.confirm": "ⴼⴼⵖ", + "confirmations.logout.message": "ⵉⵙ âµâµ‰âµœ ⵜⵅⵙⴷ â´°â´· ⵜⴼⴼⵖⴷ?", + "confirmations.mute.confirm": "ⵥⵥⵉⵥâµ", + "confirmations.mute.explanation": "This will hide posts from them and posts mentioning them, but it will still allow them to see your posts and follow you.", + "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.redraft.confirm": "Delete & redraft", + "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.", + "confirmations.reply.confirm": "ⵔⴰⵔ", + "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "confirmations.unfollow.confirm": "ⴽⴽⵙ ⴰⴹⴼⴼⵓⵕ", + "confirmations.unfollow.message": "ⵉⵙ âµâµ‰âµœ ⵜⵅⵙⴷ â´°â´· ⵜⴽⴽⵙⴷ ⴰⴹⴼⴼⵓⵕ ⵉ {name}?", + "conversation.delete": "ⴽⴽⵙ ⴰⵎⵙⴰⵡⴰâµ", + "conversation.mark_as_read": "Mark as read", + "conversation.open": "View conversation", + "conversation.with": "ⴰⴽⴷ {names}", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", + "embed.instructions": "Embed this status on your website by copying the code below.", + "embed.preview": "Here is what it will look like:", + "emoji_button.activity": "Activity", + "emoji_button.custom": "Custom", + "emoji_button.flags": "ⵉⵛâµâµ¢â´°âµâµ", + "emoji_button.food": "Food & Drink", + "emoji_button.label": "Insert emoji", + "emoji_button.nature": "Nature", + "emoji_button.not_found": "ⵓâµâ´° ⵉⵎⵓⵊⵉ!! (╯°□°)╯︵ â”»â”â”»", + "emoji_button.objects": "Objects", + "emoji_button.people": "ⵎⵉⴷⴷâµ", + "emoji_button.recent": "Frequently used", + "emoji_button.search": "ⵔⵣⵓ...", + "emoji_button.search_results": "Search results", + "emoji_button.symbols": "ⵜⵉⵎⴰⵜⴰⵔⵉâµ", + "emoji_button.travel": "Travel & Places", + "empty_column.account_suspended": "Account suspended", + "empty_column.account_timeline": "No toots here!", + "empty_column.account_unavailable": "Profile unavailable", + "empty_column.blocks": "You haven't blocked any users yet.", + "empty_column.bookmarked_statuses": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.", + "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", + "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.domain_blocks": "There are no blocked domains yet.", + "empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.", + "empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.", + "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", + "empty_column.hashtag": "There is nothing in this hashtag yet.", + "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", + "empty_column.home.public_timeline": "the public timeline", + "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", + "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", + "empty_column.mutes": "You haven't muted any users yet.", + "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", + "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up", + "error.unexpected_crash.explanation": "Due to a bug in our code or a browser compatibility issue, this page could not be displayed correctly.", + "error.unexpected_crash.explanation_addons": "This page could not be displayed correctly. This error is likely caused by a browser add-on or automatic translation tools.", + "error.unexpected_crash.next_steps": "Try refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "error.unexpected_crash.next_steps_addons": "Try disabling them and refreshing the page. If that does not help, you may still be able to use Mastodon through a different browser or native app.", + "errors.unexpected_crash.copy_stacktrace": "Copy stacktrace to clipboard", + "errors.unexpected_crash.report_issue": "Report issue", + "follow_request.authorize": "Authorize", + "follow_request.reject": "Reject", + "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", + "generic.saved": "Saved", + "getting_started.developers": "Developers", + "getting_started.directory": "Profile directory", + "getting_started.documentation": "Documentation", + "getting_started.heading": "Getting started", + "getting_started.invite": "Invite people", + "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", + "getting_started.security": "ⵜⵉⵙⵖⴰⵠⵠⵓⵎⵉⴹⴰâµ", + "getting_started.terms": "Terms of service", + "hashtag.column_header.tag_mode.all": "â´· {additional}", + "hashtag.column_header.tag_mode.any": "âµâµ– {additional}", + "hashtag.column_header.tag_mode.none": "without {additional}", + "hashtag.column_settings.select.no_options_message": "No suggestions found", + "hashtag.column_settings.select.placeholder": "ⵙⴽⵛⵎ ⴰⵀⴰⵛⵟⴰⴳ…", + "hashtag.column_settings.tag_mode.all": "All of these", + "hashtag.column_settings.tag_mode.any": "Any of these", + "hashtag.column_settings.tag_mode.none": "None of these", + "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "home.column_settings.basic": "Basic", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Show replies", + "home.hide_announcements": "Hide announcements", + "home.show_announcements": "Show announcements", + "intervals.full.days": "{number, plural, one {# ⵡⴰⵙⵙ} other {# ⵡⵓⵙⵙⴰâµ}}", + "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.minutes": "{number, plural, one {# ⵜⵓⵙⴷⵉⴷⵜ} other {# ⵜⵓⵙⴷⵉⴷⵉâµ}}", + "introduction.federation.action": "Next", + "introduction.federation.federated.headline": "Federated", + "introduction.federation.federated.text": "Public posts from other servers of the fediverse will appear in the federated timeline.", + "introduction.federation.home.headline": "â´°âµ™âµâµ“ⴱⴳ", + "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", + "introduction.federation.local.headline": "ⴰⴷⵖⴰⵔⴰâµ", + "introduction.federation.local.text": "Public posts from people on the same server as you will appear in the local timeline.", + "introduction.interactions.action": "Finish toot-orial!", + "introduction.interactions.favourite.headline": "Favourite", + "introduction.interactions.favourite.text": "You can save a toot for later, and let the author know that you liked it, by favouriting it.", + "introduction.interactions.reblog.headline": "Boost", + "introduction.interactions.reblog.text": "You can share other people's toots with your followers by boosting them.", + "introduction.interactions.reply.headline": "ⵔⴰⵔ", + "introduction.interactions.reply.text": "You can reply to other people's and your own toots, which will chain them together in a conversation.", + "introduction.welcome.action": "Let's go!", + "introduction.welcome.headline": "First steps", + "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "keyboard_shortcuts.back": "to navigate back", + "keyboard_shortcuts.blocked": "to open blocked users list", + "keyboard_shortcuts.boost": "to boost", + "keyboard_shortcuts.column": "to focus a status in one of the columns", + "keyboard_shortcuts.compose": "to focus the compose textarea", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.direct": "to open direct messages column", + "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.favourites": "to open favourites list", + "keyboard_shortcuts.federated": "to open federated timeline", + "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.local": "to open local timeline", + "keyboard_shortcuts.mention": "to mention author", + "keyboard_shortcuts.muted": "to open muted users list", + "keyboard_shortcuts.my_profile": "to open your profile", + "keyboard_shortcuts.notifications": "to open notifications column", + "keyboard_shortcuts.open_media": "to open media", + "keyboard_shortcuts.pinned": "to open pinned toots list", + "keyboard_shortcuts.profile": "to open author's profile", + "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.search": "to focus search", + "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.start": "to open \"get started\" column", + "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", + "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.up": "to move up in the list", + "lightbox.close": "ⵔⴳâµ", + "lightbox.compress": "Compress image view box", + "lightbox.expand": "Expand image view box", + "lightbox.next": "Next", + "lightbox.previous": "Previous", + "lists.account.add": "âµ”âµâµ“ âµ–âµ” ⵜâµâ´³â´°âµŽâµœ", + "lists.account.remove": "ⴽⴽⵙ ⵙⴳ ⵜâµâ´³â´°âµŽâµœ", + "lists.delete": "ⴽⴽⵙ ⵜⴰâµâ´³â´°âµŽâµœ", + "lists.edit": "âµ™âµâ´¼âµ ⵜⴰâµâ´³â´°âµŽâµœ", + "lists.edit.submit": "âµ™âµâ´¼âµ ⴰⵣⵡâµ", + "lists.new.create": "ⵙⴽⵔ ⵜⴰâµâ´³â´°âµŽâµœ", + "lists.new.title_placeholder": "ⴰⵣⵡⵠⵠⵜâµâ´³â´°âµŽâµœ ⵜⴰⵎⴰⵢâµâµ“ⵜ", + "lists.replies_policy.followed": "Any followed user", + "lists.replies_policy.list": "Members of the list", + "lists.replies_policy.none": "No one", + "lists.replies_policy.title": "Show replies to:", + "lists.search": "Search among people you follow", + "lists.subheading": "ⵜⵉâµâ´³â´°âµŽâµ‰âµ âµâµâ´½", + "load_pending": "{count, plural, one {# ⵓⴼⵔⴷⵉⵙ ⴰⵎⴰⵢâµâµ“} other {# ⵉⴼⵔⴷⴰⵙ ⵉⵎⴰⵢâµâµ“ⵜâµ}}", + "loading_indicator.label": "ⴰⵣⴷⴰⵎ...", + "media_gallery.toggle_visible": "ⴼⴼⵔ {number, plural, one {ⵜⴰⵡâµâ´°â´¼âµœ} other {ⵜⵉⵡâµâ´°â´¼âµ‰âµ}}", + "missing_indicator.label": "Not found", + "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.duration": "Duration", + "mute_modal.hide_notifications": "Hide notifications from this user?", + "mute_modal.indefinite": "Indefinite", + "navigation_bar.apps": "Mobile apps", + "navigation_bar.blocks": "Blocked users", + "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.compose": "Compose new toot", + "navigation_bar.direct": "Direct messages", + "navigation_bar.discover": "Discover", + "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.favourites": "Favourites", + "navigation_bar.filters": "Muted words", + "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.follows_and_followers": "Follows and followers", + "navigation_bar.info": "About this server", + "navigation_bar.keyboard_shortcuts": "Hotkeys", + "navigation_bar.lists": "Lists", + "navigation_bar.logout": "ⴼⴼⵖ", + "navigation_bar.mutes": "Muted users", + "navigation_bar.personal": "Personal", + "navigation_bar.pins": "Pinned toots", + "navigation_bar.preferences": "Preferences", + "navigation_bar.public_timeline": "Federated timeline", + "navigation_bar.security": "Security", + "notification.favourite": "{name} favourited your status", + "notification.follow": "{name} followed you", + "notification.follow_request": "{name} has requested to follow you", + "notification.mention": "{name} mentioned you", + "notification.own_poll": "Your poll has ended", + "notification.poll": "A poll you have voted in has ended", + "notification.reblog": "{name} boosted your status", + "notification.status": "{name} just posted", + "notifications.clear": "ⵙⴼⴹ ⵜⵉâµâµ–ⵎⵉⵙⵉâµ", + "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.column_settings.alert": "Desktop notifications", + "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.filter_bar.advanced": "Display all categories", + "notifications.column_settings.filter_bar.category": "Quick filter bar", + "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.follow": "New followers:", + "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Show in column", + "notifications.column_settings.sound": "âµ–âµ” ⵉⵎⵙâµâµ‰", + "notifications.column_settings.status": "New toots:", + "notifications.filter.all": "ⴰⴽⴽⵯ", + "notifications.filter.boosts": "Boosts", + "notifications.filter.favourites": "Favourites", + "notifications.filter.follows": "Follows", + "notifications.filter.mentions": "Mentions", + "notifications.filter.polls": "Poll results", + "notifications.filter.statuses": "Updates from people you follow", + "notifications.grant_permission": "Grant permission.", + "notifications.group": "{count} ⵜâµâµ–ⵎⵉⵙⵉâµ", + "notifications.mark_as_read": "Mark every notification as read", + "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", + "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", + "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications_permission_banner.enable": "Enable desktop notifications", + "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", + "notifications_permission_banner.title": "Never miss a thing", + "picture_in_picture.restore": "Put it back", + "poll.closed": "ⵉⵜⵜⵓⵔⴳâµ", + "poll.refresh": "Refresh", + "poll.total_people": "{count, plural, one {# ⵓⴼⴳⴰâµ} other {# ⵉⴼⴳⴰâµâµ}}", + "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", + "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll_button.add_poll": "âµ”âµâµ“ ⵢⴰⵠⵢⵉⴷⵣ", + "poll_button.remove_poll": "Remove poll", + "privacy.change": "Adjust status privacy", + "privacy.direct.long": "Visible for mentioned users only", + "privacy.direct.short": "ⵜⵓⵔⴷⵉⵜ", + "privacy.private.long": "Visible for followers only", + "privacy.private.short": "Followers-only", + "privacy.public.long": "Visible for all, shown in public timelines", + "privacy.public.short": "ⵜⴰⴳⴷⵓⴷⴰâµâµœ", + "privacy.unlisted.long": "Visible for all, but not in public timelines", + "privacy.unlisted.short": "Unlisted", + "refresh": "Refresh", + "regeneration_indicator.label": "ⴰⵣⴷⴰⵎ…", + "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "relative_time.days": "{number}â´°âµ™", + "relative_time.hours": "{number}ⵙⵔⴳ", + "relative_time.just_now": "ⴷⵖⵉ", + "relative_time.minutes": "{number}ⵙⴷ", + "relative_time.seconds": "{number}âµ™âµ", + "relative_time.today": "ⴰⵙⵙⴰ", + "reply_indicator.cancel": "ⵙⵔ", + "report.forward": "ⵙⵙⵉⴼⴹ ⵉ {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your server moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Additional comments", + "report.submit": "â´°âµ£âµ", + "report.target": "Report {target}", + "search.placeholder": "ⵔⵣⵓ", + "search_popout.search_format": "Advanced search format", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "search_popout.tips.status": "status", + "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.user": "user", + "search_results.accounts": "ⵎⵉⴷⴷâµ", + "search_results.hashtags": "ⵀⴰⵛⵟⴰⴳ", + "search_results.statuses": "Toots", + "search_results.statuses_fts_disabled": "Searching toots by their content is not enabled on this Mastodon server.", + "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "status.admin_account": "Open moderation interface for @{name}", + "status.admin_status": "Open this status in the moderation interface", + "status.block": "ⴳⴷⵠ@{name}", + "status.bookmark": "Bookmark", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "This post cannot be boosted", + "status.copy": "Copy link to status", + "status.delete": "ⴽⴽⵙ", + "status.detailed_status": "Detailed conversation view", + "status.direct": "ⵜⵓⵣⵉâµâµœ ⵜⵓⵙⵔⵉⴷⵜ ⵉ @{name}", + "status.embed": "Embed", + "status.favourite": "Favourite", + "status.filtered": "Filtered", + "status.load_more": "ⵙⵙⵉâµâµ‰ ⵓⴳⴳⴰⵔ", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "ⵓⴳⴳⴰⵔ", + "status.mute": "ⵥⵥⵉⵥⵠ@{name}", + "status.mute_conversation": "ⵥⵥⵉⵥⵠⴰⵎⵙⴰⵡⴰâµ", + "status.open": "Expand this status", + "status.pin": "Pin on profile", + "status.pinned": "Pinned toot", + "status.read_more": "âµ–âµ” ⵓⴳⴳⴰⵔ", + "status.reblog": "Boost", + "status.reblog_private": "Boost with original visibility", + "status.reblogged_by": "{name} boosted", + "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", + "status.redraft": "Delete & re-draft", + "status.remove_bookmark": "Remove bookmark", + "status.reply": "ⵔⴰⵔ", + "status.replyAll": "Reply to thread", + "status.report": "Report @{name}", + "status.sensitive_warning": "Sensitive content", + "status.share": "ⴱⴹⵓ", + "status.show_less": "ⵙⵎⴰⵠⴷⵔⵓⵙ", + "status.show_less_all": "ⵙⵎⴰⵠⴷⵔⵓⵙ ⵉ ⵎⴰⵕⵕⴰ", + "status.show_more": "ⵙⵎⴰⵠⵓⴳⴳⴰⵔ", + "status.show_more_all": "ⵙⵎⴰⵠⵓⴳⴳⴰⵔ ⵉ ⵎⴰⵕⵕⴰ", + "status.show_thread": "Show thread", + "status.uncached_media_warning": "Not available", + "status.unmute_conversation": "Unmute conversation", + "status.unpin": "Unpin from profile", + "suggestions.dismiss": "Dismiss suggestion", + "suggestions.header": "You might be interested in…", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "â´°âµ™âµâµ“ⴱⴳ", + "tabs_bar.local_timeline": "ⴰⴷⵖⴰⵔⴰâµ", + "tabs_bar.notifications": "ⵜⵉâµâµ–ⵎⵉⵙⵉâµ", + "tabs_bar.search": "ⵔⵣⵓ", + "time_remaining.days": "{number, plural, one {# ⵡⴰⵙⵙ} other {# ⵡⵓⵙⵙⴰâµ}} ⵉⵇⵇⵉⵎâµ", + "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", + "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", + "time_remaining.moments": "Moments remaining", + "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", + "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", + "timeline_hint.resources.followers": "ⵉⵎⴹⴼⴰⵕâµ", + "timeline_hint.resources.follows": "Follows", + "timeline_hint.resources.statuses": "Older toots", + "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "trends.trending_now": "Trending now", + "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "units.short.billion": "{count}B", + "units.short.million": "{count}M", + "units.short.thousand": "{count}K", + "upload_area.title": "Drag & drop to upload", + "upload_button.label": "Add images, a video or an audio file", + "upload_error.limit": "File upload limit exceeded.", + "upload_error.poll": "File upload not allowed with polls.", + "upload_form.audio_description": "Describe for people with hearing loss", + "upload_form.description": "Describe for the visually impaired", + "upload_form.edit": "âµ™âµâ´¼âµ", + "upload_form.thumbnail": "Change thumbnail", + "upload_form.undo": "ⴽⴽⵙ", + "upload_form.video_description": "Describe for people with hearing loss or visual impairment", + "upload_modal.analyzing_picture": "Analyzing picture…", + "upload_modal.apply": "Apply", + "upload_modal.choose_image": "Choose image", + "upload_modal.description_placeholder": "A quick brown fox jumps over the lazy dog", + "upload_modal.detect_text": "Detect text from picture", + "upload_modal.edit_media": "Edit media", + "upload_modal.hint": "Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.", + "upload_modal.preparing_ocr": "Preparing OCR…", + "upload_modal.preview_label": "Preview ({ratio})", + "upload_progress.label": "Uploading…", + "video.close": "ⵔⴳⵠⴰⴼⵉⴷⵢⵓ", + "video.download": "ⴰⴳⵎ ⴰⴼⴰⵢâµâµ“", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "âµ–âµ”", + "video.unmute": "Unmute sound" +} diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index ac19eb3e695ca4b4d47fba449bdb5e4aa88b39d3..6c746bf960024971e98be666c7e4d4b72b566027 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -9,14 +9,16 @@ "account.browse_more_on_origin_server": "在原始个人资料页é¢ä¸Šæµè§ˆè¯¦æƒ…", "account.cancel_follow_request": "å–æ¶ˆå…³æ³¨è¯·æ±‚", "account.direct": "å‘é€ç§ä¿¡ç»™ @{name}", + "account.disable_notifications": "当 @{name} å‘嘟时ä¸è¦é€šçŸ¥æˆ‘", "account.domain_blocked": "网站已å±è”½", "account.edit_profile": "修改个人资料", + "account.enable_notifications": "当 @{name} å‘嘟时通知我", "account.endorse": "åœ¨ä¸ªäººèµ„æ–™ä¸æŽ¨èæ¤ç”¨æˆ·", "account.follow": "关注", "account.followers": "关注者", "account.followers.empty": "ç›®å‰æ— 人关注æ¤ç”¨æˆ·ã€‚", - "account.followers_counter": "被 {count, plural, one {{counter} 人} other {{counter} 人}}关注", - "account.following_counter": "æ£åœ¨å…³æ³¨ {count, plural, other {{counter} 人}}", + "account.followers_counter": "被 {counter} 人关注", + "account.following_counter": "æ£åœ¨å…³æ³¨ {counter} 人", "account.follows.empty": "æ¤ç”¨æˆ·ç›®å‰å°šæœªå…³æ³¨ä»»ä½•人。", "account.follows_you": "å…³æ³¨äº†ä½ ", "account.hide_reblogs": "éšè—æ¥è‡ª @{name} 的转嘟", @@ -36,7 +38,7 @@ "account.requested": "æ£åœ¨ç‰å¾…å¯¹æ–¹åŒæ„ã€‚ç‚¹å‡»ä»¥å–æ¶ˆå‘é€å…³æ³¨è¯·æ±‚", "account.share": "分享 @{name} 的个人资料", "account.show_reblogs": "显示æ¥è‡ª @{name} 的转嘟", - "account.statuses_counter": "{count, plural, one {{counter} æ¡} other {{counter} æ¡}}嘟文", + "account.statuses_counter": "{counter} æ¡å˜Ÿæ–‡", "account.unblock": "解除å±è”½ @{name}", "account.unblock_domain": "ä¸å†éšè—æ¥è‡ª {domain} 的内容", "account.unendorse": "ä¸åœ¨ä¸ªäººèµ„æ–™ä¸æŽ¨èæ¤ç”¨æˆ·", @@ -131,7 +133,7 @@ "directory.local": "ä»…æ¥è‡ª {domain}", "directory.new_arrivals": "æ–°æ¥è€…", "directory.recently_active": "最近活跃", - "embed.instructions": "è¦åœ¨ä½ 的网站上嵌入这æ¡å˜Ÿæ–‡ï¼Œè¯·å¤åˆ¶ä»¥ä¸‹ä»£ç 。", + "embed.instructions": "è¦åœ¨ä½ 的网站上嵌入æ¤å˜Ÿæ–‡ï¼Œè¯·å¤åˆ¶ä»¥ä¸‹ä»£ç 。", "embed.preview": "它会åƒè¿™æ ·æ˜¾ç¤ºå‡ºæ¥ï¼š", "emoji_button.activity": "活动", "emoji_button.custom": "自定义", @@ -147,6 +149,7 @@ "emoji_button.search_results": "æœç´¢ç»“æžœ", "emoji_button.symbols": "符å·", "emoji_button.travel": "旅行和地点", + "empty_column.account_suspended": "账户被å°ç¦", "empty_column.account_timeline": "这里没有嘟文ï¼", "empty_column.account_unavailable": "个人资料ä¸å¯ç”¨", "empty_column.blocks": "ä½ ç›®å‰æ²¡æœ‰å±è”½ä»»ä½•用户。", @@ -160,13 +163,15 @@ "empty_column.hashtag": "这个è¯é¢˜æ ‡ç¾ä¸‹æš‚时没有内容。", "empty_column.home": "ä½ è¿˜æ²¡æœ‰å…³æ³¨ä»»ä½•ç”¨æˆ·ã€‚å¿«çœ‹çœ‹{public},å‘其他人问个好å§ã€‚", "empty_column.home.public_timeline": "公共时间轴", - "empty_column.list": "è¿™ä¸ªåˆ—è¡¨ä¸æš‚æ—¶æ²¡æœ‰å†…容。列表ä¸ç”¨æˆ·æ‰€å‘é€çš„的新嘟文将会在这里显示。", + "empty_column.list": "æ¤åˆ—è¡¨ä¸æš‚æ—¶æ²¡æœ‰å†…容。列表ä¸ç”¨æˆ·æ‰€å‘é€çš„的新嘟文将会在这里显示。", "empty_column.lists": "ä½ è¿˜æ²¡æœ‰åˆ›å»ºè¿‡åˆ—è¡¨ã€‚ä½ åˆ›å»ºçš„åˆ—è¡¨ä¼šåœ¨è¿™é‡Œæ˜¾ç¤ºã€‚", "empty_column.mutes": "ä½ æ²¡æœ‰éšè—任何用户。", "empty_column.notifications": "ä½ è¿˜æ²¡æœ‰æ”¶åˆ°è¿‡ä»»ä½•é€šçŸ¥ï¼Œå¿«å’Œå…¶ä»–ç”¨æˆ·äº’åŠ¨å§ã€‚", "empty_column.public": "这里什么都没有ï¼å†™ä¸€äº›å…¬å¼€çš„嘟文,或者关注其他æœåŠ¡å™¨çš„ç”¨æˆ·åŽï¼Œè¿™é‡Œå°±ä¼šæœ‰å˜Ÿæ–‡å‡ºçŽ°äº†", "error.unexpected_crash.explanation": "æ¤é¡µé¢æ— 法æ£ç¡®æ˜¾ç¤ºï¼Œè¿™å¯èƒ½æ˜¯å› 为我们的代ç 䏿œ‰é”™è¯¯ï¼Œä¹Ÿå¯èƒ½æ˜¯å› 为æµè§ˆå™¨å…¼å®¹é—®é¢˜ã€‚", + "error.unexpected_crash.explanation_addons": "æ¤é¡µé¢æ— 法æ£ç¡®æ˜¾ç¤ºï¼Œè¿™ä¸ªé”™è¯¯å¾ˆå¯èƒ½æ˜¯ç”±æµè§ˆå™¨é™„åŠ ç»„ä»¶æˆ–è‡ªåŠ¨ç¿»è¯‘å·¥å…·é€ æˆçš„。", "error.unexpected_crash.next_steps": "刷新一下页é¢è¯•试。如果没用,您å¯ä»¥æ¢ä¸ªæµè§ˆå™¨æˆ–者用本地应用。", + "error.unexpected_crash.next_steps_addons": "请å°è¯•ç¦ç”¨å®ƒä»¬å¹¶åˆ·æ–°é¡µé¢ã€‚å¦‚æžœæ²¡æœ‰å¸®åŠ©ï¼Œä½ ä»å¯ä»¥å°è¯•使用其他æµè§ˆå™¨æˆ–原生应用æ¥ä½¿ç”¨ Mastodon。", "errors.unexpected_crash.copy_stacktrace": "æŠŠå †æ ˆè·Ÿè¸ªä¿¡æ¯å¤åˆ¶åˆ°å‰ªè´´æ¿", "errors.unexpected_crash.report_issue": "报告问题", "follow_request.authorize": "åŒæ„", @@ -250,9 +255,10 @@ "keyboard_shortcuts.unfocus": "å–æ¶ˆè¾“å…¥", "keyboard_shortcuts.up": "在列表ä¸è®©å…‰æ ‡ä¸Šç§»", "lightbox.close": "å…³é—", + "lightbox.compress": "返回图片全览", + "lightbox.expand": "放大查看图片", "lightbox.next": "下一个", "lightbox.previous": "上一个", - "lightbox.view_context": "查看上下文", "lists.account.add": "æ·»åŠ åˆ°åˆ—è¡¨", "lists.account.remove": "从列表ä¸ç§»é™¤", "lists.delete": "åˆ é™¤åˆ—è¡¨", @@ -260,6 +266,10 @@ "lists.edit.submit": "æ›´æ”¹æ ‡é¢˜", "lists.new.create": "新建列表", "lists.new.title_placeholder": "æ–°åˆ—è¡¨çš„æ ‡é¢˜", + "lists.replies_policy.followed": "任何被关注的用户", + "lists.replies_policy.list": "列表æˆå‘˜", + "lists.replies_policy.none": "没有人", + "lists.replies_policy.title": "显示回å¤ç»™ï¼š", "lists.search": "æœç´¢ä½ 关注的人", "lists.subheading": "ä½ çš„åˆ—è¡¨", "load_pending": "{count} 项", @@ -267,7 +277,9 @@ "media_gallery.toggle_visible": "éšè— {number} å¼ å›¾ç‰‡", "missing_indicator.label": "找ä¸åˆ°å†…容", "missing_indicator.sublabel": "æ— æ³•æ‰¾åˆ°æ¤èµ„æº", + "mute_modal.duration": "æŒç»æœŸé—´", "mute_modal.hide_notifications": "åŒæ—¶éšè—æ¥è‡ªè¿™ä¸ªç”¨æˆ·çš„通知?", + "mute_modal.indefinite": "æ— æœŸé™", "navigation_bar.apps": "移动应用", "navigation_bar.blocks": "å·²å±è”½çš„用户", "navigation_bar.bookmarks": "书ç¾", @@ -298,6 +310,7 @@ "notification.own_poll": "您的投票已ç»ç»“æŸ", "notification.poll": "ä½ å‚与的一个投票已ç»ç»“æŸ", "notification.reblog": "{name} è½¬å˜Ÿäº†ä½ çš„å˜Ÿæ–‡", + "notification.status": "{name} 刚刚å‘嘟", "notifications.clear": "清空通知列表", "notifications.clear_confirmation": "ä½ ç¡®å®šè¦æ°¸ä¹…清空通知列表å—?", "notifications.column_settings.alert": "桌é¢é€šçŸ¥", @@ -313,13 +326,24 @@ "notifications.column_settings.reblog": "å½“æœ‰äººè½¬å˜Ÿäº†ä½ çš„å˜Ÿæ–‡æ—¶ï¼š", "notifications.column_settings.show": "åœ¨é€šçŸ¥æ æ˜¾ç¤º", "notifications.column_settings.sound": "æ’æ”¾éŸ³æ•ˆ", + "notifications.column_settings.status": "新嘟文:", "notifications.filter.all": "全部", "notifications.filter.boosts": "转嘟", "notifications.filter.favourites": "喜欢", "notifications.filter.follows": "关注", "notifications.filter.mentions": "æåŠ", "notifications.filter.polls": "投票结果", + "notifications.filter.statuses": "ä½ å…³æ³¨çš„äººçš„åŠ¨æ€", + "notifications.grant_permission": "授予æƒé™", "notifications.group": "{count} æ¡é€šçŸ¥", + "notifications.mark_as_read": "å°†æ‰€æœ‰é€šçŸ¥æ ‡ä¸ºå·²è¯»", + "notifications.permission_denied": "由于æƒé™è¢«æ‹’ç»ï¼Œæ— 法å¯ç”¨æ¡Œé¢é€šçŸ¥ã€‚", + "notifications.permission_denied_alert": "由于在æ¤ä¹‹å‰æµè§ˆå™¨æƒé™è¯·æ±‚就已被拒ç»ï¼Œæ‰€ä»¥å¯ç”¨æ¡Œé¢é€šçŸ¥å¤±è´¥", + "notifications.permission_required": "所需æƒé™æœªè¢«æŽˆäºˆï¼Œæ‰€ä»¥æ¡Œé¢é€šçŸ¥ä¸å¯ç”¨", + "notifications_permission_banner.enable": "å¯ç”¨æ¡Œé¢é€šçŸ¥", + "notifications_permission_banner.how_to_control": "å¯ç”¨æ¡Œé¢é€šçŸ¥ä»¥åœ¨ Mastodon 未打开时接收通知。您å¯ä»¥é€šè¿‡äº¤äº’通过上é¢çš„ {icon} 按钮æ¥ç²¾ç»†æŽ§åˆ¶å¯ä»¥å‘逿¡Œé¢é€šçŸ¥çš„交互类型。", + "notifications_permission_banner.title": "精彩ä¸å®¹é”™è¿‡", + "picture_in_picture.restore": "æ¢å¤", "poll.closed": "已关é—", "poll.refresh": "刷新", "poll.total_people": "{count}人", @@ -328,7 +352,7 @@ "poll.voted": "您已ç»å¯¹è¿™ä¸ªç”案投过票了", "poll_button.add_poll": "å‘起投票", "poll_button.remove_poll": "移除投票", - "privacy.change": "设置嘟文å¯è§èŒƒå›´", + "privacy.change": "设置嘟文的å¯è§èŒƒå›´", "privacy.direct.long": "åªæœ‰è¢«æåŠçš„用户能看到", "privacy.direct.short": "ç§ä¿¡", "privacy.private.long": "åªæœ‰å…³æ³¨ä½ 的用户能看到", @@ -379,11 +403,11 @@ "status.favourite": "喜欢", "status.filtered": "已过滤", "status.load_more": "åŠ è½½æ›´å¤š", - "status.media_hidden": "éšè—媒体内容", + "status.media_hidden": "å·²éšè—的媒体内容", "status.mention": "æåŠ @{name}", "status.more": "更多", "status.mute": "éšè— @{name}", - "status.mute_conversation": "éšè—æ¤å¯¹è¯", + "status.mute_conversation": "å°†æ¤å¯¹è¯é™éŸ³", "status.open": "展开嘟文", "status.pin": "在个人资料页é¢ç½®é¡¶", "status.pinned": "置顶嘟文", @@ -405,7 +429,7 @@ "status.show_more_all": "显示所有内容", "status.show_thread": "显示全部对è¯", "status.uncached_media_warning": "æš‚ä¸å¯ç”¨", - "status.unmute_conversation": "ä¸å†éšè—æ¤å¯¹è¯", + "status.unmute_conversation": "å°†æ¤å¯¹è¯è§£é™¤é™éŸ³", "status.unpin": "在个人资料页é¢å–消置顶", "suggestions.dismiss": "å…³é—建议", "suggestions.header": "您å¯èƒ½ä¼šæ„Ÿå…´è¶£â€¦", @@ -426,11 +450,11 @@ "trends.counter_by_accounts": "{count, plural, one {{counter} 人} other {{counter} 人}}æ£åœ¨è®¨è®º", "trends.trending_now": "现在æµè¡Œ", "ui.beforeunload": "å¦‚æžœä½ çŽ°åœ¨ç¦»å¼€ Mastodonï¼Œä½ çš„è‰ç¨¿å†…容将会丢失。", - "units.short.billion": "{count}å亿", - "units.short.million": "{count}百万", - "units.short.thousand": "{count}åƒ", + "units.short.billion": "{count}B", + "units.short.million": "{count}M", + "units.short.thousand": "{count}K", "upload_area.title": "将文件拖放到æ¤å¤„å¼€å§‹ä¸Šä¼ ", - "upload_button.label": "ä¸Šä¼ åª’ä½“æ–‡ä»¶ ({formats})", + "upload_button.label": "ä¸Šä¼ å›¾ç‰‡ã€è§†é¢‘或音频", "upload_error.limit": "文件大å°è¶…过é™åˆ¶ã€‚", "upload_error.poll": "投票ä¸ä¸å…è®¸ä¸Šä¼ æ–‡ä»¶ã€‚", "upload_form.audio_description": "为å¬éšœäººå£«æ·»åŠ æ–‡å—æè¿°", @@ -446,6 +470,7 @@ "upload_modal.detect_text": "ä»Žå›¾ç‰‡ä¸æ£€æµ‹æ–‡æœ¬", "upload_modal.edit_media": "编辑媒体", "upload_modal.hint": "在预览图上点击或拖动圆圈,以选择缩略图的焦点。", + "upload_modal.preparing_ocr": "æ£åœ¨å‡†å¤‡æ–‡å—识别……", "upload_modal.preview_label": "预览 ({ratio})", "upload_progress.label": "ä¸Šä¼ ä¸â€¦â€¦", "video.close": "å…³é—视频", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 24a63ab6b3872950a8bec8c5cb899807e592af22..1a62ccbb38f2cdc8eec3d2aa29544c59d024483f 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -1,28 +1,30 @@ { - "account.account_note_header": "Note", - "account.add_or_remove_from_list": "從å單䏿–°å¢žæˆ–移除", + "account.account_note_header": "ç†è¨˜", + "account.add_or_remove_from_list": "å¾žåˆ—è¡¨ä¸æ–°å¢žæˆ–移除", "account.badges.bot": "機械人", "account.badges.group": "群組", "account.block": "å°éŽ– @{name}", - "account.block_domain": "éš±è—來自 {domain} çš„ä¸€åˆ‡æ–‡ç« ", - "account.blocked": "å°éŽ–", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.block_domain": "å°éŽ–ä¾†è‡ª {domain} çš„ä¸€åˆ‡æ–‡ç« ", + "account.blocked": "å·²å°éŽ–", + "account.browse_more_on_origin_server": "ç€è¦½åŽŸæœå‹™ç«™ä¸Šçš„個人資料é ", "account.cancel_follow_request": "å–æ¶ˆé—œæ³¨è«‹æ±‚", "account.direct": "ç§è¨Š @{name}", - "account.domain_blocked": "æœå‹™ç«™è¢«éš±è—", + "account.disable_notifications": "如果 @{name} 發文請ä¸è¦å†é€šçŸ¥æˆ‘", + "account.domain_blocked": "æœå‹™ç«™è¢«å°éŽ–", "account.edit_profile": "修改個人資料", - "account.endorse": "åœ¨å€‹äººè³‡æ–™æŽ¨è–¦å°æ–¹", - "account.follow": "關注", - "account.followers": "關注的人", - "account.followers.empty": "尚沒有人關注這ä½ä½¿ç”¨è€…。", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", - "account.follows.empty": "這ä½ä½¿ç”¨è€…尚未關注任何使用者。", + "account.enable_notifications": "如果 @{name} 發文請通知我", + "account.endorse": "åœ¨å€‹äººè³‡æ–™é æŽ¨è–¦å°æ–¹", + "account.follow": "æ£åœ¨é—œæ³¨", + "account.followers": "關注者", + "account.followers.empty": "尚未有人關注這ä½ä½¿ç”¨è€…。", + "account.followers_counter": "有 {count, plural,one {{counter} 個} other {{counter} 個}}關注者", + "account.following_counter": "æ£åœ¨é—œæ³¨ {count, plural,one {{counter}}other {{counter} 人}}", + "account.follows.empty": "這ä½ä½¿ç”¨è€…尚未關注任何人。", "account.follows_you": "é—œæ³¨ä½ ", "account.hide_reblogs": "éš±è— @{name} 的轉推", "account.last_status": "ä¸Šæ¬¡æ´»èºæ™‚é–“", "account.link_verified_on": "æ¤é€£çµçš„æ‰€æœ‰æ¬Šå·²åœ¨ {date} 檢查éŽ", - "account.locked_info": "æ¤ç”¨æˆ¶çš„ç§éš±ç‹€æ…‹ç‚ºä¸å…¬é–‹ï¼Œé—œæ³¨è«‹æ±‚需經éŽè©²ç”¨æˆ¶çš„å¯©æ ¸ã€‚", + "account.locked_info": "這ä½ä½¿ç”¨è€…å°‡ç§éš±è¨å®šç‚ºã€Œä¸å…¬é–‹ã€ï¼Œæœƒæ‰‹å‹•審批誰能關注他/她。", "account.media": "媒體", "account.mention": "æåŠ @{name}", "account.moved_to": "{name} 已經é·ç§»åˆ°ï¼š", @@ -36,15 +38,15 @@ "account.requested": "ç‰å€™å¯©æ‰¹", "account.share": "分享 @{name} 的個人資料", "account.show_reblogs": "顯示 @{name} 的推文", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural,one {{counter} 篇}other {{counter} 篇}}æ–‡ç« ", "account.unblock": "è§£é™¤å° @{name} çš„å°éŽ–", - "account.unblock_domain": "ä¸å†éš±è— {domain}", + "account.unblock_domain": "解除å°åŸŸå {domain} çš„å°éŽ–", "account.unendorse": "ä¸å†æ–¼å€‹äººè³‡æ–™é é¢æŽ¨è–¦å°æ–¹", "account.unfollow": "å–æ¶ˆé—œæ³¨", "account.unmute": "å–æ¶ˆ @{name} çš„éœéŸ³", "account.unmute_notifications": "å–æ¶ˆä¾†è‡ª @{name} 通知的éœéŸ³", - "account_note.placeholder": "Click to add a note", - "alert.rate_limited.message": "請在 {retry_time, time, medium} éŽå¾Œé‡è©¦", + "account_note.placeholder": "æŒ‰æ¤æ·»åŠ å‚™æ³¨", + "alert.rate_limited.message": "請在 {retry_time, time, medium} 後é‡è©¦", "alert.rate_limited.title": "å·²é™é€Ÿ", "alert.unexpected.message": "發生ä¸å¯é 期的錯誤。", "alert.unexpected.title": "噢ï¼", @@ -57,12 +59,12 @@ "bundle_modal_error.close": "關閉", "bundle_modal_error.message": "åŠ è¼‰æœ¬çµ„ä»¶å‡ºéŒ¯ã€‚", "bundle_modal_error.retry": "é‡è©¦", - "column.blocks": "å°éŽ–ç”¨æˆ¶", + "column.blocks": "å°éŽ–åå–®", "column.bookmarks": "書籤", "column.community": "本站時間軸", "column.direct": "個人訊æ¯", "column.directory": "ç€è¦½å€‹äººè³‡æ–™", - "column.domain_blocks": "éš±è—çš„æœå‹™ç«™", + "column.domain_blocks": "å°éŽ–çš„æœå‹™ç«™", "column.favourites": "æœ€æ„›çš„æ–‡ç« ", "column.follow_requests": "關注請求", "column.home": "主é ", @@ -75,25 +77,25 @@ "column_header.hide_settings": "éš±è—è¨å®š", "column_header.moveLeft_settings": "將欄左移", "column_header.moveRight_settings": "將欄å³ç§»", - "column_header.pin": "固定", + "column_header.pin": "ç½®é ‚", "column_header.show_settings": "顯示è¨å®š", - "column_header.unpin": "å–下", + "column_header.unpin": "å–æ¶ˆç½®é ‚", "column_subheading.settings": "è¨å®š", - "community.column_settings.local_only": "åªæœ‰æœ¬åœ°", - "community.column_settings.media_only": "僅媒體", - "community.column_settings.remote_only": "åªæœ‰é 端", - "compose_form.direct_message_warning": "é€™æ–‡ç« åªæœ‰è¢«æåŠçš„用戶æ‰å¯ä»¥çœ‹åˆ°ã€‚", + "community.column_settings.local_only": "åªé¡¯ç¤ºæœ¬ç«™", + "community.column_settings.media_only": "åªé¡¯ç¤ºå¤šåª’é«”", + "community.column_settings.remote_only": "åªé¡¯ç¤ºå¤–ç«™", + "compose_form.direct_message_warning": "é€™æ–‡ç« åªæœ‰è¢«æåŠçš„使用者æ‰å¯ä»¥çœ‹åˆ°ã€‚", "compose_form.direct_message_warning_learn_more": "了解更多", "compose_form.hashtag_warning": "é€™æ–‡ç« å› ç‚ºä¸æ˜¯å…¬é–‹ï¼Œæ‰€ä»¥ä¸æœƒè¢«æ¨™ç±¤æœç´¢ã€‚åªæœ‰å…¬é–‹çš„æ–‡ç« æ‰æœƒè¢«æ¨™ç±¤æœç´¢ã€‚", - "compose_form.lock_disclaimer": "ä½ çš„ç”¨æˆ¶ç‹€æ…‹ç‚ºã€Œ{locked}ã€ï¼Œä»»ä½•人都能立å³é—œæ³¨ä½ ï¼Œç„¶å¾Œçœ‹åˆ°ã€Œåªæœ‰é—œæ³¨è€…能看ã€çš„æ–‡ç« 。", - "compose_form.lock_disclaimer.lock": "公共", + "compose_form.lock_disclaimer": "ä½ çš„ç”¨æˆ¶ç‹€æ…‹æ²’æœ‰{locked},任何人都能立å³é—œæ³¨ä½ ï¼Œç„¶å¾Œçœ‹åˆ°ã€Œåªæœ‰é—œæ³¨è€…能看ã€çš„æ–‡ç« 。", + "compose_form.lock_disclaimer.lock": "鎖定", "compose_form.placeholder": "ä½ åœ¨æƒ³ç”šéº¼ï¼Ÿ", "compose_form.poll.add_option": "æ–°å¢žé¸æ“‡", "compose_form.poll.duration": "投票期é™", "compose_form.poll.option_placeholder": "第 {number} 個鏿“‡", "compose_form.poll.remove_option": "移除æ¤é¸æ“‡", "compose_form.poll.switch_to_multiple": "變更投票為å…許多個é¸é …", - "compose_form.poll.switch_to_single": "變更投票為å…許單一é¸é …", + "compose_form.poll.switch_to_single": "變更投票為é™å®šå–®ä¸€é¸é …", "compose_form.publish": "發文", "compose_form.publish_loud": "{publish}ï¼", "compose_form.sensitive.hide": "æ¨™è¨˜åª’é«”ç‚ºæ•æ„Ÿå…§å®¹", @@ -110,8 +112,8 @@ "confirmations.delete.message": "ä½ ç¢ºå®šè¦åˆªé™¤é€™æ–‡ç« 嗎?", "confirmations.delete_list.confirm": "刪除", "confirmations.delete_list.message": "ä½ ç¢ºå®šè¦æ°¸ä¹…刪除這列表嗎?", - "confirmations.domain_block.confirm": "éš±è—æ•´å€‹ç¶²ç«™", - "confirmations.domain_block.message": "ä½ çœŸçš„çœŸçš„ç¢ºå®šè¦éš±è—整個 {domain} ?多數情æ³ä¸‹ï¼Œæ¯”較推薦å°éŽ–æˆ–éœéŸ³å¹¾å€‹ç‰¹å®šç›®æ¨™å°±å¥½ã€‚ä½ å¾žæ¤å°‡ä¸æœƒå†çœ‹åˆ°è©²ç«™çš„內容和通知。來自該站的關注者亦會被移除。", + "confirmations.domain_block.confirm": "å°éŽ–æ•´å€‹ç¶²ç«™", + "confirmations.domain_block.message": "ä½ çœŸçš„çœŸçš„ç¢ºå®šè¦å°éŽ–æ•´å€‹ {domain} ?多數情æ³ä¸‹ï¼Œå°éŽ–æˆ–éœéŸ³å¹¾å€‹ç‰¹å®šç›®æ¨™å°±å·²ç¶“有效,也是比較建è°çš„åšæ³•。若然å°éŽ–å…¨ç«™ï¼Œä½ å°‡ä¸æœƒå†åœ¨é€™è£çœ‹åˆ°è©²ç«™çš„內容和通知。來自該站的關注者亦會被移除。", "confirmations.logout.confirm": "登出", "confirmations.logout.message": "確定è¦ç™»å‡ºå—Žï¼Ÿ", "confirmations.mute.confirm": "éœéŸ³", @@ -127,9 +129,9 @@ "conversation.mark_as_read": "標為已讀", "conversation.open": "檢視å°è©±", "conversation.with": "與 {names}", - "directory.federated": "來自已知è¯é‚¦å®‡å®™", + "directory.federated": "來自已知的è¯ç›Ÿç¶²çµ¡", "directory.local": "僅來自 {domain}", - "directory.new_arrivals": "新貨", + "directory.new_arrivals": "新內容", "directory.recently_active": "最近活èº", "embed.instructions": "è¦å…§åµŒæ¤æ–‡ç« ï¼Œè«‹å°‡ä»¥ä¸‹ä»£ç¢¼è²¼é€²ä½ çš„ç¶²ç«™ã€‚", "embed.preview": "看上去會是這樣:", @@ -139,7 +141,7 @@ "emoji_button.food": "飲飲食食", "emoji_button.label": "åŠ å…¥è¡¨æƒ…ç¬¦è™Ÿ", "emoji_button.nature": "自然", - "emoji_button.not_found": "沒有表情符號ï¼ï¼ (╯°□°)╯︵ â”»â”â”»", + "emoji_button.not_found": "沒找到表情符號ï¼ï¼ (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "物å“", "emoji_button.people": "人物", "emoji_button.recent": "常用", @@ -147,6 +149,7 @@ "emoji_button.search_results": "æœå°‹çµæžœ", "emoji_button.symbols": "符號", "emoji_button.travel": "æ—…éŠæ™¯ç‰©", + "empty_column.account_suspended": "å¸³è™Ÿå·²åœæ¬Š", "empty_column.account_timeline": "這裡還沒有嘟文ï¼", "empty_column.account_unavailable": "無法å–得個人資料", "empty_column.blocks": "ä½ é‚„æ²’æœ‰å°éŽ–ä»»ä½•ä½¿ç”¨è€…ã€‚", @@ -154,11 +157,11 @@ "empty_column.community": "本站時間軸暫時未有內容,快寫一點æ±è¥¿ä¾†æ¶é 香啊ï¼", "empty_column.direct": "ä½ æ²’æœ‰å€‹äººè¨Šæ¯ã€‚ç•¶ä½ ç™¼å‡ºæˆ–æŽ¥æ”¶å€‹äººè¨Šæ¯ï¼Œå°±æœƒåœ¨é€™è£¡å‡ºç¾ã€‚", "empty_column.domain_blocks": "尚未隱è—任何網域。", - "empty_column.favourited_statuses": "ä½ é‚„æ²’æ”¶è—ä»»ä½•å˜Ÿæ–‡ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ æ”¶è—的嘟文。", - "empty_column.favourites": "還沒有人收è—這則嘟文。這裡將會顯示被收è—的嘟文。", + "empty_column.favourited_statuses": "ä½ é‚„æ²’æ”¶è—ä»»ä½•æ–‡ç« ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ æ”¶è—的嘟文。", + "empty_column.favourites": "還沒有人收è—é€™å‰‡æ–‡ç« ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºè¢«æ”¶è—的嘟文。", "empty_column.follow_requests": "您尚未收到任何關注請求。這裡將會顯示收到的關注請求。", "empty_column.hashtag": "這個標籤暫時未有內容。", - "empty_column.home": "ä½ é‚„æ²’æœ‰é—œæ³¨ä»»ä½•ç”¨æˆ¶ã€‚å¿«çœ‹çœ‹{public},å‘其他用戶æè¨•å§ã€‚", + "empty_column.home": "ä½ é‚„æ²’æœ‰é—œæ³¨ä»»ä½•ä½¿ç”¨è€…ã€‚å¿«çœ‹çœ‹{public},å‘其他使用者æè¨•å§ã€‚", "empty_column.home.public_timeline": "公共時間軸", "empty_column.list": "這個列表暫時未有內容。", "empty_column.lists": "ä½ é‚„æ²’æœ‰å»ºç«‹ä»»ä½•åå–®ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ æ‰€å»ºç«‹çš„å單。", @@ -166,20 +169,22 @@ "empty_column.notifications": "ä½ æ²’æœ‰ä»»ä½•é€šçŸ¥ç´€éŒ„ï¼Œå¿«å‘其他用戶æè¨•å§ã€‚", "empty_column.public": "跨站時間軸暫時沒有內容ï¼å¿«å¯«ä¸€äº›å…¬å…±çš„æ–‡ç« ,或者關注å¦ä¸€äº›æœå‹™ç«™çš„用戶å§ï¼ä½ 和本站ã€å‹ç«™çš„交æµï¼Œå°‡æ±ºå®šé€™è£å‡ºç¾çš„內容。", "error.unexpected_crash.explanation": "由於發生系統故障或ç€è¦½å™¨ç›¸å®¹æ€§å•題,故無法æ£å¸¸é¡¯ç¤ºé é¢ã€‚", + "error.unexpected_crash.explanation_addons": "æ¤é é¢ç„¡æ³•被æ£ç¢ºé¡¯ç¤ºï¼Œé€™å¯èƒ½æ˜¯ç”±æ–¼ç€è¦½å™¨çš„é™„åŠ å…ƒä»¶æˆ–ç¶²é 自動翻è¯å·¥å…·é€ æˆçš„。", "error.unexpected_crash.next_steps": "è«‹å˜—è©¦é‡æ–°æ•´ç†é é¢ã€‚å¦‚æžœç‹€æ³æ²’æœ‰é€²å±•ï¼Œä½ å¯ä»¥ä½¿ç”¨ä¸åŒçš„ç€è¦½å™¨æˆ– Mastodon 應用程å¼ä¾†æª¢è¦–。", - "errors.unexpected_crash.copy_stacktrace": "複製到剪貼簿", + "error.unexpected_crash.next_steps_addons": "è«‹å˜—è©¦åœæ¢ä½¿ç”¨é€™äº›é™„åŠ å…ƒä»¶ç„¶å¾Œé‡æ–°è¼‰å…¥é é¢ã€‚如果å•é¡Œæ²’æœ‰è§£æ±ºï¼Œä½ ä»ç„¶å¯ä»¥ä½¿ç”¨ä¸åŒçš„ç€è¦½å™¨æˆ– Mastodon 應用程å¼ä¾†æª¢è¦–。", + "errors.unexpected_crash.copy_stacktrace": "複製 stacktrace 到剪貼簿", "errors.unexpected_crash.report_issue": "èˆ‰å ±å•題", "follow_request.authorize": "批准", "follow_request.reject": "拒絕", - "follow_requests.unlocked_explanation": "å³ä¾¿æ‚¨çš„帳號未被鎖定,{domain} 的員工èªç‚ºå¯èƒ½æƒ³è¦è‡ªå·±å¯©æ ¸é€™äº›å¸³è™Ÿçš„追蹤請求。", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "å³ä½¿æ‚¨çš„帳戶未上鎖,{domain} 的工作人員èªç‚ºæ‚¨å¯èƒ½æƒ³æ‰‹å‹•å¯©æ ¸ä¾†è‡ªé€™äº›å¸³æˆ¶çš„é—œæ³¨è«‹æ±‚ã€‚", + "generic.saved": "已儲å˜", "getting_started.developers": "開發者", "getting_started.directory": "個人資料目錄", "getting_started.documentation": "文件", "getting_started.heading": "開始使用", "getting_started.invite": "邀請使用者", - "getting_started.open_source_notice": "Mastodon(è¬è±¡ï¼‰æ˜¯ä¸€å€‹é–‹æ”¾æºç¢¼çš„è»Ÿä»¶ã€‚ä½ å¯ä»¥åœ¨å®˜æ–¹ GitHub ({github}) è²¢ç»æˆ–è€…å›žå ±å•題。", - "getting_started.security": "帳戶安全", + "getting_started.open_source_notice": "Mastodon(è¬è±¡ï¼‰æ˜¯ä¸€å€‹é–‹æ”¾æºç¢¼çš„è»Ÿä»¶ã€‚ä½ å¯ä»¥åœ¨å®˜æ–¹ GitHub {github} è²¢ç»æˆ–è€…å›žå ±å•題。", + "getting_started.security": "帳戶è¨å®š", "getting_started.terms": "æœå‹™æ¢æ¬¾", "hashtag.column_header.tag_mode.all": "以åŠ{additional}", "hashtag.column_header.tag_mode.any": "或是{additional}", @@ -189,7 +194,7 @@ "hashtag.column_settings.tag_mode.all": "全部", "hashtag.column_settings.tag_mode.any": "任一", "hashtag.column_settings.tag_mode.none": "å…¨ä¸", - "hashtag.column_settings.tag_toggle": "Include additional tags in this column", + "hashtag.column_settings.tag_toggle": "在這欄ä½åŠ å…¥é¡å¤–的標籤", "home.column_settings.basic": "基本", "home.column_settings.show_reblogs": "é¡¯ç¤ºè¢«è½‰æŽ¨çš„æ–‡ç« ", "home.column_settings.show_replies": "é¡¯ç¤ºå›žæ‡‰æ–‡ç« ", @@ -199,24 +204,24 @@ "intervals.full.hours": "{number, plural, one {# å°æ™‚} other {# å°æ™‚}}", "intervals.full.minutes": "{number, plural, one {# 分é˜} other {# 分é˜}}", "introduction.federation.action": "下一æ¥", - "introduction.federation.federated.headline": "ç«™å°è¯ç›Ÿ", - "introduction.federation.federated.text": "來自è¯ç›Ÿå®‡å®™ä¸å…¶ä»–ç«™å°çš„公開嘟文將會在站點è¯ç›Ÿæ™‚間軸ä¸é¡¯ç¤ºã€‚", + "introduction.federation.federated.headline": "已知æœå‹™ç«™", + "introduction.federation.federated.text": "來自社交è¯ç›Ÿå…¶ä»–ç¶²ç«™çš„å…¬é–‹æ–‡ç« ï¼Œå°‡æœƒé¡¯ç¤ºåœ¨ç«™é»žè·¨ç«™æ™‚é–“è»¸ä¸Šã€‚", "introduction.federation.home.headline": "首é ", - "introduction.federation.home.text": "ä½ é—œæ³¨ä½¿ç”¨è€…çš„å˜Ÿæ–‡å°‡æœƒåœ¨é¦–é å‹•æ…‹ä¸é¡¯ç¤ºã€‚ä½ å¯ä»¥é—œæ³¨ä»»ä½•伺æœå™¨ä¸Šçš„任何人ï¼", - "introduction.federation.local.headline": "本機", - "introduction.federation.local.text": "跟您åŒä¼ºæœå™¨ä¹‹ä½¿ç”¨è€…所發的公開嘟文將會顯示在本機時間軸ä¸ã€‚", - "introduction.interactions.action": "Finish toot-orial!", - "introduction.interactions.favourite.headline": "關注", - "introduction.interactions.favourite.text": "您能儲å˜å˜Ÿæ–‡ä¾›ç¨å€™è§€çœ‹ï¼Œæˆ–者收è—å˜Ÿæ–‡ï¼Œè®“ä½œè€…çŸ¥é“æ‚¨å–œæ¡é€™å‰‡å˜Ÿæ–‡ã€‚", - "introduction.interactions.reblog.headline": "轉嘟", - "introduction.interactions.reblog.text": "您能藉由轉嘟他人嘟文來分享給您的關注者。", + "introduction.federation.home.text": "ä½ æ‰€é—œæ³¨ä½¿ç”¨è€…çš„æ–‡ç« ï¼Œå°‡æœƒåœ¨é¦–é å‹•æ…‹ä¸é¡¯ç¤ºã€‚ä½ å¯ä»¥é—œæ³¨ä»»ä½•伺æœå™¨ä¸Šçš„任何人ï¼", + "introduction.federation.local.headline": "本站", + "introduction.federation.local.text": "èˆ‡ä½ å…±ç”¨ä¸€å€‹æœå‹™ç«™ä½¿ç”¨è€…çš„å…¬é–‹æ–‡ç« ï¼Œå°‡æœƒé¡¯ç¤ºåœ¨æœ¬ç«™æ™‚é–“è»¸ä¸ã€‚", + "introduction.interactions.action": "完æˆä½¿ç”¨æ•™å¸", + "introduction.interactions.favourite.headline": "最愛", + "introduction.interactions.favourite.text": "ä½ èƒ½ç”¨å°‡æ–‡ç« åŠ å…¥ã€Œæœ€æ„›çš„æ–‡ç« ã€ï¼Œä¸€æ–¹ä¾¿æŠŠå„²å˜æ–‡ç« ç¨å€™è§€çœ‹ï¼Œä¹ŸåŒæ™‚å°ä½œè€…表示支æŒã€‚", + "introduction.interactions.reblog.headline": "轉推", + "introduction.interactions.reblog.text": "ä½ å¯ä»¥é€éŽã€Œè½‰æŽ¨æ–‡ç« ã€æŠŠæ–‡ç« åˆ†äº«çµ¦ä½ çš„é—œæ³¨è€…ã€‚", "introduction.interactions.reply.headline": "回覆", - "introduction.interactions.reply.text": "æ‚¨èƒ½å›žè¦†å…¶ä»–äººæˆ–è‡ªå·±çš„å˜Ÿæ–‡ï¼Œé€™éº¼åšæœƒæŠŠé€™äº›å›žè¦†ä¸²æˆä¸€ä¸²å°è©±ã€‚", + "introduction.interactions.reply.text": "ä½ å¯ä»¥å›žè¦†å…¶ä»–äººæˆ–è‡ªå·±çš„æ–‡ç« ï¼Œé€™éº¼åšæœƒæŠŠé€™äº›å›žè¦†ä¸²æˆä¸€ä¸²å°è©±ã€‚", "introduction.welcome.action": "開始旅程å§ï¼", "introduction.welcome.headline": "第一æ¥", - "introduction.welcome.text": "æ¡è¿Žä¾†åˆ°è¯ç›Ÿå®‡å®™ï¼ç‰ç‰ä½ å°±å¯ä»¥å»£æ’訊æ¯åŠè·¨è¶Šå„種å„å¼å„樣的伺æœå™¨èˆ‡æœ‹å‹èŠå¤©ã€‚但這å°ä¼ºæœå™¨ï¼Œ{domain},éžå¸¸ç‰¹åˆ¥ - å®ƒå¯„ç®¡äº†ä½ çš„å€‹äººè³‡æ–™ï¼Œæ‰€ä»¥è«‹è¨˜ä½å®ƒçš„åå—。", - "keyboard_shortcuts.back": "後退", - "keyboard_shortcuts.blocked": "開啟「å°éŽ–ä½¿ç”¨è€…ã€åå–®", + "introduction.welcome.text": "æ¡è¿Žä¾†åˆ°è¯ç›Ÿç¤¾äº¤ç¶²çµ¡ (fediverse)ï¼ç¨å¾Œä½ å°±å¯ä»¥å»£æ’訊æ¯ï¼ŒåŒæ™‚與多個æœå‹™ç«™çš„ä¸åŒæœ‹å‹èŠå¤©ã€‚ä½†ç•™æ„ {domain} 這個æœå‹™ç«™éžå¸¸ç‰¹åˆ¥â€”â€”å®ƒè¨—ç®¡äº†ä½ çš„å€‹äººè³‡æ–™å•Šï¼æ‰€ä»¥è«‹è¨˜ä½å®ƒã€‚", + "keyboard_shortcuts.back": "返回", + "keyboard_shortcuts.blocked": "開啟å°éŽ–åå–®", "keyboard_shortcuts.boost": "轉推", "keyboard_shortcuts.column": "把標示移動到其ä¸ä¸€åˆ—", "keyboard_shortcuts.compose": "把標示移動到文å—輸入å€", @@ -224,35 +229,36 @@ "keyboard_shortcuts.direct": "開啟ç§è¨Šæ¬„", "keyboard_shortcuts.down": "在列表往下移動", "keyboard_shortcuts.enter": "æ‰“é–‹æ–‡ç« ", - "keyboard_shortcuts.favourite": "æ”¶è—", - "keyboard_shortcuts.favourites": "開啟收è—åå–®", - "keyboard_shortcuts.federated": "開啟站點è¯ç›Ÿæ™‚間軸", + "keyboard_shortcuts.favourite": "æ”¶è—æ–‡ç« ", + "keyboard_shortcuts.favourites": "開啟最愛的內容", + "keyboard_shortcuts.federated": "打開跨站時間軸", "keyboard_shortcuts.heading": "éµç›¤å¿«é€Ÿéµ", - "keyboard_shortcuts.home": "é–‹å•Ÿé¦–é æ™‚間軸", + "keyboard_shortcuts.home": "開啟個人時間軸", "keyboard_shortcuts.hotkey": "快速éµ", "keyboard_shortcuts.legend": "顯示這個說明", - "keyboard_shortcuts.local": "開啟本機時間軸", + "keyboard_shortcuts.local": "開啟本站時間軸", "keyboard_shortcuts.mention": "æåŠä½œè€…", - "keyboard_shortcuts.muted": "開啟éœéŸ³ä½¿ç”¨è€…åå–®", + "keyboard_shortcuts.muted": "開啟éœéŸ³åå–®", "keyboard_shortcuts.my_profile": "開啟個人資料é é¢", "keyboard_shortcuts.notifications": "開啟通知欄", "keyboard_shortcuts.open_media": "開啟媒體", - "keyboard_shortcuts.pinned": "開啟釘é¸çš„嘟文åå–®", + "keyboard_shortcuts.pinned": "開啟釘é¸çš„æ–‡ç« 清單", "keyboard_shortcuts.profile": "開啟作者的個人資料é é¢", "keyboard_shortcuts.reply": "回覆", "keyboard_shortcuts.requests": "開啟關注請求åå–®", "keyboard_shortcuts.search": "把標示移動到æœç´¢", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "顯示或隱è—è¢«æŠ˜ç–Šçš„æ£æ–‡", "keyboard_shortcuts.start": "é–‹å•Ÿã€Œé–‹å§‹ä½¿ç”¨ã€æ¬„ä½", "keyboard_shortcuts.toggle_hidden": "顯示或隱è—è¢«æ¨™ç‚ºæ•æ„Ÿçš„æ–‡å—", "keyboard_shortcuts.toggle_sensitivity": "顯示 / éš±è—媒體", - "keyboard_shortcuts.toot": "新的推文", + "keyboard_shortcuts.toot": "æ–°çš„æ–‡ç« ", "keyboard_shortcuts.unfocus": "把標示移離文å—輸入和æœç´¢", "keyboard_shortcuts.up": "在列表往上移動", "lightbox.close": "關閉", - "lightbox.next": "繼續", - "lightbox.previous": "回退", - "lightbox.view_context": "檢視內文", + "lightbox.compress": "ç¸®å°æª¢è¦–", + "lightbox.expand": "擴大檢視", + "lightbox.next": "下一é ", + "lightbox.previous": "上一é ", "lists.account.add": "新增到列表", "lists.account.remove": "從列表刪除", "lists.delete": "刪除列表", @@ -260,22 +266,28 @@ "lists.edit.submit": "變更標題", "lists.new.create": "新增列表", "lists.new.title_placeholder": "新列表標題", - "lists.search": "å¾žä½ é—œæ³¨çš„ç”¨æˆ¶ä¸æœç´¢", + "lists.replies_policy.followed": "任何已關注的用戶", + "lists.replies_policy.list": "列表ä¸çš„用戶", + "lists.replies_policy.none": "無人", + "lists.replies_policy.title": "é¡¯ç¤ºå›žæ‡‰æ–‡ç« ï¸°", + "lists.search": "å¾žä½ é—œæ³¨çš„äººæœç´¢", "lists.subheading": "列表", "load_pending": "{count, plural, other {# å€‹æ–°é …ç›®}}", "loading_indicator.label": "載入ä¸...", - "media_gallery.toggle_visible": "打開或關上", + "media_gallery.toggle_visible": "éš±è—圖片", "missing_indicator.label": "找ä¸åˆ°å…§å®¹", "missing_indicator.sublabel": "無法找到內容", - "mute_modal.hide_notifications": "éš±è—來自這用戶的通知嗎?", - "navigation_bar.apps": "å°éŽ–çš„ä½¿ç”¨è€…", - "navigation_bar.blocks": "è¢«ä½ å°éŽ–çš„ç”¨æˆ¶", + "mute_modal.duration": "時間", + "mute_modal.hide_notifications": "需è¦éš±è—這使用者的通知嗎?", + "mute_modal.indefinite": "沒期é™", + "navigation_bar.apps": "手機 App", + "navigation_bar.blocks": "å°éŽ–åå–®", "navigation_bar.bookmarks": "書籤", "navigation_bar.community_timeline": "本站時間軸", - "navigation_bar.compose": "撰寫新嘟文", + "navigation_bar.compose": "æ’°å¯«æ–°æ–‡ç« ", "navigation_bar.direct": "個人訊æ¯", "navigation_bar.discover": "探索", - "navigation_bar.domain_blocks": "éš±è—çš„æœå‹™ç«™", + "navigation_bar.domain_blocks": "å°éŽ–çš„æœå‹™ç«™", "navigation_bar.edit_profile": "修改個人資料", "navigation_bar.favourites": "最愛的內容", "navigation_bar.filters": "éœéŸ³è©žå½™", @@ -285,23 +297,24 @@ "navigation_bar.keyboard_shortcuts": "éµç›¤å¿«é€Ÿéµ", "navigation_bar.lists": "列表", "navigation_bar.logout": "登出", - "navigation_bar.mutes": "è¢«ä½ éœéŸ³çš„用戶", + "navigation_bar.mutes": "éœéŸ³åå–®", "navigation_bar.personal": "個人", "navigation_bar.pins": "ç½®é ‚æ–‡ç« ", "navigation_bar.preferences": "å好è¨å®š", "navigation_bar.public_timeline": "跨站時間軸", "navigation_bar.security": "安全", - "notification.favourite": "{name} æ”¶è—äº†ä½ çš„æ–‡ç« ", + "notification.favourite": "{name} å–œæ¡ä½ çš„æ–‡ç« ", "notification.follow": "{name} é–‹å§‹é—œæ³¨ä½ ", "notification.follow_request": "{name} è¦æ±‚é—œæ³¨ä½ ", "notification.mention": "{name} æåŠä½ ", - "notification.own_poll": "æ‚¨çš„æŠ•ç¥¨å·²çµæŸ", - "notification.poll": "您投éŽçš„æŠ•ç¥¨å·²ç¶“çµæŸ", + "notification.own_poll": "ä½ çš„æŠ•ç¥¨å·²çµæŸ", + "notification.poll": "ä½ åƒèˆ‡éŽçš„ä¸€å€‹æŠ•ç¥¨å·²ç¶“çµæŸ", "notification.reblog": "{name} è½‰æŽ¨ä½ çš„æ–‡ç« ", + "notification.status": "{name} å‰›ç™¼è¡¨äº†æ–‡ç« ", "notifications.clear": "清空通知紀錄", "notifications.clear_confirmation": "ä½ ç¢ºå®šè¦æ¸…空通知紀錄嗎?", "notifications.column_settings.alert": "顯示桌é¢é€šçŸ¥", - "notifications.column_settings.favourite": "æ”¶è—äº†ä½ çš„æ–‡ç« ï¼š", + "notifications.column_settings.favourite": "ä½ æœ€æ„›çš„æ–‡ç« ï¼š", "notifications.column_settings.filter_bar.advanced": "顯示所有分類", "notifications.column_settings.filter_bar.category": "å¿«é€ŸéŽæ¿¾æ¬„", "notifications.column_settings.filter_bar.show": "顯示", @@ -313,25 +326,36 @@ "notifications.column_settings.reblog": "è½‰æŽ¨ä½ çš„æ–‡ç« ï¼š", "notifications.column_settings.show": "在通知欄顯示", "notifications.column_settings.sound": "æ’æ”¾éŸ³æ•ˆ", + "notifications.column_settings.status": "æ–°çš„æ–‡ç« ", "notifications.filter.all": "全部", - "notifications.filter.boosts": "轉嘟", + "notifications.filter.boosts": "轉推", "notifications.filter.favourites": "最愛", "notifications.filter.follows": "關注的使用者", "notifications.filter.mentions": "æåŠ", "notifications.filter.polls": "æŠ•ç¥¨çµæžœ", + "notifications.filter.statuses": "已關注的用戶的最新動態", + "notifications.grant_permission": "授予權é™", "notifications.group": "{count} æ¢é€šçŸ¥", + "notifications.mark_as_read": "標記所有通知為已讀", + "notifications.permission_denied": "本站ä¸èƒ½ç™¼é€æ¡Œé¢é€šçŸ¥ï¼Œå› 為ç€è¦½å™¨å…ˆå‰æ‹’絕了本站的桌é¢é€šçŸ¥æ¬Šé™è«‹æ±‚", + "notifications.permission_denied_alert": "無法啟用桌é¢é€šçŸ¥ï¼Œå› 為ç€è¦½å™¨å…ˆå‰æ‹’絕了本站的桌é¢é€šçŸ¥æ¬Šé™è«‹æ±‚", + "notifications.permission_required": "由於ç€è¦½å™¨æœªæœ‰æŽˆäºˆæ¡Œé¢é€šçŸ¥æ¬Šé™ï¼Œæœ¬ç«™æš«æœªèƒ½ç™¼é€æ¡Œé¢é€šçŸ¥ã€‚", + "notifications_permission_banner.enable": "啟用桌é¢é€šçŸ¥", + "notifications_permission_banner.how_to_control": "åªè¦å•Ÿç”¨æ¡Œé¢é€šçŸ¥ï¼Œä¾¿å¯åœ¨ Mastodon 網站沒有打開時收到通知。在已經啟用桌é¢é€šçŸ¥çš„æ™‚å€™ï¼Œä½ å¯ä»¥é€éŽä¸Šé¢çš„ {icon} 按鈕準確控制哪些類型的互動會產生桌é¢é€šçŸ¥ã€‚", + "notifications_permission_banner.title": "䏿”¾éŽä»»ä½•事情", + "picture_in_picture.restore": "é‚„åŽŸå½±ç‰‡æ’æ”¾å™¨", "poll.closed": "已關閉", "poll.refresh": "釿–°æ•´ç†", - "poll.total_people": "{count, plural, one {# 個投票} other {# 個投票}}", - "poll.total_votes": "{count, plural, one {# 個投票} other {# 個投票}}", + "poll.total_people": "{count, plural, one {# 人投票} other {# 人投票}}", + "poll.total_votes": "{count, plural, one {# 票} other {# 票}}", "poll.vote": "投票", - "poll.voted": "ä½ å·²å°æ¤å•題投票", + "poll.voted": "ä½ å·²æŠ•ç¥¨çµ¦é€™ç”æ¡ˆ", "poll_button.add_poll": "建立投票", "poll_button.remove_poll": "移除投票", "privacy.change": "調整ç§éš±è¨å®š", - "privacy.direct.long": "åªæœ‰æåŠçš„用戶能看到", + "privacy.direct.long": "åªæœ‰æåŠçš„使用者能看到", "privacy.direct.short": "ç§äººè¨Šæ¯", - "privacy.private.long": "åªæœ‰é—œæ³¨ä½ 用戶能看到", + "privacy.private.long": "åªæœ‰ä½ 的關注者能看到", "privacy.private.short": "關注者", "privacy.public.long": "在公共時間軸顯示", "privacy.public.short": "公共", @@ -340,11 +364,11 @@ "refresh": "釿–°æ•´ç†", "regeneration_indicator.label": "載入ä¸â€¦â€¦", "regeneration_indicator.sublabel": "ä½ çš„ä¸»é æ™‚間軸æ£åœ¨æº–å‚™ä¸ï¼", - "relative_time.days": "{number}æ—¥", - "relative_time.hours": "{number}å°æ™‚", + "relative_time.days": "{number}æ—¥å‰", + "relative_time.hours": "{number}å°æ™‚å‰", "relative_time.just_now": "剛剛", - "relative_time.minutes": "{number}分é˜", - "relative_time.seconds": "{number}ç§’", + "relative_time.minutes": "{number}分é˜å‰", + "relative_time.seconds": "{number}ç§’å‰", "relative_time.today": "今天", "reply_indicator.cancel": "å–æ¶ˆ", "report.forward": "轉寄到 {target}", @@ -355,28 +379,28 @@ "report.target": "èˆ‰å ±", "search.placeholder": "æœå°‹", "search_popout.search_format": "高級æœç´¢æ ¼å¼", - "search_popout.tips.full_text": "輸入簡單的文å—,æœç´¢ç”±ä½ ç™¼æ”¾ã€æ”¶è—ã€è½‰æŽ¨å’ŒæåŠä½ çš„æ–‡ç« ï¼Œä»¥åŠç¬¦åˆçš„用戶å稱,帳號å稱和標籤。", + "search_popout.tips.full_text": "輸入簡單的文å—,æœç´¢ç”±ä½ ç™¼æ”¾ã€æ”¶è—ã€è½‰æŽ¨å’ŒæåŠä½ çš„æ–‡ç« ï¼Œä»¥åŠç¬¦åˆçš„使用者å稱,顯示å稱和標籤。", "search_popout.tips.hashtag": "標籤", "search_popout.tips.status": "æ–‡ç« ", - "search_popout.tips.text": "輸入簡單的文å—,æœç´¢ç¬¦åˆçš„用戶å稱,帳號å稱和標籤", - "search_popout.tips.user": "用戶", + "search_popout.tips.text": "輸入簡單的文å—,æœç´¢ç¬¦åˆçš„顯示å稱ã€ä½¿ç”¨è€…å稱和標籤", + "search_popout.tips.user": "使用者", "search_results.accounts": "使用者", "search_results.hashtags": "標籤", "search_results.statuses": "æ–‡ç« ", - "search_results.statuses_fts_disabled": "「ä¾å…§å®¹æœå°‹å˜Ÿæ–‡ã€æœªåœ¨æ¤ Mastodon 伺æœå™¨å•Ÿç”¨ã€‚", + "search_results.statuses_fts_disabled": "æ¤ Mastodon 伺æœå™¨ä¸¦æœªå•Ÿç”¨ã€Œæœå°‹æ–‡ç« å…§ç« ã€åŠŸèƒ½ã€‚", "search_results.total": "{count, number} é …çµæžœ", "status.admin_account": "開啟 @{name} 的管ç†ä»‹é¢", - "status.admin_status": "在管ç†ä»‹é¢é–‹å•Ÿæ¤å˜Ÿæ–‡", + "status.admin_status": "在管ç†ä»‹é¢é–‹å•Ÿé€™ç¯‡æ–‡ç« ", "status.block": "å°éŽ– @{name}", "status.bookmark": "書籤", "status.cancel_reblog_private": "å–æ¶ˆè½‰æŽ¨", "status.cannot_reblog": "é€™ç¯‡æ–‡ç« ç„¡æ³•è¢«è½‰æŽ¨", - "status.copy": "將連çµè¤‡è£½åˆ°å˜Ÿæ–‡ä¸", + "status.copy": "將連çµè¤‡è£½åˆ°æ–‡ç« ä¸", "status.delete": "刪除", - "status.detailed_status": "å°è©±çš„詳細內容", + "status.detailed_status": "詳細å°è©±å…§å®¹", "status.direct": "ç§è¨Š @{name}", - "status.embed": "鑲嵌", - "status.favourite": "æ”¶è—", + "status.embed": "嵌入", + "status.favourite": "最愛", "status.filtered": "å·²éŽæ¿¾", "status.load_more": "載入更多", "status.media_hidden": "éš±è—媒體內容", @@ -391,7 +415,7 @@ "status.reblog": "轉推", "status.reblog_private": "轉推到原讀者", "status.reblogged_by": "{name} 轉推", - "status.reblogs.empty": "還沒有人轉嘟。如果有,會顯示在這裡。", + "status.reblogs.empty": "還未有人轉推。有的話會顯示在這裡。", "status.redraft": "刪除並編輯", "status.remove_bookmark": "移除書籤", "status.reply": "回應", @@ -399,60 +423,61 @@ "status.report": "èˆ‰å ± @{name}", "status.sensitive_warning": "æ•æ„Ÿå…§å®¹", "status.share": "分享", - "status.show_less": "減少顯示", - "status.show_less_all": "æ¸›å°‘é¡¯ç¤ºé€™é¡žæ–‡ç« ", - "status.show_more": "顯示更多", - "status.show_more_all": "é¡¯ç¤ºæ›´å¤šé€™é¡žæ–‡ç« ", + "status.show_less": "æ”¶èµ·", + "status.show_less_all": "全部收起", + "status.show_more": "展開", + "status.show_more_all": "全部展開", "status.show_thread": "顯示討論串", "status.uncached_media_warning": "無法使用", - "status.unmute_conversation": "è§£ç¦å°è©±", + "status.unmute_conversation": "å°è©±è§£é™¤éœéŸ³", "status.unpin": "è§£é™¤ç½®é ‚", "suggestions.dismiss": "關閉建è°", - "suggestions.header": "您å¯èƒ½å°é€™äº›æ±è¥¿æœ‰èˆˆè¶£â€¦", + "suggestions.header": "ä½ å¯èƒ½å°é€™äº›æ„Ÿèˆˆè¶£â€¦", "tabs_bar.federated_timeline": "跨站", "tabs_bar.home": "主é ", "tabs_bar.local_timeline": "本站", "tabs_bar.notifications": "通知", "tabs_bar.search": "æœå°‹", - "time_remaining.days": "剩餘{number, plural, one {# 天數} other {# 天數}}", - "time_remaining.hours": "剩餘{number, plural, one {# å°æ™‚} other {# å°æ™‚}}", - "time_remaining.minutes": "剩餘{number, plural, one {# 分é˜} other {# 分é˜}}", + "time_remaining.days": "剩餘 {number, plural, one {# 天} other {# 天}}", + "time_remaining.hours": "剩餘 {number, plural, one {# å°æ™‚} other {# å°æ™‚}}", + "time_remaining.minutes": "剩餘 {number, plural, one {# 分é˜} other {# 分é˜}}", "time_remaining.moments": "剩餘時間", "time_remaining.seconds": "剩餘 {number, plural, one {# ç§’} other {# ç§’}}", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", - "trends.trending_now": "ç›®å‰è¶¨å‹¢", + "timeline_hint.remote_resource_not_displayed": "䏿œƒé¡¯ç¤ºä¾†è‡ªå…¶ä»–伺æœå™¨çš„ {resource}", + "timeline_hint.resources.followers": "關注者", + "timeline_hint.resources.follows": "關注ä¸", + "timeline_hint.resources.statuses": "æ›´æ—©çš„æ–‡ç« ", + "trends.counter_by_accounts": "{count, plural, one {{counter} 個人}other {{counter} 個人}}æ£åœ¨è¨Žè«–", + "trends.trending_now": "ç¾åœ¨æµè¡Œ", "ui.beforeunload": "å¦‚æžœä½ ç¾åœ¨é›¢é–‹ Mastodonï¼Œä½ çš„è‰ç¨¿å…§å®¹å°‡æœƒè¢«ä¸Ÿæ£„。", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "將檔案拖放至æ¤ä¸Šè¼‰", - "upload_button.label": "上載媒體檔案", + "upload_button.label": "åŠ å…¥åœ–ç‰‡ã€å½±ç‰‡æˆ–音訊檔", "upload_error.limit": "å·²é”到檔案上傳é™åˆ¶ã€‚", "upload_error.poll": "ä¸å…許在投票上傳檔案。", "upload_form.audio_description": "ç°¡å–®æè¿°å…§å®¹çµ¦è½éšœäººå£«", "upload_form.description": "ç‚ºè¦–è¦ºéšœç¤™äººå£«æ·»åŠ æ–‡å—說明", "upload_form.edit": "編輯", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "更改é 覽圖", "upload_form.undo": "刪除", "upload_form.video_description": "ç°¡å–®æè¿°çµ¦è½éšœæˆ–視障人士", "upload_modal.analyzing_picture": "æ£åœ¨åˆ†æžåœ–片…", "upload_modal.apply": "套用", - "upload_modal.choose_image": "Choose image", - "upload_modal.description_placeholder": "A quick brown fox è·³éŽé‚£é𻿇¶ç‹—", + "upload_modal.choose_image": "鏿“‡åœ–片", + "upload_modal.description_placeholder": "ä¸€éš»æ•æ·çš„ç‹ç‹¸ï¼Œè¼•巧地跳éŽé‚£é𻿇¶æ´‹æ´‹çš„ç‹—", "upload_modal.detect_text": "å¾žåœ–ç‰‡åµæ¸¬æ–‡å—", "upload_modal.edit_media": "編輯媒體", "upload_modal.hint": "é»žæ“Šæˆ–æ‹–æ›³åœ“åœˆä»¥é¸æ“‡é 覽縮圖。", + "upload_modal.preparing_ocr": "準備辨è˜åœ–片文å—…", "upload_modal.preview_label": "é 覽 ({ratio})", "upload_progress.label": "上載ä¸â€¦â€¦", "video.close": "關閉影片", "video.download": "下載檔案", - "video.exit_fullscreen": "退出全熒幕", + "video.exit_fullscreen": "退出全螢幕", "video.expand": "展開影片", - "video.fullscreen": "全熒幕", + "video.fullscreen": "全螢幕", "video.hide": "éš±è—影片", "video.mute": "éœéŸ³", "video.pause": "æš«åœ", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index e964ccd4961fdda5db5203e8822cd3e77de5b53c..cc996e91b3b89587cefb5b22cbee7a55b719584b 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -1,28 +1,30 @@ { - "account.account_note_header": "Note", + "account.account_note_header": "備註", "account.add_or_remove_from_list": "從å單䏿–°å¢žæˆ–移除", "account.badges.bot": "機器人", "account.badges.group": "群組", "account.block": "å°éŽ– @{name}", - "account.block_domain": "éš±è—來自 {domain} 的所有內容", + "account.block_domain": "å°éŽ–ä¾†è‡ª {domain} 網域的所有內容", "account.blocked": "å·²å°éŽ–", - "account.browse_more_on_origin_server": "Browse more on the original profile", + "account.browse_more_on_origin_server": "在該伺æœå™¨çš„個人檔案é 上ç€è¦½æ›´å¤š", "account.cancel_follow_request": "å–æ¶ˆé—œæ³¨è«‹æ±‚", "account.direct": "傳ç§è¨Šçµ¦ @{name}", - "account.domain_blocked": "已隱è—網域", + "account.disable_notifications": "å–æ¶ˆä¾†è‡ª @{name} 嘟文的通知", + "account.domain_blocked": "å·²å°éŽ–ç¶²åŸŸ", "account.edit_profile": "編輯個人資料", + "account.enable_notifications": "ç•¶ @{name} 嘟文時通知我", "account.endorse": "åœ¨å€‹äººè³‡æ–™æŽ¨è–¦å°æ–¹", "account.follow": "關注", "account.followers": "關注者", - "account.followers.empty": "尚沒有人關注這ä½ä½¿ç”¨è€…。", - "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", - "account.following_counter": "{count, plural, one {{counter} Following} other {{counter} Following}}", - "account.follows.empty": "這ä½ä½¿ç”¨è€…尚未關注任何使用者。", - "account.follows_you": "é—œæ³¨äº†ä½ ", - "account.hide_reblogs": "éš±è—來自 @{name} 的轉推", - "account.last_status": "上次活èº", + "account.followers.empty": "尚未有人關注這ä½ä½¿ç”¨è€…。", + "account.followers_counter": "被 {count, plural,one {{counter} 人}other {{counter} 人}}關注", + "account.following_counter": "æ£åœ¨é—œæ³¨ {count, plural,one {{counter}}other {{counter} 人}}", + "account.follows.empty": "這ä½ä½¿ç”¨è€…尚未關注任何人。", + "account.follows_you": "關注了您", + "account.hide_reblogs": "éš±è—來自 @{name} 的轉嘟", + "account.last_status": "ä¸Šæ¬¡æ´»èºæ™‚é–“", "account.link_verified_on": "已在 {date} 檢查æ¤é€£çµçš„æ“æœ‰è€…æ¬Šé™", - "account.locked_info": "這隻帳戶的隱ç§ç‹€æ…‹è¢«è¨æˆéŽ–å®šã€‚è©²æ“æœ‰è€…æœƒæ‰‹å‹•å¯©æ ¸èƒ½é—œæ³¨é€™éš»å¸³è™Ÿçš„äººã€‚", + "account.locked_info": "æ¤å¸³è™Ÿçš„éš±ç§ç‹€æ…‹è¢«è¨ç‚ºéŽ–å®šã€‚è©²æ“æœ‰è€…æœƒæ‰‹å‹•å¯©æ ¸èƒ½é—œæ³¨æ¤å¸³è™Ÿçš„人。", "account.media": "媒體", "account.mention": "æåŠ @{name}", "account.moved_to": "{name} å·²é·ç§»è‡³ï¼š", @@ -36,15 +38,15 @@ "account.requested": "æ£åœ¨ç‰å¾…æ ¸å‡†ã€‚æŒ‰ä¸€ä¸‹å–æ¶ˆé—œæ³¨è«‹æ±‚", "account.share": "分享 @{name} 的個人資料", "account.show_reblogs": "顯示來自 @{name} 的嘟文", - "account.statuses_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}", + "account.statuses_counter": "{count, plural,one {{counter} 則}other {{counter} 則}}嘟文", "account.unblock": "å–æ¶ˆå°éŽ– @{name}", - "account.unblock_domain": "å–æ¶ˆéš±è— {domain}", + "account.unblock_domain": "å–æ¶ˆå°éŽ–åŸŸå {domain}", "account.unendorse": "ä¸å†æ–¼å€‹äººè³‡æ–™é é¢æŽ¨è–¦å°æ–¹", "account.unfollow": "å–æ¶ˆé—œæ³¨", "account.unmute": "å–æ¶ˆéœéŸ³ @{name}", "account.unmute_notifications": "釿–°æŽ¥æ”¶ä¾†è‡ª @{name} 的通知", - "account_note.placeholder": "Click to add a note", - "alert.rate_limited.message": "請在 {retry_time, time, medium} éŽå¾Œé‡è©¦", + "account_note.placeholder": "æŒ‰æ¤æ·»åŠ å‚™æ³¨", + "alert.rate_limited.message": "請在 {retry_time, time, medium} 後é‡è©¦", "alert.rate_limited.title": "å·²é™é€Ÿ", "alert.unexpected.message": "發生了éžé 期的錯誤。", "alert.unexpected.title": "哎呀ï¼", @@ -57,17 +59,17 @@ "bundle_modal_error.close": "關閉", "bundle_modal_error.message": "載入æ¤å…ƒä»¶æ™‚發生錯誤。", "bundle_modal_error.retry": "é‡è©¦", - "column.blocks": "å°éŽ–çš„ä½¿ç”¨è€…", + "column.blocks": "å·²å°éŽ–çš„ä½¿ç”¨è€…", "column.bookmarks": "書籤", "column.community": "本機時間軸", "column.direct": "ç§è¨Š", "column.directory": "ç€è¦½å€‹äººè³‡æ–™", - "column.domain_blocks": "éš±è—的網域", + "column.domain_blocks": "å·²å°éŽ–çš„ç¶²åŸŸ", "column.favourites": "æ”¶è—", "column.follow_requests": "關注請求", - "column.home": "主é ", + "column.home": "首é ", "column.lists": "åå–®", - "column.mutes": "被éœéŸ³çš„使用者", + "column.mutes": "å·²éœéŸ³çš„使用者", "column.notifications": "通知", "column.pins": "釘é¸çš„嘟文", "column.public": "è¯é‚¦æ™‚間軸", @@ -79,113 +81,116 @@ "column_header.show_settings": "顯示è¨å®š", "column_header.unpin": "å–æ¶ˆé‡˜é¸", "column_subheading.settings": "è¨å®š", - "community.column_settings.local_only": "åªæœ‰æœ¬åœ°", + "community.column_settings.local_only": "åªæœ‰æœ¬æ©Ÿ", "community.column_settings.media_only": "åªæœ‰åª’é«”", "community.column_settings.remote_only": "åªæœ‰é 端", "compose_form.direct_message_warning": "這æ¢å˜Ÿæ–‡åªæœ‰è¢«æåŠçš„使用者æ‰çœ‹å¾—到。", "compose_form.direct_message_warning_learn_more": "了解更多", - "compose_form.hashtag_warning": "由於這則嘟文被è¨å®šæˆã€Œä¸å…¬é–‹ã€ï¼Œæ‰€ä»¥å®ƒå°‡ä¸æœƒè¢«åˆ—åœ¨ä»»ä½•ä¸»é¡Œæ¨™ç±¤ä¸‹ã€‚åªæœ‰å…¬é–‹çš„嘟文æ‰èƒ½è—‰ä¸»é¡Œæ¨™ç±¤æ‰¾åˆ°ã€‚", + "compose_form.hashtag_warning": "由於這則嘟文è¨å®šç‚ºã€Œä¸å…¬é–‹ã€ï¼Œå®ƒå°‡ä¸æœƒè¢«åˆ—æ–¼ä»»ä½•ä¸»é¡Œæ¨™ç±¤ä¸‹ã€‚åªæœ‰å…¬é–‹çš„嘟文æ‰èƒ½è—‰ç”±ä¸»é¡Œæ¨™ç±¤æ‰¾åˆ°ã€‚", "compose_form.lock_disclaimer": "您的帳戶尚未{locked}。任何人都能關注您並看到您è¨å®šæˆåªæœ‰é—œæ³¨è€…能看的嘟文。", "compose_form.lock_disclaimer.lock": "上鎖", - "compose_form.placeholder": "您æ£åœ¨æƒ³äº›ä»€éº¼ï¼Ÿ", - "compose_form.poll.add_option": "æ–°å¢žé¸æ“‡", + "compose_form.placeholder": "æ£åœ¨æƒ³äº›ä»€éº¼å—Žï¼Ÿ", + "compose_form.poll.add_option": "新增é¸é …", "compose_form.poll.duration": "投票期é™", - "compose_form.poll.option_placeholder": "第 {number} 個鏿“‡", - "compose_form.poll.remove_option": "移除æ¤é¸æ“‡", + "compose_form.poll.option_placeholder": "第 {number} 個é¸é …", + "compose_form.poll.remove_option": "移除æ¤é¸é …", "compose_form.poll.switch_to_multiple": "變更投票為å…許多個é¸é …", "compose_form.poll.switch_to_single": "變更投票為å…許單一é¸é …", "compose_form.publish": "嘟出去", "compose_form.publish_loud": "{publish}ï¼", "compose_form.sensitive.hide": "æ¨™è¨˜åª’é«”ç‚ºæ•æ„Ÿå…§å®¹", "compose_form.sensitive.marked": "æ¤åª’é«”è¢«æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹", - "compose_form.sensitive.unmarked": "æ¤åª’é«”æœªæ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹", + "compose_form.sensitive.unmarked": "æ¤åª’é«”æœªè¢«æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹", "compose_form.spoiler.marked": "æ£æ–‡å·²éš±è—到è¦å‘Šä¹‹å¾Œ", "compose_form.spoiler.unmarked": "æ£æ–‡æœªè¢«éš±è—", "compose_form.spoiler_placeholder": "請在æ¤è™•寫入è¦å‘Šè¨Šæ¯", "confirmation_modal.cancel": "å–æ¶ˆ", "confirmations.block.block_and_report": "å°éŽ–ä¸¦æª¢èˆ‰", "confirmations.block.confirm": "å°éŽ–", - "confirmations.block.message": "確定å°éŽ– {name} ?", + "confirmations.block.message": "確定è¦å°éŽ– {name} 嗎?", "confirmations.delete.confirm": "刪除", - "confirmations.delete.message": "ä½ ç¢ºå®šè¦åˆªé™¤é€™æ¢å˜Ÿæ–‡ï¼Ÿ", + "confirmations.delete.message": "您確定è¦åˆªé™¤é€™å‰‡å˜Ÿæ–‡ï¼Ÿ", "confirmations.delete_list.confirm": "刪除", "confirmations.delete_list.message": "確定永久刪除æ¤å單?", - "confirmations.domain_block.confirm": "éš±è—æ•´å€‹ç¶²åŸŸ", - "confirmations.domain_block.message": "真的éžå¸¸ç¢ºå®šå°éŽ–æ•´å€‹ {domain} 嗎?大部分情æ³ä¸‹ï¼Œä½ åªéœ€è¦å°éŽ–æˆ–éœéŸ³å°‘æ•¸ç‰¹å®šçš„äººå°±èƒ½æ»¿è¶³éœ€æ±‚äº†ã€‚ä½ å°‡ä¸èƒ½åœ¨ä»»ä½•公開的時間軸åŠé€šçŸ¥ä¸çœ‹åˆ°é‚£å€‹ç¶²åŸŸçš„å…§å®¹ã€‚ä½ ä¾†è‡ªè©²ç¶²åŸŸçš„é—œæ³¨è€…ä¹Ÿæœƒè¢«ç§»é™¤ã€‚", + "confirmations.domain_block.confirm": "éš±è—æ•´å€‹åŸŸå", + "confirmations.domain_block.message": "真的éžå¸¸ç¢ºå®šå°éŽ–æ•´å€‹ {domain} 網域嗎?大部分情æ³ä¸‹ï¼Œæ‚¨åªéœ€è¦å°éŽ–æˆ–éœéŸ³å°‘數特定的帳號就能滿足需求了。您將ä¸èƒ½åœ¨ä»»ä½•公開的時間軸åŠé€šçŸ¥ä¸çœ‹åˆ°æ¤ç¶²åŸŸçš„內容。您來自該網域的關注者也將被移除。", "confirmations.logout.confirm": "登出", "confirmations.logout.message": "確定è¦ç™»å‡ºå—Žï¼Ÿ", "confirmations.mute.confirm": "éœéŸ³", - "confirmations.mute.explanation": "這將會隱è—來自他們的貼文與通知,但是他們還是å¯ä»¥æŸ¥é–±ä½ çš„è²¼æ–‡èˆ‡é—œæ³¨ä½ ã€‚", + "confirmations.mute.explanation": "這將會隱è—來自他們的貼文與通知,但是他們還是å¯ä»¥æŸ¥é–±ä½ 的貼文與關注您。", "confirmations.mute.message": "確定éœéŸ³ {name} ?", "confirmations.redraft.confirm": "åˆªé™¤ä¸¦é‡æ–°ç·¨è¼¯", "confirmations.redraft.message": "ç¢ºå®šåˆªæŽ‰é€™å‰‡å˜Ÿæ–‡ä¸¦é‡æ–°ç·¨è¼¯å—Žï¼Ÿå°‡æœƒå¤±åŽ»é€™å‰‡å˜Ÿæ–‡çš„è½‰å˜ŸåŠæ”¶è—,且回覆這則的嘟文將會變æˆç¨ç«‹çš„嘟文。", "confirmations.reply.confirm": "回覆", "confirmations.reply.message": "ç¾åœ¨å›žè¦†å°‡è“‹æŽ‰æ‚¨ç›®å‰æ£åœ¨æ’°å¯«çš„訊æ¯ã€‚是å¦ä»è¦å›žè¦†ï¼Ÿ", "confirmations.unfollow.confirm": "å–æ¶ˆé—œæ³¨", - "confirmations.unfollow.message": "真的è¦å–消關注 {name} 嗎?", + "confirmations.unfollow.message": "確定è¦å–消關注 {name} 嗎?", "conversation.delete": "刪除å°è©±", - "conversation.mark_as_read": "標為已讀", + "conversation.mark_as_read": "標記為已讀", "conversation.open": "檢視å°è©±", "conversation.with": "與 {names}", "directory.federated": "來自已知è¯é‚¦å®‡å®™", - "directory.local": "僅來自 {domain}", - "directory.new_arrivals": "新貨", + "directory.local": "僅來自 {domain} 網域", + "directory.new_arrivals": "新人", "directory.recently_active": "最近活èº", - "embed.instructions": "è¦åµŒå…¥æ¤å˜Ÿæ–‡ï¼Œè«‹å°‡ä»¥ä¸‹ç¨‹å¼ç¢¼è²¼é€²ä½ 的網站。", - "embed.preview": "他會顯示æˆé€™æ¨£ï¼š", + "embed.instructions": "è¦åœ¨æ‚¨çš„網站嵌入æ¤å˜Ÿæ–‡ï¼Œè«‹è¤‡è£½ä»¥ä¸‹ç¨‹å¼ç¢¼ã€‚", + "embed.preview": "它將顯示æˆé€™æ¨£ï¼š", "emoji_button.activity": "活動", "emoji_button.custom": "自訂", - "emoji_button.flags": "旗標", - "emoji_button.food": "飲食", + "emoji_button.flags": "旗幟", + "emoji_button.food": "食物 & 飲料", "emoji_button.label": "æ’入表情符號", - "emoji_button.nature": "大自然", + "emoji_button.nature": "自然", "emoji_button.not_found": "啊就沒這表情符號å¼ï¼ï¼ (╯°□°)╯︵ â”»â”â”»", "emoji_button.objects": "物件", - "emoji_button.people": "使用者", + "emoji_button.people": "人物", "emoji_button.recent": "最常使用", "emoji_button.search": "æœå°‹â€¦", "emoji_button.search_results": "æœå°‹çµæžœ", "emoji_button.symbols": "符號", "emoji_button.travel": "æ—…éŠèˆ‡åœ°é»ž", + "empty_column.account_suspended": "帳號被暫åœ", "empty_column.account_timeline": "這裡還沒有嘟文ï¼", "empty_column.account_unavailable": "無法å–得個人資料", - "empty_column.blocks": "ä½ é‚„æ²’æœ‰å°éŽ–ä»»ä½•ä½¿ç”¨è€…ã€‚", - "empty_column.bookmarked_statuses": "ä½ é‚„æ²’å»ºç«‹ä»»ä½•æ›¸ç±¤ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ å»ºç«‹çš„æ›¸ç±¤ã€‚", - "empty_column.community": "本地時間軸是空的。快公開嘟些文æ¶é 香啊ï¼", + "empty_column.blocks": "您還沒有å°éŽ–ä»»ä½•ä½¿ç”¨è€…ã€‚", + "empty_column.bookmarked_statuses": "您還沒建立任何書籤。當您建立書簽時,它將於æ¤é¡¯ç¤ºã€‚", + "empty_column.community": "本機時間軸是空的。快公開嘟些文æ¶é 香啊ï¼", "empty_column.direct": "您還沒有任何ç§è¨Šã€‚當您ç§è¨Šåˆ¥äººæˆ–收到ç§è¨Šæ™‚,它將於æ¤é¡¯ç¤ºã€‚", - "empty_column.domain_blocks": "尚未隱è—任何網域。", - "empty_column.favourited_statuses": "ä½ é‚„æ²’æ”¶è—ä»»ä½•å˜Ÿæ–‡ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ æ”¶è—的嘟文。", - "empty_column.favourites": "還沒有人收è—這則嘟文。這裡將會顯示被收è—的嘟文。", + "empty_column.domain_blocks": "尚未å°éŽ–ä»»ä½•ç¶²åŸŸã€‚", + "empty_column.favourited_statuses": "您還沒收è—éŽä»»ä½•嘟文。當您收è—嘟文時,它將於æ¤é¡¯ç¤ºã€‚", + "empty_column.favourites": "還沒有人收è—éŽé€™å‰‡å˜Ÿæ–‡ã€‚當有人收è—嘟文時,它將於æ¤é¡¯ç¤ºã€‚", "empty_column.follow_requests": "您尚未收到任何關注請求。這裡將會顯示收到的關注請求。", "empty_column.hashtag": "這個主題標籤下什麼也沒有。", "empty_column.home": "æ‚¨çš„é¦–é æ™‚間軸是空的ï¼å‰å¾€ {public} 或使用æœå°‹åŠŸèƒ½ä¾†èªè˜å…¶ä»–人。", "empty_column.home.public_timeline": "公開時間軸", "empty_column.list": "這份å單還沒有æ±è¥¿ã€‚ç•¶æ¤å單的æˆå“¡å˜Ÿå‡ºäº†æ–°çš„嘟文時,它們就會顯示於æ¤ã€‚", - "empty_column.lists": "ä½ é‚„æ²’æœ‰å»ºç«‹ä»»ä½•åå–®ã€‚é€™è£¡å°‡æœƒé¡¯ç¤ºä½ æ‰€å»ºç«‹çš„å單。", - "empty_column.mutes": "ä½ å°šæœªéœéŸ³ä»»ä½•使用者。", + "empty_column.lists": "您還沒有建立任何å單。這裡將會顯示您所建立的å單。", + "empty_column.mutes": "您尚未éœéŸ³ä»»ä½•使用者。", "empty_column.notifications": "您尚未收到任何通知,和別人互動開啟å°è©±å§ã€‚", "empty_column.public": "這裡什麼都沒有ï¼å˜—試寫些公開的嘟文,或著自己關注其他伺æœå™¨çš„使用者後就會有嘟文出ç¾äº†", - "error.unexpected_crash.explanation": "由於發生系統故障或ç€è¦½å™¨ç›¸å®¹æ€§å•題,故無法æ£å¸¸é¡¯ç¤ºé é¢ã€‚", - "error.unexpected_crash.next_steps": "è«‹å˜—è©¦é‡æ–°æ•´ç†é é¢ã€‚å¦‚æžœç‹€æ³æ²’æœ‰é€²å±•ï¼Œä½ å¯ä»¥ä½¿ç”¨ä¸åŒçš„ç€è¦½å™¨æˆ– Mastodon 應用程å¼ä¾†æª¢è¦–。", - "errors.unexpected_crash.copy_stacktrace": "複製到剪貼簿", - "errors.unexpected_crash.report_issue": "èˆ‰å ±å•題", + "error.unexpected_crash.explanation": "由於發生系統故障或ç€è¦½å™¨ç›¸å®¹æ€§å•題,無法æ£å¸¸é¡¯ç¤ºæ¤é é¢ã€‚", + "error.unexpected_crash.explanation_addons": "æ¤é é¢ç„¡æ³•被æ£å¸¸é¡¯ç¤ºï¼Œé€™å¯èƒ½æ˜¯ç”±ç€è¦½å™¨é™„åŠ å…ƒä»¶æˆ–ç¶²é 自動翻è¯å·¥å…·é€ æˆçš„。", + "error.unexpected_crash.next_steps": "è«‹å˜—è©¦é‡æ–°æ•´ç†é é¢ã€‚å¦‚æžœç‹€æ³æ²’有改善,您å¯ä»¥ä½¿ç”¨ä¸åŒçš„ç€è¦½å™¨æˆ–應用程å¼ä¾†æª¢è¦–來使用 Mastodon。", + "error.unexpected_crash.next_steps_addons": "è«‹å˜—è©¦é—œé–‰ä»–å€‘ç„¶å¾Œé‡æ–°æ•´ç†é é¢ã€‚å¦‚æžœç‹€æ³æ²’有改善,您å¯ä»¥ä½¿ç”¨ä¸åŒçš„ç€è¦½å™¨æˆ–應用程å¼ä¾†æª¢è¦–來使用 Mastodon。", + "errors.unexpected_crash.copy_stacktrace": "複製 stacktrace 到剪貼簿", + "errors.unexpected_crash.report_issue": "å›žå ±å•題", "follow_request.authorize": "授權", "follow_request.reject": "拒絕", - "follow_requests.unlocked_explanation": "å³ä¾¿æ‚¨çš„帳號未被鎖定,{domain} 的員工èªç‚ºå¯èƒ½æƒ³è¦è‡ªå·±å¯©æ ¸é€™äº›å¸³è™Ÿçš„追蹤請求。", - "generic.saved": "Saved", + "follow_requests.unlocked_explanation": "å³ä¾¿æ‚¨çš„帳號未被鎖定,{domain} 的員工èªç‚ºæ‚¨å¯èƒ½æƒ³è¦è‡ªå·±å¯©æ ¸é€™äº›å¸³è™Ÿçš„追蹤請求。", + "generic.saved": "已儲å˜", "getting_started.developers": "開發者", "getting_started.directory": "個人資料目錄", "getting_started.documentation": "文件", "getting_started.heading": "開始使用", "getting_started.invite": "邀請使用者", - "getting_started.open_source_notice": "Mastodon 是開æºè»Ÿé«”ã€‚ä½ å¯ä»¥åœ¨ GitHub {github} ä¸Šè²¢ç»æˆ–æ˜¯å›žå ±å•題。", - "getting_started.security": "安全性", + "getting_started.open_source_notice": "Mastodon 是開æºè»Ÿé«”。您å¯ä»¥åœ¨ GitHub {github} ä¸Šè²¢ç»æˆ–æ˜¯å›žå ±å•題。", + "getting_started.security": "帳號安全性è¨å®š", "getting_started.terms": "æœå‹™æ¢æ¬¾", - "hashtag.column_header.tag_mode.all": "以åŠ{additional}", - "hashtag.column_header.tag_mode.any": "或是{additional}", - "hashtag.column_header.tag_mode.none": "而無需{additional}", + "hashtag.column_header.tag_mode.all": "ä»¥åŠ {additional}", + "hashtag.column_header.tag_mode.any": "或是 {additional}", + "hashtag.column_header.tag_mode.none": "而無需 {additional}", "hashtag.column_settings.select.no_options_message": "找ä¸åˆ°å»ºè°", - "hashtag.column_settings.select.placeholder": "輸入主題標籤…", + "hashtag.column_settings.select.placeholder": "請輸入主題標籤…", "hashtag.column_settings.tag_mode.all": "全部", "hashtag.column_settings.tag_mode.any": "任一", "hashtag.column_settings.tag_mode.none": "å…¨ä¸", @@ -199,14 +204,14 @@ "intervals.full.hours": "{number, plural, one {# å°æ™‚} other {# å°æ™‚}}", "intervals.full.minutes": "{number, plural, one {# 分é˜} other {# 分é˜}}", "introduction.federation.action": "下一æ¥", - "introduction.federation.federated.headline": "ç«™å°è¯ç›Ÿ", - "introduction.federation.federated.text": "來自è¯ç›Ÿå®‡å®™ä¸å…¶ä»–ç«™å°çš„公開嘟文將會在站點è¯ç›Ÿæ™‚間軸ä¸é¡¯ç¤ºã€‚", + "introduction.federation.federated.headline": "è¯é‚¦", + "introduction.federation.federated.text": "來自è¯ç›Ÿå®‡å®™ä¸å…¶ä»–伺æœå™¨çš„公開嘟文將會在è¯é‚¦æ™‚間軸ä¸é¡¯ç¤ºã€‚", "introduction.federation.home.headline": "首é ", "introduction.federation.home.text": "ä½ é—œæ³¨ä½¿ç”¨è€…çš„å˜Ÿæ–‡å°‡æœƒåœ¨é¦–é å‹•æ…‹ä¸é¡¯ç¤ºã€‚ä½ å¯ä»¥é—œæ³¨ä»»ä½•伺æœå™¨ä¸Šçš„任何人ï¼", "introduction.federation.local.headline": "本機", "introduction.federation.local.text": "跟您åŒä¼ºæœå™¨ä¹‹ä½¿ç”¨è€…所發的公開嘟文將會顯示在本機時間軸ä¸ã€‚", "introduction.interactions.action": "å®Œæˆæ•™å¸ï¼", - "introduction.interactions.favourite.headline": "關注", + "introduction.interactions.favourite.headline": "æ”¶è—", "introduction.interactions.favourite.text": "您能儲å˜å˜Ÿæ–‡ä¾›ç¨å€™è§€çœ‹ï¼Œæˆ–者收è—å˜Ÿæ–‡ï¼Œè®“ä½œè€…çŸ¥é“æ‚¨å–œæ¡é€™å‰‡å˜Ÿæ–‡ã€‚", "introduction.interactions.reblog.headline": "轉嘟", "introduction.interactions.reblog.text": "您能藉由轉嘟他人嘟文來分享給您的關注者。", @@ -214,23 +219,23 @@ "introduction.interactions.reply.text": "æ‚¨èƒ½å›žè¦†å…¶ä»–äººæˆ–è‡ªå·±çš„å˜Ÿæ–‡ï¼Œé€™éº¼åšæœƒæŠŠé€™äº›å›žè¦†ä¸²æˆä¸€ä¸²å°è©±ã€‚", "introduction.welcome.action": "開始旅程å§ï¼", "introduction.welcome.headline": "第一æ¥", - "introduction.welcome.text": "æ¡è¿Žä¾†åˆ°è¯ç›Ÿå®‡å®™ï¼ç‰ç‰ä½ å°±å¯ä»¥å»£æ’訊æ¯åŠè·¨è¶Šå„種å„å¼å„樣的伺æœå™¨èˆ‡æœ‹å‹èŠå¤©ã€‚但這å°ä¼ºæœå™¨ï¼Œ{domain},éžå¸¸ç‰¹åˆ¥ - å®ƒå¯„ç®¡äº†ä½ çš„å€‹äººè³‡æ–™ï¼Œæ‰€ä»¥è«‹è¨˜ä½å®ƒçš„åå—。", + "introduction.welcome.text": "æ¡è¿Žä¾†åˆ°è¯ç›Ÿå®‡å®™ï¼ç¨å€™æ‚¨å°±å¯ä»¥å»£æ’訊æ¯åŠè·¨è¶Šå„種å„å¼å„樣的伺æœå™¨èˆ‡æœ‹å‹èŠå¤©ã€‚但這å°ä¼ºæœå™¨ï¼Œ{domain},éžå¸¸ç‰¹åˆ¥ - 它承載了您的個人資料,所以請記ä½å®ƒçš„åå—。", "keyboard_shortcuts.back": "返回上一é ", "keyboard_shortcuts.blocked": "開啟「å°éŽ–ä½¿ç”¨è€…ã€åå–®", "keyboard_shortcuts.boost": "轉嘟", "keyboard_shortcuts.column": "將焦點放在其ä¸ä¸€æ¬„的嘟文", "keyboard_shortcuts.compose": "將焦點移至撰寫文å—å€å¡Š", - "keyboard_shortcuts.description": "æè¿°", + "keyboard_shortcuts.description": "說明", "keyboard_shortcuts.direct": "開啟ç§è¨Šæ¬„", - "keyboard_shortcuts.down": "往下移動åå–®é …ç›®", + "keyboard_shortcuts.down": "在åå–®ä¸å¾€ä¸‹ç§»å‹•", "keyboard_shortcuts.enter": "檢視嘟文", - "keyboard_shortcuts.favourite": "æ”¶è—", + "keyboard_shortcuts.favourite": "åŠ åˆ°æ”¶è—", "keyboard_shortcuts.favourites": "開啟收è—åå–®", - "keyboard_shortcuts.federated": "開啟站點è¯ç›Ÿæ™‚間軸", + "keyboard_shortcuts.federated": "開啟è¯é‚¦æ™‚間軸", "keyboard_shortcuts.heading": "éµç›¤å¿«é€Ÿéµ", "keyboard_shortcuts.home": "é–‹å•Ÿé¦–é æ™‚間軸", "keyboard_shortcuts.hotkey": "快速éµ", - "keyboard_shortcuts.legend": "顯示æ¤åˆ—表", + "keyboard_shortcuts.legend": "顯示æ¤åœ–例", "keyboard_shortcuts.local": "開啟本機時間軸", "keyboard_shortcuts.mention": "æåŠä½œè€…", "keyboard_shortcuts.muted": "開啟éœéŸ³ä½¿ç”¨è€…åå–®", @@ -239,20 +244,21 @@ "keyboard_shortcuts.open_media": "開啟媒體", "keyboard_shortcuts.pinned": "開啟釘é¸çš„嘟文åå–®", "keyboard_shortcuts.profile": "開啟作者的個人資料é é¢", - "keyboard_shortcuts.reply": "回覆", + "keyboard_shortcuts.reply": "回應嘟文", "keyboard_shortcuts.requests": "開啟關注請求åå–®", "keyboard_shortcuts.search": "將焦點移至æœå°‹æ¡†", - "keyboard_shortcuts.spoilers": "to show/hide CW field", + "keyboard_shortcuts.spoilers": "顯示或隱è—è¢«æŠ˜ç–Šçš„æ£æ–‡", "keyboard_shortcuts.start": "é–‹å•Ÿã€Œé–‹å§‹ä½¿ç”¨ã€æ¬„ä½", "keyboard_shortcuts.toggle_hidden": "顯示/éš±è—在內容è¦å‘Šä¹‹å¾Œçš„æ£æ–‡", "keyboard_shortcuts.toggle_sensitivity": "顯示 / éš±è—媒體", "keyboard_shortcuts.toot": "開始發出新嘟文", "keyboard_shortcuts.unfocus": "å–æ¶ˆè¼¸å…¥æ–‡å—å€å¡Š / æœå°‹çš„焦點", - "keyboard_shortcuts.up": "往上移動åå–®é …ç›®", + "keyboard_shortcuts.up": "在åå–®ä¸å¾€ä¸Šç§»å‹•", "lightbox.close": "關閉", + "lightbox.compress": "折疊圖片檢視框", + "lightbox.expand": "展開圖片檢視框", "lightbox.next": "下一æ¥", "lightbox.previous": "上一æ¥", - "lightbox.view_context": "檢視內文", "lists.account.add": "新增至åå–®", "lists.account.remove": "從åå–®ä¸ç§»é™¤", "lists.delete": "刪除åå–®", @@ -260,15 +266,21 @@ "lists.edit.submit": "變更標題", "lists.new.create": "新增åå–®", "lists.new.title_placeholder": "æ–°å單標題", + "lists.replies_policy.followed": "任何跟隨的使用者", + "lists.replies_policy.list": "列表æˆå“¡", + "lists.replies_policy.none": "沒有人", + "lists.replies_policy.title": "顯示回覆:", "lists.search": "æœå°‹æ‚¨é—œæ³¨çš„使用者", "lists.subheading": "您的åå–®", - "load_pending": "{count, plural, other {# å€‹æ–°é …ç›®}}", + "load_pending": "{count, plural, one {# å€‹æ–°é …ç›®} other {# å€‹æ–°é …ç›®}}", "loading_indicator.label": "讀å–ä¸...", "media_gallery.toggle_visible": "切æ›å¯è¦‹æ€§", "missing_indicator.label": "找ä¸åˆ°", "missing_indicator.sublabel": "找ä¸åˆ°æ¤è³‡æº", + "mute_modal.duration": "æŒçºŒæ™‚é–“", "mute_modal.hide_notifications": "éš±è—來自這ä½ä½¿ç”¨è€…的通知?", - "navigation_bar.apps": "å°éŽ–çš„ä½¿ç”¨è€…", + "mute_modal.indefinite": "無期é™", + "navigation_bar.apps": "行動應用程å¼", "navigation_bar.blocks": "å°éŽ–ä½¿ç”¨è€…", "navigation_bar.bookmarks": "書籤", "navigation_bar.community_timeline": "本機時間軸", @@ -291,71 +303,83 @@ "navigation_bar.preferences": "å好è¨å®š", "navigation_bar.public_timeline": "è¯é‚¦æ™‚間軸", "navigation_bar.security": "安全性", - "notification.favourite": "{name} æŠŠä½ çš„å˜Ÿæ–‡åŠ å…¥äº†æœ€æ„›", - "notification.follow": "{name} é—œæ³¨äº†ä½ ", - "notification.follow_request": "{name} è¦æ±‚é—œæ³¨ä½ ", - "notification.mention": "{name} æåˆ°äº†ä½ ", + "notification.favourite": "{name} æŠŠæ‚¨çš„å˜Ÿæ–‡åŠ å…¥äº†æœ€æ„›", + "notification.follow": "{name} 關注了您", + "notification.follow_request": "{name} è¦æ±‚關注您", + "notification.mention": "{name} æåˆ°äº†æ‚¨", "notification.own_poll": "æ‚¨çš„æŠ•ç¥¨å·²çµæŸ", - "notification.poll": "您投éŽçš„æŠ•ç¥¨å·²ç¶“çµæŸ", - "notification.reblog": "{name}è½‰å˜Ÿäº†ä½ çš„å˜Ÿæ–‡", + "notification.poll": "您曾投éŽçš„æŠ•ç¥¨å·²ç¶“çµæŸ", + "notification.reblog": "{name} 轉嘟了您的嘟文", + "notification.status": "{name} 剛剛嘟文", "notifications.clear": "清除通知", - "notifications.clear_confirmation": "ç¢ºå®šè¦æ°¸ä¹…æ¸…é™¤ä½ çš„é€šçŸ¥å—Žï¼Ÿ", + "notifications.clear_confirmation": "ç¢ºå®šè¦æ°¸ä¹…清除您的通知嗎?", "notifications.column_settings.alert": "桌é¢é€šçŸ¥", "notifications.column_settings.favourite": "最愛:", "notifications.column_settings.filter_bar.advanced": "顯示所有分類", "notifications.column_settings.filter_bar.category": "å¿«é€ŸéŽæ¿¾æ¬„", "notifications.column_settings.filter_bar.show": "顯示", "notifications.column_settings.follow": "新關注者:", - "notifications.column_settings.follow_request": "新的關注請求:", + "notifications.column_settings.follow_request": "新的關注請求:", "notifications.column_settings.mention": "æåŠï¼š", "notifications.column_settings.poll": "æŠ•ç¥¨çµæžœï¼š", - "notifications.column_settings.push": "推é€é€šçŸ¥", + "notifications.column_settings.push": "推æ’通知", "notifications.column_settings.reblog": "轉嘟:", "notifications.column_settings.show": "在欄ä½ä¸é¡¯ç¤º", - "notifications.column_settings.sound": "æ’æ”¾éŸ³æ•ˆ", + "notifications.column_settings.sound": "æ’æ”¾è²éŸ³", + "notifications.column_settings.status": "新嘟文:", "notifications.filter.all": "全部", "notifications.filter.boosts": "轉嘟", "notifications.filter.favourites": "最愛", "notifications.filter.follows": "關注的使用者", "notifications.filter.mentions": "æåŠ", "notifications.filter.polls": "æŠ•ç¥¨çµæžœ", + "notifications.filter.statuses": "已跟隨使用者的最新動態", + "notifications.grant_permission": "授予權é™", "notifications.group": "{count} æ¢é€šçŸ¥", + "notifications.mark_as_read": "將所有通知都標記為已讀", + "notifications.permission_denied": "ç”±æ–¼ä¹‹å‰æ‹’絕了ç€è¦½å™¨è«‹æ±‚ï¼Œå› æ¤æ¡Œé¢é€šçŸ¥ä¸å¯ç”¨", + "notifications.permission_denied_alert": "å› ç‚ºä¹‹å‰ç€è¦½å™¨æ¬Šé™è¢«æ‹’絕,無法啟用桌é¢é€šçŸ¥", + "notifications.permission_required": "å› ç‚ºå°šæœªæŽˆäºˆæ‰€éœ€çš„æ¬Šé™ï¼Œæ‰€ä»¥æ¡Œé¢é€šçŸ¥ä¸å¯ç”¨ã€‚", + "notifications_permission_banner.enable": "啟用桌é¢é€šçŸ¥", + "notifications_permission_banner.how_to_control": "啟用桌é¢é€šçŸ¥ä»¥åœ¨ Mastodon 沒有開啟的時候接收通知。在已經啟用桌é¢é€šçŸ¥çš„æ™‚候,您å¯ä»¥é€éŽä¸Šé¢çš„ {icon} 按鈕準確的控制哪些類型的互動會產生桌é¢é€šçŸ¥ã€‚", + "notifications_permission_banner.title": "ä¸è¦éŒ¯éŽä»»ä½•æ±è¥¿ï¼", + "picture_in_picture.restore": "還原", "poll.closed": "已關閉", "poll.refresh": "釿–°æ•´ç†", "poll.total_people": "{count, plural, one {# 個投票} other {# 個投票}}", "poll.total_votes": "{count, plural, one {# 個投票} other {# 個投票}}", "poll.vote": "投票", - "poll.voted": "ä½ å·²å°æ¤å•題投票", + "poll.voted": "æ‚¨å·²å°æ¤å•題投票", "poll_button.add_poll": "建立投票", "poll_button.remove_poll": "移除投票", - "privacy.change": "調整隱ç§ç‹€æ…‹", - "privacy.direct.long": "åªæœ‰è¢«æåˆ°çš„使用者能看到", + "privacy.change": "調整嘟文隱ç§ç‹€æ…‹", + "privacy.direct.long": "åªæœ‰è¢«æåŠçš„使用者能看到", "privacy.direct.short": "ç§è¨Š", - "privacy.private.long": "åªæœ‰é—œæ³¨ä½ 的使用者能看到", + "privacy.private.long": "åªæœ‰é—œæ³¨æ‚¨çš„使用者能看到", "privacy.private.short": "僅關注者", - "privacy.public.long": "嘟到公開時間軸", + "privacy.public.long": "公開,且顯示於公開時間軸", "privacy.public.short": "公開", "privacy.unlisted.long": "å…¬é–‹ï¼Œä½†ä¸æœƒé¡¯ç¤ºåœ¨å…¬é–‹æ™‚間軸", "privacy.unlisted.short": "ä¸å…¬é–‹", "refresh": "釿–°æ•´ç†", "regeneration_indicator.label": "載入ä¸â€¦", - "regeneration_indicator.sublabel": "ä½ çš„ä¸»é æ™‚間軸æ£åœ¨æº–å‚™ä¸!", + "regeneration_indicator.sublabel": "æ‚¨çš„ä¸»é æ™‚間軸æ£åœ¨æº–å‚™ä¸ï¼", "relative_time.days": "{number} 天", - "relative_time.hours": "{number} å°æ™‚", + "relative_time.hours": "{number}å°æ™‚å‰", "relative_time.just_now": "剛剛", - "relative_time.minutes": "{number} 分", + "relative_time.minutes": "{number} 分å‰", "relative_time.seconds": "{number} ç§’", "relative_time.today": "今天", "reply_indicator.cancel": "å–æ¶ˆ", "report.forward": "轉寄到 {target}", - "report.forward_hint": "這個帳戶屬於其他站點。è¦åƒè©²ç«™é»žç™¼é€åŒ¿å的檢舉訊æ¯å—Ž?", - "report.hint": "é€™é …è¨Šæ¯æœƒç™¼é€åˆ°æ‚¨ä¼ºæœå™¨çš„管ç†å“¡ã€‚ä½ å¯ä»¥æä¾›æª¢èˆ‰é€™å€‹å¸³æˆ¶çš„ç†ç”±ï¼š", - "report.placeholder": "更多訊æ¯", + "report.forward_hint": "這個帳戶屬於其他伺æœå™¨ã€‚è¦åƒè©²ä¼ºæœå™¨ç™¼é€åŒ¿å的檢舉訊æ¯å—Ž?", + "report.hint": "é€™é …è¨Šæ¯æœƒç™¼é€åˆ°æ‚¨ä¼ºæœå™¨çš„管ç†å“¡ã€‚您å¯ä»¥æä¾›æª¢èˆ‰é€™å€‹å¸³æˆ¶çš„ç†ç”±ï¼š", + "report.placeholder": "其他備註", "report.submit": "é€å‡º", "report.target": "檢舉 {target}", "search.placeholder": "æœå°‹", "search_popout.search_format": "進階æœå°‹æ ¼å¼", - "search_popout.tips.full_text": "輸入簡單的文å—,æœå°‹ç”±ä½ æ’°å¯«ã€æœ€æ„›ã€è½‰å˜Ÿæˆ–æä½ 的嘟文,以åŠç¬¦åˆä½¿ç”¨è€…å稱ã€å¸³æˆ¶å稱和標籤。", + "search_popout.tips.full_text": "輸入簡單的文å—,æœå°‹ç”±æ‚¨æ’°å¯«ã€æ”¶è—ã€è½‰å˜Ÿæˆ–ææ‚¨çš„嘟文,以åŠèˆ‡é—œéµè©žåŒ¹é…的使用者å稱ã€å¸³æˆ¶é¡¯ç¤ºå稱和主題標籤。", "search_popout.tips.hashtag": "主題標籤", "search_popout.tips.status": "嘟文", "search_popout.tips.text": "輸入簡單的文å—,æœå°‹ç¬¦åˆçš„使用者å稱,帳戶å稱與標籤", @@ -370,32 +394,32 @@ "status.block": "å°éŽ– @{name}", "status.bookmark": "書籤", "status.cancel_reblog_private": "å–æ¶ˆè½‰å˜Ÿ", - "status.cannot_reblog": "這篇嘟文無法被轉嘟", - "status.copy": "將連çµè¤‡è£½åˆ°å˜Ÿæ–‡ä¸", + "status.cannot_reblog": "這則嘟文無法被轉嘟", + "status.copy": "複製嘟文連çµ", "status.delete": "刪除", - "status.detailed_status": "å°è©±çš„詳細內容", + "status.detailed_status": "詳細的å°è©±å…§å®¹", "status.direct": "發é€ç§è¨Šçµ¦ @{name}", - "status.embed": "嵌入", + "status.embed": "內嵌", "status.favourite": "最愛", "status.filtered": "å·²éŽæ¿¾", "status.load_more": "載入更多", "status.media_hidden": "éš±è—媒體內容", - "status.mention": "æåˆ° @{name}", + "status.mention": "æåŠ @{name}", "status.more": "更多", "status.mute": "éœéŸ³ @{name}", "status.mute_conversation": "éœéŸ³å°è©±", - "status.open": "展開嘟文", + "status.open": "展開æ¤å˜Ÿæ–‡", "status.pin": "釘é¸åˆ°å€‹äººè³‡æ–™é ", "status.pinned": "釘é¸çš„嘟文", "status.read_more": "閱讀更多", "status.reblog": "轉嘟", "status.reblog_private": "轉嘟給原有關注者", "status.reblogged_by": "{name} 轉嘟了", - "status.reblogs.empty": "還沒有人轉嘟。如果有,會顯示在這裡。", + "status.reblogs.empty": "還沒有人轉嘟éŽé€™å‰‡å˜Ÿæ–‡ã€‚當有人轉嘟時,它將於æ¤é¡¯ç¤ºã€‚", "status.redraft": "刪除 & 編輯", "status.remove_bookmark": "移除書籤", "status.reply": "回覆", - "status.replyAll": "回覆所有人", + "status.replyAll": "回覆討論串", "status.report": "檢舉 @{name}", "status.sensitive_warning": "æ•æ„Ÿå…§å®¹", "status.share": "分享", @@ -406,46 +430,47 @@ "status.show_thread": "顯示討論串", "status.uncached_media_warning": "無法使用", "status.unmute_conversation": "解除æ¤å°è©±çš„éœéŸ³", - "status.unpin": "è§£é™¤ç½®é ‚", + "status.unpin": "從個人é é¢è§£é™¤é‡˜é¸", "suggestions.dismiss": "關閉建è°", "suggestions.header": "您å¯èƒ½å°é€™äº›æ±è¥¿æœ‰èˆˆè¶£â€¦", - "tabs_bar.federated_timeline": "其他站點", - "tabs_bar.home": "主é ", - "tabs_bar.local_timeline": "本站", + "tabs_bar.federated_timeline": "è¯é‚¦å®‡å®™", + "tabs_bar.home": "首é ", + "tabs_bar.local_timeline": "本機", "tabs_bar.notifications": "通知", "tabs_bar.search": "æœå°‹", - "time_remaining.days": "剩餘{number, plural, one {# 天數} other {# 天數}}", + "time_remaining.days": "剩餘{number, plural, one {# 天} other {# 天}}", "time_remaining.hours": "剩餘{number, plural, one {# å°æ™‚} other {# å°æ™‚}}", "time_remaining.minutes": "剩餘{number, plural, one {# 分é˜} other {# 分é˜}}", "time_remaining.moments": "剩餘時間", "time_remaining.seconds": "剩餘 {number, plural, one {# ç§’} other {# ç§’}}", - "timeline_hint.remote_resource_not_displayed": "{resource} from other servers are not displayed.", - "timeline_hint.resources.followers": "Followers", - "timeline_hint.resources.follows": "Follows", - "timeline_hint.resources.statuses": "Older toots", - "trends.counter_by_accounts": "{count, plural, one {{counter} person} other {{counter} people}} talking", + "timeline_hint.remote_resource_not_displayed": "䏿œƒé¡¯ç¤ºä¾†è‡ªå…¶ä»–æœå‹™å™¨çš„ {resource}", + "timeline_hint.resources.followers": "關注者", + "timeline_hint.resources.follows": "æ£åœ¨é—œæ³¨", + "timeline_hint.resources.statuses": "更早的嘟文", + "trends.counter_by_accounts": "{count, plural,one {{counter} 人}other {{counter} 人}}æ£åœ¨è¨Žè«–", "trends.trending_now": "ç›®å‰è¶¨å‹¢", - "ui.beforeunload": "如果離開 Mastodonï¼Œä½ çš„è‰ç¨¿å°‡æœƒä¸è¦‹ã€‚", + "ui.beforeunload": "如果離開 Mastodon,您的è‰ç¨¿å°‡æœƒä¸è¦‹ã€‚", "units.short.billion": "{count}B", "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "拖放來上傳", - "upload_button.label": "上傳媒體檔案 (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_button.label": "上傳圖åƒã€å½±ç‰‡ã€æˆ–音樂檔案", "upload_error.limit": "å·²é”到檔案上傳é™åˆ¶ã€‚", - "upload_error.poll": "ä¸å…許在投票上傳檔案。", - "upload_form.audio_description": "ç°¡å–®æè¿°å…§å®¹çµ¦è½éšœäººå£«", + "upload_error.poll": "ä¸å…許在投票ä¸ä¸Šå‚³æª”案。", + "upload_form.audio_description": "æè¿°å…§å®¹çµ¦è½éšœäººå£«", "upload_form.description": "ç‚ºè¦–éšœäººå£«å¢žåŠ æ–‡å—說明", "upload_form.edit": "編輯", - "upload_form.thumbnail": "Change thumbnail", + "upload_form.thumbnail": "更改é 覽圖", "upload_form.undo": "刪除", - "upload_form.video_description": "ç°¡å–®æè¿°çµ¦è½éšœæˆ–視障人士", + "upload_form.video_description": "æè¿°çµ¦è½éšœæˆ–視障人士", "upload_modal.analyzing_picture": "æ£åœ¨åˆ†æžåœ–片…", "upload_modal.apply": "套用", - "upload_modal.choose_image": "Choose image", - "upload_modal.description_placeholder": "A quick brown fox è·³éŽé‚£é𻿇¶ç‹—", - "upload_modal.detect_text": "å¾žåœ–ç‰‡åµæ¸¬æ–‡å—", + "upload_modal.choose_image": "鏿“‡åœ–片", + "upload_modal.description_placeholder": "我能åžä¸‹çŽ»ç’ƒè€Œä¸å‚·èº«é«”", + "upload_modal.detect_text": "從圖片ä¸åµæ¸¬æ–‡å—", "upload_modal.edit_media": "編輯媒體", - "upload_modal.hint": "é»žæ“Šæˆ–æ‹–æ›³åœ“åœˆä»¥é¸æ“‡é 覽縮圖。", + "upload_modal.hint": "æ–¼é 覽ä¸é»žæ“Šæˆ–æ‹–æ›³åœ“åœˆä»¥é¸æ“‡å°‡æ–¼æ‰€æœ‰ç¸®åœ–ä¸é¡¯ç¤ºçš„焦點。", + "upload_modal.preparing_ocr": "準備 OCR ä¸â€¦â€¦", "upload_modal.preview_label": "é 覽 ({ratio})", "upload_progress.label": "上傳ä¸...", "video.close": "關閉影片", diff --git a/app/javascript/mastodon/main.js b/app/javascript/mastodon/main.js index da4884fd3d77644b77ec3cd484b77e24f79344de..bda51f692b770f8cda0c433648d35b085b81d0f6 100644 --- a/app/javascript/mastodon/main.js +++ b/app/javascript/mastodon/main.js @@ -1,4 +1,5 @@ import * as registerPushNotifications from './actions/push_notifications'; +import { setupBrowserNotifications } from './actions/notifications'; import { default as Mastodon, store } from './containers/mastodon'; import React from 'react'; import ReactDOM from 'react-dom'; @@ -22,6 +23,7 @@ function main() { const props = JSON.parse(mountNode.getAttribute('data-props')); ReactDOM.render(<Mastodon {...props} />, mountNode); + store.dispatch(setupBrowserNotifications()); if (process.env.NODE_ENV === 'production') { // avoid offline in dev mode because it's harder to debug require('offline-plugin/runtime').install(); diff --git a/app/javascript/mastodon/reducers/index.js b/app/javascript/mastodon/reducers/index.js index 3823bb05e09b41da5f5f2e76d746dd37b2c20729..a8fb69c274830d4d0fa7e2d7108802cc0b17b1c9 100644 --- a/app/javascript/mastodon/reducers/index.js +++ b/app/javascript/mastodon/reducers/index.js @@ -36,6 +36,7 @@ import trends from './trends'; import missed_updates from './missed_updates'; import announcements from './announcements'; import markers from './markers'; +import picture_in_picture from './picture_in_picture'; const reducers = { announcements, @@ -75,6 +76,7 @@ const reducers = { trends, missed_updates, markers, + picture_in_picture, }; export default combineReducers(reducers); diff --git a/app/javascript/mastodon/reducers/meta.js b/app/javascript/mastodon/reducers/meta.js index 36a5a1c35403d4f8ada45dc3f6162a503559d42e..65becc44f8f46482ce1dde8f7c23da155f4851c2 100644 --- a/app/javascript/mastodon/reducers/meta.js +++ b/app/javascript/mastodon/reducers/meta.js @@ -1,15 +1,20 @@ -import { STORE_HYDRATE } from '../actions/store'; +import { STORE_HYDRATE } from 'mastodon/actions/store'; +import { APP_LAYOUT_CHANGE } from 'mastodon/actions/app'; import { Map as ImmutableMap } from 'immutable'; +import { layoutFromWindow } from 'mastodon/is_mobile'; const initialState = ImmutableMap({ streaming_api_base_url: null, access_token: null, + layout: layoutFromWindow(), }); export default function meta(state = initialState, action) { switch(action.type) { case STORE_HYDRATE: return state.merge(action.state.get('meta')); + case APP_LAYOUT_CHANGE: + return state.set('layout', action.layout); default: return state; } diff --git a/app/javascript/mastodon/reducers/mutes.js b/app/javascript/mastodon/reducers/mutes.js index 4672e50974eaa2a1394b5df9a6c51bc15548e0fa..a9eb61ff834cbcff296c6ad0d1ec1d541a0ba3cf 100644 --- a/app/javascript/mastodon/reducers/mutes.js +++ b/app/javascript/mastodon/reducers/mutes.js @@ -3,12 +3,14 @@ import Immutable from 'immutable'; import { MUTES_INIT_MODAL, MUTES_TOGGLE_HIDE_NOTIFICATIONS, + MUTES_CHANGE_DURATION, } from '../actions/mutes'; const initialState = Immutable.Map({ new: Immutable.Map({ account: null, notifications: true, + duration: 0, }), }); @@ -21,6 +23,8 @@ export default function mutes(state = initialState, action) { }); case MUTES_TOGGLE_HIDE_NOTIFICATIONS: return state.updateIn(['new', 'notifications'], (old) => !old); + case MUTES_CHANGE_DURATION: + return state.setIn(['new', 'duration'], Number(action.duration)); default: return state; } diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js index ed1ba02726727362f80de3570cd3ffdd1e21fc64..1d48747176b092a2e77dc92a5806909a46b15548 100644 --- a/app/javascript/mastodon/reducers/notifications.js +++ b/app/javascript/mastodon/reducers/notifications.js @@ -9,6 +9,9 @@ import { NOTIFICATIONS_LOAD_PENDING, NOTIFICATIONS_MOUNT, NOTIFICATIONS_UNMOUNT, + NOTIFICATIONS_MARK_AS_READ, + NOTIFICATIONS_SET_BROWSER_SUPPORT, + NOTIFICATIONS_SET_BROWSER_PERMISSION, } from '../actions/notifications'; import { ACCOUNT_BLOCK_SUCCESS, @@ -16,6 +19,13 @@ import { FOLLOW_REQUEST_AUTHORIZE_SUCCESS, FOLLOW_REQUEST_REJECT_SUCCESS, } from '../actions/accounts'; +import { + MARKERS_FETCH_SUCCESS, +} from '../actions/markers'; +import { + APP_FOCUS, + APP_UNFOCUS, +} from '../actions/app'; import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks'; import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; @@ -26,9 +36,14 @@ const initialState = ImmutableMap({ items: ImmutableList(), hasMore: true, top: false, - mounted: false, + mounted: 0, unread: 0, + lastReadId: '0', + readMarkerId: '0', + isTabVisible: true, isLoading: false, + browserSupport: false, + browserPermission: 'default', }); const notificationToMap = notification => ImmutableMap({ @@ -46,8 +61,10 @@ const normalizeNotification = (state, notification, usePendingItems) => { return state.update('pendingItems', list => list.unshift(notificationToMap(notification))).update('unread', unread => unread + 1); } - if (!top) { + if (shouldCountUnreadNotifications(state)) { state = state.update('unread', unread => unread + 1); + } else { + state = state.set('lastReadId', notification.id); } return state.update('items', list => { @@ -60,6 +77,7 @@ const normalizeNotification = (state, notification, usePendingItems) => { }; const expandNormalizedNotifications = (state, notifications, next, isLoadingRecent, usePendingItems) => { + const lastReadId = state.get('lastReadId'); let items = ImmutableList(); notifications.forEach((n, i) => { @@ -87,6 +105,15 @@ const expandNormalizedNotifications = (state, notifications, next, isLoadingRece mutable.set('hasMore', false); } + if (shouldCountUnreadNotifications(state)) { + mutable.update('unread', unread => unread + items.count(item => compareId(item.get('id'), lastReadId) > 0)); + } else { + const mostRecent = items.find(item => item !== null); + if (mostRecent && compareId(lastReadId, mostRecent.get('id')) < 0) { + mutable.set('lastReadId', mostRecent.get('id')); + } + } + mutable.set('isLoading', false); }); }; @@ -96,21 +123,93 @@ const filterNotifications = (state, accountIds, type) => { return state.update('items', helper).update('pendingItems', helper); }; +const clearUnread = (state) => { + state = state.set('unread', state.get('pendingItems').size); + const lastNotification = state.get('items').find(item => item !== null); + return state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0'); +}; + const updateTop = (state, top) => { - if (top) { - state = state.set('unread', state.get('pendingItems').size); + state = state.set('top', top); + + if (!shouldCountUnreadNotifications(state)) { + state = clearUnread(state); } - return state.set('top', top); + return state; }; const deleteByStatus = (state, statusId) => { + const lastReadId = state.get('lastReadId'); + + if (shouldCountUnreadNotifications(state)) { + const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0); + state = state.update('unread', unread => unread - deletedUnread.size); + } + const helper = list => list.filterNot(item => item !== null && item.get('status') === statusId); + const deletedUnread = state.get('pendingItems').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0); + state = state.update('unread', unread => unread - deletedUnread.size); return state.update('items', helper).update('pendingItems', helper); }; +const updateMounted = (state) => { + state = state.update('mounted', count => count + 1); + if (!shouldCountUnreadNotifications(state, state.get('mounted') === 1)) { + state = state.set('readMarkerId', state.get('lastReadId')); + state = clearUnread(state); + } + return state; +}; + +const updateVisibility = (state, visibility) => { + state = state.set('isTabVisible', visibility); + if (!shouldCountUnreadNotifications(state)) { + state = state.set('readMarkerId', state.get('lastReadId')); + state = clearUnread(state); + } + return state; +}; + +const shouldCountUnreadNotifications = (state, ignoreScroll = false) => { + const isTabVisible = state.get('isTabVisible'); + const isOnTop = state.get('top'); + const isMounted = state.get('mounted') > 0; + const lastReadId = state.get('lastReadId'); + const lastItem = state.get('items').findLast(item => item !== null); + const lastItemReached = !state.get('hasMore') || lastReadId === '0' || (lastItem && compareId(lastItem.get('id'), lastReadId) <= 0); + + return !(isTabVisible && (ignoreScroll || isOnTop) && isMounted && lastItemReached); +}; + +const recountUnread = (state, last_read_id) => { + return state.withMutations(mutable => { + if (compareId(last_read_id, mutable.get('lastReadId')) > 0) { + mutable.set('lastReadId', last_read_id); + } + + if (compareId(last_read_id, mutable.get('readMarkerId')) > 0) { + mutable.set('readMarkerId', last_read_id); + } + + if (state.get('unread') > 0 || shouldCountUnreadNotifications(state)) { + mutable.set('unread', mutable.get('pendingItems').count(item => item !== null) + mutable.get('items').count(item => item && compareId(item.get('id'), last_read_id) > 0)); + } + }); +}; + export default function notifications(state = initialState, action) { switch(action.type) { + case MARKERS_FETCH_SUCCESS: + return action.markers.notifications ? recountUnread(state, action.markers.notifications.last_read_id) : state; + case NOTIFICATIONS_MOUNT: + return updateMounted(state); + case NOTIFICATIONS_UNMOUNT: + return state.update('mounted', count => count - 1); + case APP_FOCUS: + return updateVisibility(state, true); + case APP_UNFOCUS: + return updateVisibility(state, false); case NOTIFICATIONS_LOAD_PENDING: return state.update('items', list => state.get('pendingItems').concat(list.take(40))).set('pendingItems', ImmutableList()).set('unread', 0); case NOTIFICATIONS_EXPAND_REQUEST: @@ -144,10 +243,13 @@ export default function notifications(state = initialState, action) { return action.timeline === 'home' ? state.update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) : state; - case NOTIFICATIONS_MOUNT: - return state.set('mounted', true); - case NOTIFICATIONS_UNMOUNT: - return state.set('mounted', false); + case NOTIFICATIONS_MARK_AS_READ: + const lastNotification = state.get('items').find(item => item !== null); + return lastNotification ? recountUnread(state, lastNotification.get('id')) : state; + case NOTIFICATIONS_SET_BROWSER_SUPPORT: + return state.set('browserSupport', action.value); + case NOTIFICATIONS_SET_BROWSER_PERMISSION: + return state.set('browserPermission', action.value); default: return state; } diff --git a/app/javascript/mastodon/reducers/picture_in_picture.js b/app/javascript/mastodon/reducers/picture_in_picture.js new file mode 100644 index 0000000000000000000000000000000000000000..06cd8c5e875051b584d0338d08d3f0c71d1285b1 --- /dev/null +++ b/app/javascript/mastodon/reducers/picture_in_picture.js @@ -0,0 +1,22 @@ +import { PICTURE_IN_PICTURE_DEPLOY, PICTURE_IN_PICTURE_REMOVE } from 'mastodon/actions/picture_in_picture'; + +const initialState = { + statusId: null, + accountId: null, + type: null, + src: null, + muted: false, + volume: 0, + currentTime: 0, +}; + +export default function pictureInPicture(state = initialState, action) { + switch(action.type) { + case PICTURE_IN_PICTURE_DEPLOY: + return { statusId: action.statusId, accountId: action.accountId, type: action.playerType, ...action.props }; + case PICTURE_IN_PICTURE_REMOVE: + return { ...initialState }; + default: + return state; + } +}; diff --git a/app/javascript/mastodon/reducers/relationships.js b/app/javascript/mastodon/reducers/relationships.js index 1d050cc6349915a25036380113c1a7cf0dcd52c6..53949258a3206b1da3127442d79127406a0cb6d9 100644 --- a/app/javascript/mastodon/reducers/relationships.js +++ b/app/javascript/mastodon/reducers/relationships.js @@ -45,7 +45,7 @@ const initialState = ImmutableMap(); export default function relationships(state = initialState, action) { switch(action.type) { case ACCOUNT_FOLLOW_REQUEST: - return state.setIn([action.id, action.locked ? 'requested' : 'following'], true); + return state.getIn([action.id, 'following']) ? state : state.setIn([action.id, action.locked ? 'requested' : 'following'], true); case ACCOUNT_FOLLOW_FAIL: return state.setIn([action.id, action.locked ? 'requested' : 'following'], false); case ACCOUNT_UNFOLLOW_REQUEST: diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index efef2ad9a5364bbc6343501f54013b8e70ac7874..357ab352aee2b25561e9410237ab8815803bc195 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -29,12 +29,13 @@ const initialState = ImmutableMap({ notifications: ImmutableMap({ alerts: ImmutableMap({ - follow: true, + follow: false, follow_request: false, - favourite: true, - reblog: true, - mention: true, - poll: true, + favourite: false, + reblog: false, + mention: false, + poll: false, + status: false, }), quickFilter: ImmutableMap({ @@ -43,6 +44,8 @@ const initialState = ImmutableMap({ advanced: false, }), + dismissPermissionBanner: false, + shows: ImmutableMap({ follow: true, follow_request: false, @@ -50,6 +53,7 @@ const initialState = ImmutableMap({ reblog: true, mention: true, poll: true, + status: true, }), sounds: ImmutableMap({ @@ -59,6 +63,7 @@ const initialState = ImmutableMap({ reblog: true, mention: true, poll: true, + status: true, }), }), diff --git a/app/javascript/mastodon/reducers/user_lists.js b/app/javascript/mastodon/reducers/user_lists.js index 8165952a700debfd87d9bc54d7399475384e4988..10aaa2d682d6b0fa06ba447762cc1121a04dee73 100644 --- a/app/javascript/mastodon/reducers/user_lists.js +++ b/app/javascript/mastodon/reducers/user_lists.js @@ -53,14 +53,20 @@ import { } from 'mastodon/actions/directory'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +const initialListState = ImmutableMap({ + next: null, + isLoading: false, + items: ImmutableList(), +}); + const initialState = ImmutableMap({ - followers: ImmutableMap(), - following: ImmutableMap(), - reblogged_by: ImmutableMap(), - favourited_by: ImmutableMap(), - follow_requests: ImmutableMap(), - blocks: ImmutableMap(), - mutes: ImmutableMap(), + followers: initialListState, + following: initialListState, + reblogged_by: initialListState, + favourited_by: initialListState, + follow_requests: initialListState, + blocks: initialListState, + mutes: initialListState, }); const normalizeList = (state, path, accounts, next) => { diff --git a/app/javascript/mastodon/rtl.js b/app/javascript/mastodon/rtl.js deleted file mode 100644 index 89bed6de88811a5be77b99fbee174c7276898f67..0000000000000000000000000000000000000000 --- a/app/javascript/mastodon/rtl.js +++ /dev/null @@ -1,32 +0,0 @@ -// U+0590 to U+05FF - Hebrew -// U+0600 to U+06FF - Arabic -// U+0700 to U+074F - Syriac -// U+0750 to U+077F - Arabic Supplement -// U+0780 to U+07BF - Thaana -// U+07C0 to U+07FF - N'Ko -// U+0800 to U+083F - Samaritan -// U+08A0 to U+08FF - Arabic Extended-A -// U+FB1D to U+FB4F - Hebrew presentation forms -// U+FB50 to U+FDFF - Arabic presentation forms A -// U+FE70 to U+FEFF - Arabic presentation forms B - -const rtlChars = /[\u0590-\u083F]|[\u08A0-\u08FF]|[\uFB1D-\uFDFF]|[\uFE70-\uFEFF]/mg; - -export function isRtl(text) { - if (text.length === 0) { - return false; - } - - text = text.replace(/(?:^|[^\/\w])@([a-z0-9_]+(@[a-z0-9\.\-]+)?)/ig, ''); - text = text.replace(/(?:^|[^\/\w])#([\S]+)/ig, ''); - text = text.replace(/\s+/g, ''); - text = text.replace(/(\w\S+\.\w{2,}\S*)/g, ''); - - const matches = text.match(rtlChars); - - if (!matches) { - return false; - } - - return matches.length / text.length > 0.3; -}; diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index fd3b72f96c62a7592a6453d477abcca31e0e9368..1e19db65d027f006570a67a98936f923801fc71a 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -1,5 +1,5 @@ import { createSelector } from 'reselect'; -import { List as ImmutableList, is } from 'immutable'; +import { List as ImmutableList, Map as ImmutableMap, is } from 'immutable'; import { me } from '../initial_state'; const getAccountBase = (state, id) => state.getIn(['accounts', id], null); @@ -121,6 +121,16 @@ export const makeGetStatus = () => { ); }; +export const makeGetPictureInPicture = () => { + return createSelector([ + (state, { id }) => state.get('picture_in_picture').statusId === id, + (state) => state.getIn(['meta', 'layout']) !== 'mobile', + ], (inUse, available) => ImmutableMap({ + inUse: inUse && available, + available, + })); +}; + const getAlertsBase = state => state.get('alerts'); export const getAlerts = createSelector([getAlertsBase], (base) => { diff --git a/app/javascript/mastodon/stream.js b/app/javascript/mastodon/stream.js index 0cb2b228f3c29b8e33fd120d1734a4aeb26fc585..c6d12cd6ff7c0bf5044b5ba3f39597233cde23a1 100644 --- a/app/javascript/mastodon/stream.js +++ b/app/javascript/mastodon/stream.js @@ -1,87 +1,235 @@ +// @ts-check + import WebSocketClient from '@gamestdio/websocket'; -const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max)); +/** + * @type {WebSocketClient | undefined} + */ +let sharedConnection; -const knownEventTypes = [ - 'update', - 'delete', - 'notification', - 'conversation', - 'filters_changed', -]; +/** + * @typedef Subscription + * @property {string} channelName + * @property {Object.<string, string>} params + * @property {function(): void} onConnect + * @property {function(StreamEvent): void} onReceive + * @property {function(): void} onDisconnect + */ -export function connectStream(path, pollingRefresh = null, callbacks = () => ({ onConnect() {}, onDisconnect() {}, onReceive() {} })) { - return (dispatch, getState) => { - const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']); - const accessToken = getState().getIn(['meta', 'access_token']); - const { onConnect, onDisconnect, onReceive } = callbacks(dispatch, getState); +/** + * @typedef StreamEvent + * @property {string} event + * @property {object} payload + */ - let polling = null; +/** + * @type {Array.<Subscription>} + */ +const subscriptions = []; - const setupPolling = () => { - pollingRefresh(dispatch, () => { - polling = setTimeout(() => setupPolling(), 20000 + randomIntUpTo(20000)); - }); - }; +/** + * @type {Object.<string, number>} + */ +const subscriptionCounters = {}; + +/** + * @param {Subscription} subscription + */ +const addSubscription = subscription => { + subscriptions.push(subscription); +}; + +/** + * @param {Subscription} subscription + */ +const removeSubscription = subscription => { + const index = subscriptions.indexOf(subscription); + + if (index !== -1) { + subscriptions.splice(index, 1); + } +}; + +/** + * @param {Subscription} subscription + */ +const subscribe = ({ channelName, params, onConnect }) => { + const key = channelNameWithInlineParams(channelName, params); + + subscriptionCounters[key] = subscriptionCounters[key] || 0; + + if (subscriptionCounters[key] === 0) { + sharedConnection.send(JSON.stringify({ type: 'subscribe', stream: channelName, ...params })); + } + + subscriptionCounters[key] += 1; + onConnect(); +}; - const clearPolling = () => { - if (polling) { - clearTimeout(polling); - polling = null; +/** + * @param {Subscription} subscription + */ +const unsubscribe = ({ channelName, params, onDisconnect }) => { + const key = channelNameWithInlineParams(channelName, params); + + subscriptionCounters[key] = subscriptionCounters[key] || 1; + + if (subscriptionCounters[key] === 1 && sharedConnection.readyState === WebSocketClient.OPEN) { + sharedConnection.send(JSON.stringify({ type: 'unsubscribe', stream: channelName, ...params })); + } + + subscriptionCounters[key] -= 1; + onDisconnect(); +}; + +const sharedCallbacks = { + connected () { + subscriptions.forEach(subscription => subscribe(subscription)); + }, + + received (data) { + const { stream } = data; + + subscriptions.filter(({ channelName, params }) => { + const streamChannelName = stream[0]; + + if (stream.length === 1) { + return channelName === streamChannelName; } - }; - const subscription = getStream(streamingAPIBaseURL, accessToken, path, { - connected () { - if (pollingRefresh) { - clearPolling(); - } + const streamIdentifier = stream[1]; - onConnect(); - }, + if (['hashtag', 'hashtag:local'].includes(channelName)) { + return channelName === streamChannelName && params.tag === streamIdentifier; + } else if (channelName === 'list') { + return channelName === streamChannelName && params.list === streamIdentifier; + } - disconnected () { - if (pollingRefresh) { - polling = setTimeout(() => setupPolling(), randomIntUpTo(40000)); - } + return false; + }).forEach(subscription => { + subscription.onReceive(data); + }); + }, - onDisconnect(); + disconnected () { + subscriptions.forEach(subscription => unsubscribe(subscription)); + }, + + reconnected () { + }, +}; + +/** + * @param {string} channelName + * @param {Object.<string, string>} params + * @return {string} + */ +const channelNameWithInlineParams = (channelName, params) => { + if (Object.keys(params).length === 0) { + return channelName; + } + + return `${channelName}&${Object.keys(params).map(key => `${key}=${params[key]}`).join('&')}`; +}; + +/** + * @param {string} channelName + * @param {Object.<string, string>} params + * @param {function(Function, Function): { onConnect: (function(): void), onReceive: (function(StreamEvent): void), onDisconnect: (function(): void) }} callbacks + * @return {function(): void} + */ +export const connectStream = (channelName, params, callbacks) => (dispatch, getState) => { + const streamingAPIBaseURL = getState().getIn(['meta', 'streaming_api_base_url']); + const accessToken = getState().getIn(['meta', 'access_token']); + const { onConnect, onReceive, onDisconnect } = callbacks(dispatch, getState); + + // If we cannot use a websockets connection, we must fall back + // to using individual connections for each channel + if (!streamingAPIBaseURL.startsWith('ws')) { + const connection = createConnection(streamingAPIBaseURL, accessToken, channelNameWithInlineParams(channelName, params), { + connected () { + onConnect(); }, received (data) { onReceive(data); }, - reconnected () { - if (pollingRefresh) { - clearPolling(); - pollingRefresh(dispatch); - } + disconnected () { + onDisconnect(); + }, + reconnected () { onConnect(); }, - }); - const disconnect = () => { - if (subscription) { - subscription.close(); - } - - clearPolling(); + return () => { + connection.close(); }; + } + + const subscription = { + channelName, + params, + onConnect, + onReceive, + onDisconnect, + }; + + addSubscription(subscription); + + // If a connection is open, we can execute the subscription right now. Otherwise, + // because we have already registered it, it will be executed on connect - return disconnect; + if (!sharedConnection) { + sharedConnection = /** @type {WebSocketClient} */ (createConnection(streamingAPIBaseURL, accessToken, '', sharedCallbacks)); + } else if (sharedConnection.readyState === WebSocketClient.OPEN) { + subscribe(subscription); + } + + return () => { + removeSubscription(subscription); + unsubscribe(subscription); }; -} +}; + +const KNOWN_EVENT_TYPES = [ + 'update', + 'delete', + 'notification', + 'conversation', + 'filters_changed', + 'encrypted_message', + 'announcement', + 'announcement.delete', + 'announcement.reaction', +]; +/** + * @param {MessageEvent} e + * @param {function(StreamEvent): void} received + */ +const handleEventSourceMessage = (e, received) => { + received({ + event: e.type, + payload: e.data, + }); +}; + +/** + * @param {string} streamingAPIBaseURL + * @param {string} accessToken + * @param {string} channelName + * @param {{ connected: Function, received: function(StreamEvent): void, disconnected: Function, reconnected: Function }} callbacks + * @return {WebSocketClient | EventSource} + */ +const createConnection = (streamingAPIBaseURL, accessToken, channelName, { connected, received, disconnected, reconnected }) => { + const params = channelName.split('&'); -export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) { - const params = stream.split('&'); - stream = params.shift(); + channelName = params.shift(); if (streamingAPIBaseURL.startsWith('ws')) { - params.unshift(`stream=${stream}`); const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`, accessToken); ws.onopen = connected; @@ -92,28 +240,26 @@ export default function getStream(streamingAPIBaseURL, accessToken, stream, { co return ws; } - stream = stream.replace(/:/g, '/'); + channelName = channelName.replace(/:/g, '/'); + + if (channelName.endsWith(':media')) { + channelName = channelName.replace('/media', ''); + params.push('only_media=true'); + } + params.push(`access_token=${accessToken}`); - const es = new EventSource(`${streamingAPIBaseURL}/api/v1/streaming/${stream}?${params.join('&')}`); - let firstConnect = true; + const es = new EventSource(`${streamingAPIBaseURL}/api/v1/streaming/${channelName}?${params.join('&')}`); + es.onopen = () => { - if (firstConnect) { - firstConnect = false; - connected(); - } else { - reconnected(); - } + connected(); }; - for (let type of knownEventTypes) { - es.addEventListener(type, (e) => { - received({ - event: e.type, - payload: e.data, - }); - }); - } - es.onerror = disconnected; + + KNOWN_EVENT_TYPES.forEach(type => { + es.addEventListener(type, e => handleEventSourceMessage(/** @type {MessageEvent} */ (e), received)); + }); + + es.onerror = /** @type {function(): void} */ (disconnected); return es; }; diff --git a/app/javascript/mastodon/utils/config.js b/app/javascript/mastodon/utils/config.js new file mode 100644 index 0000000000000000000000000000000000000000..932cd0cbf543e110eb5c3255f92f0fe9fc45ab07 --- /dev/null +++ b/app/javascript/mastodon/utils/config.js @@ -0,0 +1,10 @@ +import ready from '../ready'; + +export let assetHost = ''; + +ready(() => { + const cdnHost = document.querySelector('meta[name=cdn-host]'); + if (cdnHost) { + assetHost = cdnHost.content || ''; + } +}); diff --git a/app/javascript/mastodon/utils/notifications.js b/app/javascript/mastodon/utils/notifications.js new file mode 100644 index 0000000000000000000000000000000000000000..7634cac21f80cd6c44cae2b142e489a5b5a80e5a --- /dev/null +++ b/app/javascript/mastodon/utils/notifications.js @@ -0,0 +1,30 @@ +// Handles browser quirks, based on +// https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API + +const checkNotificationPromise = () => { + try { + // eslint-disable-next-line promise/catch-or-return + Notification.requestPermission().then(); + } catch(e) { + return false; + } + + return true; +}; + +const handlePermission = (permission, callback) => { + // Whatever the user answers, we make sure Chrome stores the information + if(!('permission' in Notification)) { + Notification.permission = permission; + } + + callback(Notification.permission); +}; + +export const requestNotificationPermission = (callback) => { + if (checkNotificationPromise()) { + Notification.requestPermission().then((permission) => handlePermission(permission, callback)).catch(console.warn); + } else { + Notification.requestPermission((permission) => handlePermission(permission, callback)); + } +}; diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js index 6c1cb61a2535cd748907f93ebdfbe74a26f88c6c..8f14853796a97cb4eaae070a9047b5421769582a 100644 --- a/app/javascript/mastodon/utils/resize_image.js +++ b/app/javascript/mastodon/utils/resize_image.js @@ -41,6 +41,45 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { } }); +// Some browsers don't allow reading from a canvas and instead return all-white +// or randomized data. Use a pre-defined image to check if reading the canvas +// works. +const checkCanvasReliability = () => new Promise((resolve, reject) => { + switch(_browser_quirks['canvas-read-unreliable']) { + case true: + reject('Canvas reading unreliable'); + break; + case false: + resolve(); + break; + default: + // 2×2 GIF with white, red, green and blue pixels + const testImageURL = + 'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7'; + const refData = + [255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]; + const img = new Image(); + img.onload = () => { + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + context.drawImage(img, 0, 0, 2, 2); + const imageData = context.getImageData(0, 0, 2, 2); + if (imageData.data.every((x, i) => refData[i] === x)) { + _browser_quirks['canvas-read-unreliable'] = false; + resolve(); + } else { + _browser_quirks['canvas-read-unreliable'] = true; + reject('Canvas reading unreliable'); + } + }; + img.onerror = () => { + _browser_quirks['canvas-read-unreliable'] = true; + reject('Failed to load test image'); + }; + img.src = testImageURL; + } +}); + const getImageUrl = inputFile => new Promise((resolve, reject) => { if (window.URL && URL.createObjectURL) { try { @@ -110,14 +149,6 @@ const processImage = (img, { width, height, orientation, type = 'image/png' }) = context.drawImage(img, 0, 0, width, height); - // The Tor Browser and maybe other browsers may prevent reading from canvas - // and return an all-white image instead. Assume reading failed if the resized - // image is perfectly white. - const imageData = context.getImageData(0, 0, width, height); - if (imageData.data.every(value => value === 255)) { - throw 'Failed to read from canvas'; - } - canvas.toBlob(resolve, type); }); @@ -127,7 +158,8 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) = const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height))); const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width))); - getOrientation(img, type) + checkCanvasReliability() + .then(getOrientation(img, type)) .then(orientation => processImage(img, { width: newWidth, height: newHeight, diff --git a/app/javascript/packs/about.js b/app/javascript/packs/about.js index 843cb2c87d43860242a16b32852452f597080f78..892d825ece23e552289d47300a9d887e9949f938 100644 --- a/app/javascript/packs/about.js +++ b/app/javascript/packs/about.js @@ -1,3 +1,4 @@ +import './public-path'; import loadPolyfills from '../mastodon/load_polyfills'; import { start } from '../mastodon/common'; diff --git a/app/javascript/packs/admin.js b/app/javascript/packs/admin.js index 51f92de8aa58a79bed1a5f5fd73d3b74cdc9e9f6..8fd1b8a8edbb934a2d655c92cf98ad738fff538d 100644 --- a/app/javascript/packs/admin.js +++ b/app/javascript/packs/admin.js @@ -1,3 +1,4 @@ +import './public-path'; import { delegate } from '@rails/ujs'; import ready from '../mastodon/ready'; @@ -56,18 +57,46 @@ const onEnableBootstrapTimelineAccountsChange = (target) => { bootstrapTimelineAccountsField.disabled = !target.checked; if (target.checked) { bootstrapTimelineAccountsField.parentElement.classList.remove('disabled'); + bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled'); } else { bootstrapTimelineAccountsField.parentElement.classList.add('disabled'); + bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled'); } } }; delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); +const onChangeRegistrationMode = (target) => { + const enabled = target.value === 'approved'; + + [].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => { + input.disabled = !enabled; + if (enabled) { + let element = input; + do { + element.classList.remove('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } else { + let element = input; + do { + element.classList.add('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } + }); +}; + +delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target)); + ready(() => { const domainBlockSeverityInput = document.getElementById('domain_block_severity'); if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput); const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts'); if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); + + const registrationMode = document.getElementById('form_admin_settings_registrations_mode'); + if (registrationMode) onChangeRegistrationMode(registrationMode); }); diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index c65ebed74f8b94abf31111d7aa395e2a33a42ba4..91240aecfb85a09494bcdb6e54837ef244d57f43 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1,3 +1,4 @@ +import './public-path'; import loadPolyfills from '../mastodon/load_polyfills'; import { start } from '../mastodon/common'; diff --git a/app/javascript/packs/error.js b/app/javascript/packs/error.js index 685c890658a007886aaafa00509d42916de05788..6376dc2f5dfcc1f63eb3f5af6c847caf9209e1de 100644 --- a/app/javascript/packs/error.js +++ b/app/javascript/packs/error.js @@ -1,3 +1,4 @@ +import './public-path'; import ready from '../mastodon/ready'; ready(() => { diff --git a/app/javascript/packs/public-path.js b/app/javascript/packs/public-path.js new file mode 100644 index 0000000000000000000000000000000000000000..f96109f4fcd1824561deaeb737f12927f806da78 --- /dev/null +++ b/app/javascript/packs/public-path.js @@ -0,0 +1,21 @@ +// Dynamically set webpack's loading path depending on a meta header, in order +// to share the same assets regardless of instance configuration. +// See https://webpack.js.org/guides/public-path/#on-the-fly + +function removeOuterSlashes(string) { + return string.replace(/^\/*/, '').replace(/\/*$/, ''); +} + +function formatPublicPath(host = '', path = '') { + let formattedHost = removeOuterSlashes(host); + if (formattedHost && !/^http/i.test(formattedHost)) { + formattedHost = `//${formattedHost}`; + } + const formattedPath = removeOuterSlashes(path); + return `${formattedHost}/${formattedPath}/`; +} + +const cdnHost = document.querySelector('meta[name=cdn-host]'); + +// eslint-disable-next-line camelcase, no-undef, no-unused-vars +__webpack_public_path__ = formatPublicPath(cdnHost ? cdnHost.content : '', process.env.PUBLIC_OUTPUT_PATH); diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index 08cc662e60b65c1e904dee7c06464d115256acdf..8c5c15b8f4c8ddc3d503f474e2fc7e36a3a338a8 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -1,3 +1,4 @@ +import './public-path'; import escapeTextContentForBrowser from 'escape-html'; import loadPolyfills from '../mastodon/load_polyfills'; import ready from '../mastodon/ready'; @@ -116,6 +117,28 @@ function main() { new Rellax('.parallax', { speed: -1 }); } + delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => { + const password = document.getElementById('registration_user_password'); + const confirmation = document.getElementById('registration_user_password_confirmation'); + if (password.value && password.value !== confirmation.value) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); + } else { + confirmation.setCustomValidity(''); + } + }); + + delegate(document, '#user_password,#user_password_confirmation', 'input', () => { + const password = document.getElementById('user_password'); + const confirmation = document.getElementById('user_password_confirmation'); + if (!confirmation) return; + + if (password.value && password.value !== confirmation.value) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); + } else { + confirmation.setCustomValidity(''); + } + }); + delegate(document, '.custom-emoji', 'mouseover', getEmojiAnimationHandler('data-original')); delegate(document, '.custom-emoji', 'mouseout', getEmojiAnimationHandler('data-static')); @@ -257,6 +280,17 @@ function main() { target.style.display = 'block'; } }); + + // Empty the honeypot fields in JS in case something like an extension + // automatically filled them. + delegate(document, '#registration_new_user,#new_user', 'submit', () => { + ['user_website', 'user_confirm_password', 'registration_user_website', 'registration_user_confirm_password'].forEach(id => { + const field = document.getElementById(id); + if (field) { + field.value = ''; + } + }); + }); } loadPolyfills() diff --git a/app/javascript/packs/share.js b/app/javascript/packs/share.js index 4ef23e1b2e9b8ef705ff07a4d9e468df39d89801..1225d7b52943151a18249c091a7454a63c012d79 100644 --- a/app/javascript/packs/share.js +++ b/app/javascript/packs/share.js @@ -1,3 +1,4 @@ +import './public-path'; import loadPolyfills from '../mastodon/load_polyfills'; import { start } from '../mastodon/common'; diff --git a/app/javascript/packs/two_factor_authentication.js b/app/javascript/packs/two_factor_authentication.js new file mode 100644 index 0000000000000000000000000000000000000000..dde06be8c19f5ec0caebda7b8e7236f0e42d5565 --- /dev/null +++ b/app/javascript/packs/two_factor_authentication.js @@ -0,0 +1,118 @@ +import axios from 'axios'; +import * as WebAuthnJSON from '@github/webauthn-json'; +import ready from '../mastodon/ready'; +import 'regenerator-runtime/runtime'; + +function getCSRFToken() { + var CSRFSelector = document.querySelector('meta[name="csrf-token"]'); + if (CSRFSelector) { + return CSRFSelector.getAttribute('content'); + } else { + return null; + } +} + +function hideFlashMessages() { + Array.from(document.getElementsByClassName('flash-message')).forEach(function(flashMessage) { + flashMessage.classList.add('hidden'); + }); +} + +function callback(url, body) { + axios.post(url, JSON.stringify(body), { + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-CSRF-Token': getCSRFToken(), + }, + credentials: 'same-origin', + }).then(function(response) { + window.location.replace(response.data.redirect_path); + }).catch(function(error) { + if (error.response.status === 422) { + const errorMessage = document.getElementById('security-key-error-message'); + errorMessage.classList.remove('hidden'); + console.error(error.response.data.error); + } else { + console.error(error); + } + }); +} + +ready(() => { + if (!WebAuthnJSON.supported()) { + const unsupported_browser_message = document.getElementById('unsupported-browser-message'); + if (unsupported_browser_message) { + unsupported_browser_message.classList.remove('hidden'); + document.querySelector('.btn.js-webauthn').disabled = true; + } + } + + + const webAuthnCredentialRegistrationForm = document.getElementById('new_webauthn_credential'); + if (webAuthnCredentialRegistrationForm) { + webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => { + event.preventDefault(); + + var nickname = event.target.querySelector('input[name="new_webauthn_credential[nickname]"]'); + if (nickname.value) { + axios.get('/settings/security_keys/options') + .then((response) => { + const credentialOptions = response.data; + + WebAuthnJSON.create({ 'publicKey': credentialOptions }).then((credential) => { + var params = { 'credential': credential, 'nickname': nickname.value }; + callback('/settings/security_keys', params); + }).catch((error) => { + const errorMessage = document.getElementById('security-key-error-message'); + errorMessage.classList.remove('hidden'); + console.error(error); + }); + }).catch((error) => { + console.error(error.response.data.error); + }); + } else { + nickname.focus(); + } + }); + } + + const webAuthnCredentialAuthenticationForm = document.getElementById('webauthn-form'); + if (webAuthnCredentialAuthenticationForm) { + webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => { + event.preventDefault(); + + axios.get('sessions/security_key_options') + .then((response) => { + const credentialOptions = response.data; + + WebAuthnJSON.get({ 'publicKey': credentialOptions }).then((credential) => { + var params = { 'user': { 'credential': credential } }; + callback('sign_in', params); + }).catch((error) => { + const errorMessage = document.getElementById('security-key-error-message'); + errorMessage.classList.remove('hidden'); + console.error(error); + }); + }).catch((error) => { + console.error(error.response.data.error); + }); + }); + + const otpAuthenticationForm = document.getElementById('otp-authentication-form'); + + const linkToOtp = document.getElementById('link-to-otp'); + linkToOtp.addEventListener('click', () => { + webAuthnCredentialAuthenticationForm.classList.add('hidden'); + otpAuthenticationForm.classList.remove('hidden'); + hideFlashMessages(); + }); + + const linkToWebAuthn = document.getElementById('link-to-webauthn'); + linkToWebAuthn.addEventListener('click', () => { + otpAuthenticationForm.classList.add('hidden'); + webAuthnCredentialAuthenticationForm.classList.remove('hidden'); + hideFlashMessages(); + }); + } +}); diff --git a/app/javascript/styles/contrast/diff.scss b/app/javascript/styles/contrast/diff.scss index 5a40e7d79a9f0a537bc5947fa9f21c3242d0ccf1..841ed66480c6288375f7ce8045bfbab88261e86a 100644 --- a/app/javascript/styles/contrast/diff.scss +++ b/app/javascript/styles/contrast/diff.scss @@ -75,3 +75,8 @@ .public-layout .public-account-header__tabs__tabs .counter.active::after { border-bottom: 4px solid $ui-highlight-color; } + +.compose-form .autosuggest-textarea__textarea::placeholder, +.compose-form .spoiler-input__input::placeholder { + color: $inverted-text-color; +} diff --git a/app/javascript/styles/mailer.scss b/app/javascript/styles/mailer.scss index e25a80c043287ba3aaae16fdbbd134bdb0a3cdc8..55ebd309195352acf8628d92ffa8172a0be823e8 100644 --- a/app/javascript/styles/mailer.scss +++ b/app/javascript/styles/mailer.scss @@ -58,6 +58,16 @@ td { vertical-align: top; } +.auto-dir { + p { + unicode-bidi: plaintext; + } + + a { + unicode-bidi: isolate; + } +} + .email-table, .content-section, .column, @@ -96,7 +106,7 @@ body { .col-3, .col-4, .col-5, -.col-6, { +.col-6 { font-size: 0; display: inline-block; width: 100%; diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 8c8d69fc47e284e3e9eb0057d01f53b5a47e618f..d4290d7e61a80eb919d9e25594b9fb06570ee88b 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -256,14 +256,6 @@ html { background: $ui-base-color; } -.status.status-direct { - background: lighten($ui-base-color, 4%); -} - -.focusable:focus .status.status-direct { - background: lighten($ui-base-color, 8%); -} - .detailed-status, .detailed-status__action-bar { background: $white; @@ -363,11 +355,45 @@ html { .error-modal, .onboarding-modal, .report-modal__comment .setting-text__wrapper, -.report-modal__comment .setting-text { +.report-modal__comment .setting-text, +.announcements, +.picture-in-picture__header, +.picture-in-picture__footer, +.reactions-bar__item { background: $white; border: 1px solid lighten($ui-base-color, 8%); } +.reactions-bar__item { + &:hover, + &:focus, + &:active { + background-color: $ui-base-color; + } +} + +.reactions-bar__item.active { + background-color: mix($white, $ui-highlight-color, 80%); + border-color: mix(lighten($ui-base-color, 8%), $ui-highlight-color, 80%); +} + +.media-modal__overlay .picture-in-picture__footer { + border: 0; +} + +.picture-in-picture__header { + border-bottom: 0; +} + +.announcements, +.picture-in-picture__footer { + border-top: 0; +} + +.icon-with-badge__badge { + border-color: $white; +} + .report-modal__comment { border-right-color: lighten($ui-base-color, 8%); } @@ -520,6 +546,12 @@ html { } } +.picture-in-picture-placeholder { + background: $white; + border-color: lighten($ui-base-color, 8%); + color: lighten($ui-base-color, 8%); +} + .brand__tagline { color: $ui-secondary-color; } @@ -767,3 +799,8 @@ html { .compose-form .compose-form__warning { box-shadow: none; } + +.mute-modal select { + border: 1px solid lighten($ui-base-color, 8%); + background: $simple-background-color url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(lighten($ui-base-color, 8%))}'/></svg>") no-repeat right 8px center / auto 16px; +} diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index 3be0aee49bcaab3646dedc80da8df89e031e8076..d6bd9e3c6054b0f164f79955ab7e34a2ac4e5d99 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -732,6 +732,7 @@ $small-breakpoint: 960px; &__column { flex: 1 1 50%; + overflow-x: hidden; } } diff --git a/app/javascript/styles/mastodon/boost.scss b/app/javascript/styles/mastodon/boost.scss index 5a6d6ae406c4610faf56bd1bcbba343f7c67b23a..fb1451cb245bee001cbc058098cc82d8234c3527 100644 --- a/app/javascript/styles/mastodon/boost.scss +++ b/app/javascript/styles/mastodon/boost.scss @@ -1,11 +1,32 @@ -button.icon-button i.fa-retweet { - background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($action-button-color)}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); +button.icon-button { + i.fa-retweet { + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($action-button-color)}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); + } - &:hover { + &:hover i.fa-retweet { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color(lighten($action-button-color, 7%))}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); } -} -button.icon-button.disabled i.fa-retweet { - background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); + &.reblogPrivate { + i.fa-retweet { + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='209' width='22'><path d='M 4.9707031 3.1503906 L 4.9707031 3.1601562 C 4.8707031 3.1901563 4.8 3.2598438 4.75 3.3398438 L 0.80078125 8.2402344 C 0.60078125 8.5402344 0.8292187 9.0190625 1.1992188 9.0390625 L 3.5996094 9.0390625 L 3.5996094 11.720703 C 3.5996094 15.980703 3.0497656 15.339844 7.2597656 15.339844 L 11.869141 15.339844 L 11.869141 14.119141 L 11.869141 13.523438 L 11.869141 12.441406 C 11.869141 12.441406 11.869141 12.439453 11.869141 12.439453 L 7.2695312 12.439453 C 6.8295312 12.439453 6.5507814 12.140703 6.5507812 11.720703 L 6.5507812 9.0195312 L 9.0507812 9.0195312 C 9.4207813 9.0495313 9.6792188 8.54 9.4492188 8.25 L 5.5 3.3496094 C 5.38 3.1796094 5.1607031 3.1003906 4.9707031 3.1503906 z M 17.150391 3.5800781 L 17.130859 3.5898438 C 16.580859 3.5698436 15.810469 3.609375 14.730469 3.609375 L 7.0996094 3.609375 L 9.4199219 6.4609375 L 9.4492188 6.5195312 L 14.699219 6.5195312 C 15.106887 6.5195312 15.397113 6.7872181 15.414062 7.2050781 C 15.738375 7.0991315 16.077769 7.0273437 16.435547 7.0273438 L 16.578125 7.0273438 C 17.24903 7.0273438 17.874081 7.2325787 18.400391 7.578125 L 18.400391 7.2402344 C 18.400391 4.0902344 18.800391 3.6200781 17.150391 3.5800781 z M 16.435547 8.0273438 C 15.143818 8.0273438 14.083984 9.0851838 14.083984 10.376953 L 14.083984 11.607422 L 13.570312 11.607422 C 13.375448 11.607422 13.210603 11.704118 13.119141 11.791016 C 13.027691 11.877916 12.983569 11.958238 12.951172 12.03125 C 12.886382 12.177277 12.867187 12.304789 12.867188 12.441406 L 12.867188 13.523438 L 12.867188 14.119141 L 12.867188 15.677734 L 12.867188 16.509766 L 13.570312 16.509766 L 19.472656 16.509766 L 20.173828 16.509766 L 20.173828 15.677734 L 20.173828 13.523438 L 20.173828 12.441406 C 20.173828 12.304794 20.156597 12.177281 20.091797 12.03125 C 20.059397 11.95824 20.015299 11.877916 19.923828 11.791016 C 19.832368 11.704116 19.667509 11.607422 19.472656 11.607422 L 18.927734 11.607422 L 18.927734 10.376953 C 18.927734 9.0851838 17.867902 8.0273438 16.576172 8.0273438 L 16.435547 8.0273438 z M 16.435547 9.2207031 L 16.576172 9.2207031 C 17.22782 9.2207031 17.734375 9.7251013 17.734375 10.376953 L 17.734375 11.607422 L 15.277344 11.607422 L 15.277344 10.376953 C 15.277344 9.7251013 15.7839 9.2207031 16.435547 9.2207031 z M 12.919922 9.9394531 C 12.559922 9.9594531 12.359141 10.480234 12.619141 10.740234 L 12.751953 10.904297 C 12.862211 10.870135 12.980058 10.842244 13.085938 10.802734 L 13.085938 10.378906 C 13.085938 10.228632 13.111295 10.084741 13.130859 9.9394531 L 12.919922 9.9394531 z M 19.882812 9.9394531 C 19.902378 10.084741 19.927734 10.228632 19.927734 10.378906 L 19.927734 10.791016 C 20.168811 10.875098 20.455966 10.916935 20.613281 11.066406 C 20.691227 11.140457 20.749315 11.223053 20.806641 11.302734 L 21.259766 10.740234 C 21.519766 10.460234 21.260625 9.9094531 20.890625 9.9394531 L 19.882812 9.9394531 z M 16.435547 10.220703 C 16.301234 10.220703 16.277344 10.244432 16.277344 10.378906 L 16.277344 10.607422 L 16.734375 10.607422 L 16.734375 10.378906 C 16.734375 10.244433 16.712442 10.220703 16.578125 10.220703 L 16.435547 10.220703 z ' fill='#{hex-color($action-button-color)}' stroke-width='0'/><path d='M 7.7792969 19.650391 L 7.7792969 19.660156 C 7.5392969 19.680156 7.3398437 19.910156 7.3398438 20.160156 L 7.3398438 22.619141 L 7.2792969 22.619141 C 6.1992969 22.619141 5.4208594 22.589844 4.8808594 22.589844 C 3.2408594 22.589844 3.6308594 23.020234 3.6308594 26.240234 L 3.6308594 30.710938 C 3.6308594 34.970937 3.0692969 34.330078 7.2792969 34.330078 L 8.5 34.330078 L 7.1992188 33.269531 C 7.0992188 33.189531 7.02 33.070703 7 32.970703 C 6.98 32.800703 7.0592186 32.619531 7.1992188 32.519531 L 8.5292969 31.419922 L 7.2792969 31.419922 C 6.8392969 31.419922 6.5605469 31.120703 6.5605469 30.720703 L 6.5605469 26.240234 C 6.5605469 25.800234 6.8392969 25.519531 7.2792969 25.519531 L 7.3398438 25.519531 L 7.3398438 28.019531 C 7.3398438 28.399531 7.8801564 28.650391 8.1601562 28.400391 L 13.060547 24.470703 C 13.310547 24.290703 13.310547 23.869453 13.060547 23.689453 L 8.1601562 19.769531 C 8.0601563 19.669531 7.9192969 19.630391 7.7792969 19.650391 z M 17.119141 22.580078 L 17.119141 22.589844 C 16.579141 22.569844 15.820703 22.609375 14.720703 22.609375 L 13.470703 22.609375 L 14.769531 23.679688 C 14.869531 23.749688 14.950703 23.879766 14.970703 24.009766 C 14.990703 24.169766 14.909531 24.310156 14.769531 24.410156 L 13.439453 25.509766 L 14.720703 25.509766 C 15.129702 25.509766 15.41841 25.778986 15.433594 26.199219 C 15.752266 26.097283 16.084896 26.027344 16.435547 26.027344 L 16.578125 26.027344 C 17.236645 26.027344 17.848901 26.228565 18.369141 26.5625 L 18.369141 26.240234 C 18.369141 23.090234 18.769141 22.620078 17.119141 22.580078 z M 16.435547 27.027344 C 15.143818 27.027344 14.083984 28.085184 14.083984 29.376953 L 14.083984 30.607422 L 13.570312 30.607422 C 13.375452 30.607422 13.210603 30.704118 13.119141 30.791016 C 13.027691 30.877916 12.983569 30.958238 12.951172 31.03125 C 12.886382 31.177277 12.867184 31.304789 12.867188 31.441406 L 12.867188 32.523438 L 12.867188 33.119141 L 12.867188 34.677734 L 12.867188 35.509766 L 13.570312 35.509766 L 19.472656 35.509766 L 20.173828 35.509766 L 20.173828 34.677734 L 20.173828 32.523438 L 20.173828 31.441406 C 20.173828 31.304794 20.156597 31.177281 20.091797 31.03125 C 20.059397 30.95824 20.015299 30.877916 19.923828 30.791016 C 19.832368 30.704116 19.667509 30.607422 19.472656 30.607422 L 18.927734 30.607422 L 18.927734 29.376953 C 18.927734 28.085184 17.867902 27.027344 16.576172 27.027344 L 16.435547 27.027344 z M 16.435547 28.220703 L 16.576172 28.220703 C 17.22782 28.220703 17.734375 28.725101 17.734375 29.376953 L 17.734375 30.607422 L 15.277344 30.607422 L 15.277344 29.376953 C 15.277344 28.725101 15.7839 28.220703 16.435547 28.220703 z M 13.109375 29.150391 L 8.9199219 32.509766 C 8.6599219 32.689766 8.6599219 33.109063 8.9199219 33.289062 L 11.869141 35.648438 L 11.869141 34.677734 L 11.869141 33.119141 L 11.869141 32.523438 L 11.869141 31.441406 C 11.869141 31.217489 11.912641 30.907486 12.037109 30.626953 C 12.093758 30.499284 12.228597 30.257492 12.429688 30.066406 C 12.580253 29.92335 12.859197 29.887344 13.085938 29.802734 L 13.085938 29.378906 C 13.085938 29.300761 13.104 29.227272 13.109375 29.150391 z M 16.435547 29.220703 C 16.301234 29.220703 16.277344 29.244432 16.277344 29.378906 L 16.277344 29.607422 L 16.734375 29.607422 L 16.734375 29.378906 C 16.734375 29.244433 16.712442 29.220703 16.578125 29.220703 L 16.435547 29.220703 z M 12.943359 36.509766 L 13.820312 37.210938 C 14.090314 37.460938 14.639141 37.210078 14.619141 36.830078 L 14.619141 36.509766 L 13.570312 36.509766 L 12.943359 36.509766 z M 10.330078 38.650391 L 10.339844 38.660156 C 10.099844 38.680156 9.9001562 38.910156 9.9101562 39.160156 L 9.9101562 41.630859 L 7.3007812 41.630859 C 6.2207812 41.630859 5.4403906 41.589844 4.9003906 41.589844 C 3.2603906 41.589844 3.6503906 42.020234 3.6503906 45.240234 L 3.6503906 49.710938 C 3.6503906 53.370936 3.4202344 53.409141 5.9902344 53.369141 L 4.6503906 52.269531 C 4.5503906 52.189531 4.4692187 52.070703 4.4492188 51.970703 C 4.4492188 51.800703 4.5203906 51.619531 4.6503906 51.519531 L 6.609375 49.919922 C 6.579375 49.859922 6.5703125 49.790703 6.5703125 49.720703 L 6.5703125 45.240234 C 6.5703125 44.800234 6.8490625 44.519531 7.2890625 44.519531 L 9.9003906 44.519531 L 9.9003906 47.019531 C 9.9003906 47.379531 10.399219 47.620391 10.699219 47.400391 L 15.630859 43.470703 C 15.870859 43.290703 15.870859 42.869453 15.630859 42.689453 L 10.689453 38.769531 C 10.589453 38.689531 10.460078 38.640391 10.330078 38.650391 z M 16.869141 41.585938 C 16.616211 41.581522 16.322969 41.584844 15.980469 41.589844 L 15.970703 41.589844 L 17.310547 42.689453 C 17.410547 42.759453 17.489766 42.889531 17.509766 43.019531 C 17.529766 43.179531 17.479609 43.319922 17.349609 43.419922 L 15.390625 45.019531 C 15.406724 45.075878 15.427133 45.132837 15.4375 45.197266 C 15.754974 45.096169 16.086404 45.027344 16.435547 45.027344 L 16.578125 45.027344 C 17.24129 45.027344 17.858323 45.230088 18.380859 45.568359 L 18.380859 45.25 C 18.380859 42.0475 18.639648 41.616836 16.869141 41.585938 z M 16.435547 46.027344 C 15.143818 46.027344 14.083984 47.085184 14.083984 48.376953 L 14.083984 49.607422 L 13.570312 49.607422 C 13.375448 49.607422 13.210603 49.704118 13.119141 49.791016 C 13.027691 49.877916 12.983569 49.958238 12.951172 50.03125 C 12.886382 50.177277 12.867187 50.304789 12.867188 50.441406 L 12.867188 51.523438 L 12.867188 52.119141 L 12.867188 53.677734 L 12.867188 54.509766 L 13.570312 54.509766 L 19.472656 54.509766 L 20.173828 54.509766 L 20.173828 53.677734 L 20.173828 51.523438 L 20.173828 50.441406 C 20.173828 50.304794 20.156597 50.177281 20.091797 50.03125 C 20.059397 49.95824 20.015299 49.877916 19.923828 49.791016 C 19.832368 49.704116 19.667509 49.607422 19.472656 49.607422 L 18.927734 49.607422 L 18.927734 48.376953 C 18.927734 47.085184 17.867902 46.027344 16.576172 46.027344 L 16.435547 46.027344 z M 16.435547 47.220703 L 16.576172 47.220703 C 17.22782 47.220703 17.734375 47.725101 17.734375 48.376953 L 17.734375 49.607422 L 15.277344 49.607422 L 15.277344 48.376953 C 15.277344 47.725101 15.7839 47.220703 16.435547 47.220703 z M 11.470703 47.490234 C 11.410703 47.510234 11.349063 47.539844 11.289062 47.589844 L 6.3496094 51.519531 C 6.1096094 51.699531 6.1096094 52.120781 6.3496094 52.300781 L 11.289062 56.220703 C 11.569064 56.440703 12.070312 56.199844 12.070312 55.839844 L 12.070312 55.509766 L 11.869141 55.509766 L 11.869141 53.677734 L 11.869141 52.119141 L 11.869141 51.523438 L 11.869141 50.441406 C 11.869141 50.217489 11.912641 49.907486 12.037109 49.626953 C 12.043809 49.611855 12.061451 49.584424 12.070312 49.566406 L 12.070312 47.960938 C 12.070312 47.660938 11.770703 47.430234 11.470703 47.490234 z M 16.435547 48.220703 C 16.301234 48.220703 16.277344 48.244432 16.277344 48.378906 L 16.277344 48.607422 L 16.734375 48.607422 L 16.734375 48.378906 C 16.734375 48.244433 16.712442 48.220703 16.578125 48.220703 L 16.435547 48.220703 z M 13.060547 57.650391 L 13.060547 57.660156 C 12.830547 57.690156 12.660156 57.920156 12.660156 58.160156 L 12.660156 60.630859 L 7.2792969 60.630859 C 6.1992969 60.630859 5.4208594 60.589844 4.8808594 60.589844 C 3.2408594 60.589844 3.6308594 61.020234 3.6308594 64.240234 L 3.6308594 69.109375 L 6.5605469 66.740234 L 6.5605469 64.240234 C 6.5605469 63.800234 6.8392969 63.519531 7.2792969 63.519531 L 12.660156 63.519531 L 12.660156 66.019531 C 12.660156 66.299799 12.960394 66.500006 13.226562 66.474609 C 13.625751 65.076914 14.904956 64.035678 16.421875 64.029297 L 18.380859 62.470703 C 18.620859 62.290703 18.620859 61.869453 18.380859 61.689453 L 13.439453 57.769531 C 13.339453 57.669531 13.200547 57.630391 13.060547 57.650391 z M 18.359375 63.810547 L 17.800781 64.269531 C 18.004793 64.350836 18.198411 64.450249 18.380859 64.568359 L 18.380859 64.25 L 18.380859 63.810547 L 18.359375 63.810547 z M 16.435547 65.027344 C 15.143818 65.027344 14.083984 66.085184 14.083984 67.376953 L 14.083984 68.607422 L 13.570312 68.607422 C 13.375448 68.607422 13.210603 68.704118 13.119141 68.791016 C 13.027691 68.877916 12.983569 68.958238 12.951172 69.03125 C 12.886382 69.177277 12.867187 69.304789 12.867188 69.441406 L 12.867188 70.523438 L 12.867188 71.119141 L 12.867188 72.677734 L 12.867188 73.509766 L 13.570312 73.509766 L 19.472656 73.509766 L 20.173828 73.509766 L 20.173828 72.677734 L 20.173828 70.523438 L 20.173828 69.441406 C 20.173828 69.304794 20.156597 69.177281 20.091797 69.03125 C 20.059397 68.95824 20.015299 68.877916 19.923828 68.791016 C 19.832368 68.704116 19.667509 68.607422 19.472656 68.607422 L 18.927734 68.607422 L 18.927734 67.376953 C 18.927734 66.085184 17.867902 65.027344 16.576172 65.027344 L 16.435547 65.027344 z M 16.435547 66.220703 L 16.576172 66.220703 C 17.22782 66.220703 17.734375 66.725101 17.734375 67.376953 L 17.734375 68.607422 L 15.277344 68.607422 L 15.277344 67.376953 C 15.277344 66.725101 15.7839 66.220703 16.435547 66.220703 z M 8.7207031 66.509766 C 8.6507031 66.529766 8.5895312 66.559375 8.5195312 66.609375 L 3.5996094 70.519531 C 3.3496094 70.699531 3.3496094 71.120781 3.5996094 71.300781 L 8.5292969 75.220703 C 8.8092969 75.440703 9.3105469 75.199844 9.3105469 74.839844 L 9.3105469 72.339844 L 11.869141 72.339844 L 11.869141 71.119141 L 11.869141 70.523438 L 11.869141 69.449219 L 9.3203125 69.449219 L 9.3203125 66.980469 C 9.3203125 66.680469 9.0007031 66.449766 8.7207031 66.509766 z M 16.435547 67.220703 C 16.301234 67.220703 16.277344 67.244432 16.277344 67.378906 L 16.277344 67.607422 L 16.734375 67.607422 L 16.734375 67.378906 C 16.734375 67.244433 16.712442 67.220703 16.578125 67.220703 L 16.435547 67.220703 z M 19.248047 78.800781 C 19.148558 78.831033 19.050295 78.90106 18.970703 78.970703 L 18.070312 79.869141 C 17.630312 79.569141 16.710703 79.619141 14.720703 79.619141 L 7.2792969 79.619141 C 6.1992969 79.619141 5.4208594 79.589844 4.8808594 79.589844 C 3.2408594 79.589844 3.6308594 80.020234 3.6308594 83.240234 L 3.6308594 83.939453 L 6.5605469 84.240234 L 6.5605469 83.240234 C 6.5605469 82.800234 6.8392969 82.519531 7.2792969 82.519531 L 14.720703 82.519531 C 14.920703 82.519531 15.090703 82.600703 15.220703 82.720703 L 13.419922 84.519531 C 13.279464 84.665607 13.281282 84.881022 13.363281 85.054688 C 13.880838 83.867655 15.067337 83.027344 16.435547 83.027344 L 16.578125 83.027344 C 18.290465 83.027344 19.703357 84.345788 19.890625 86.011719 L 19.960938 86.019531 C 20.240938 86.049531 20.520234 85.770234 20.490234 85.490234 L 19.789062 79.240234 C 19.789062 78.973661 19.498025 78.767523 19.25 78.800781 L 19.248047 78.800781 z M 16.435547 84.027344 C 15.143818 84.027344 14.083984 85.085184 14.083984 86.376953 L 14.083984 87.607422 L 13.570312 87.607422 C 13.375448 87.607422 13.210603 87.704118 13.119141 87.791016 C 13.027691 87.877916 12.983569 87.958238 12.951172 88.03125 C 12.886382 88.177277 12.867187 88.304789 12.867188 88.441406 L 12.867188 89.523438 L 12.867188 90.119141 L 12.867188 91.677734 L 12.867188 92.509766 L 13.570312 92.509766 L 19.472656 92.509766 L 20.173828 92.509766 L 20.173828 91.677734 L 20.173828 89.523438 L 20.173828 88.441406 C 20.173828 88.304794 20.156597 88.177281 20.091797 88.03125 C 20.059397 87.95824 20.015299 87.877916 19.923828 87.791016 C 19.832368 87.704116 19.667509 87.607422 19.472656 87.607422 L 18.927734 87.607422 L 18.927734 86.376953 C 18.927734 85.085184 17.867902 84.027344 16.576172 84.027344 L 16.435547 84.027344 z M 2.0507812 84.900391 C 1.8507824 84.970391 1.6907031 85.199453 1.7207031 85.439453 L 2.4199219 91.689453 C 2.4399219 92.049453 3 92.240929 3.25 91.960938 L 4.0507812 91.160156 C 4.0707812 91.160156 4.0898437 91.140156 4.0898438 91.160156 C 4.5498437 91.400156 5.4595313 91.330078 7.2695312 91.330078 L 11.869141 91.330078 L 11.869141 90.119141 L 11.869141 89.523438 L 11.869141 88.441406 C 11.869141 88.437991 11.871073 88.433136 11.871094 88.429688 L 7.2792969 88.429688 C 7.1292969 88.429688 6.9808594 88.400078 6.8808594 88.330078 L 8.8007812 86.400391 C 9.1007822 86.160391 8.8992969 85.600547 8.5292969 85.560547 L 2.25 84.910156 L 2.0507812 84.910156 L 2.0507812 84.900391 z M 16.435547 85.220703 L 16.576172 85.220703 C 17.22782 85.220703 17.734375 85.725101 17.734375 86.376953 L 17.734375 87.607422 L 15.277344 87.607422 L 15.277344 86.376953 C 15.277344 85.725101 15.7839 85.220703 16.435547 85.220703 z M 4.8808594 98.599609 C 3.5508594 98.599609 3.5400781 99.080402 3.5800781 100.90039 L 4.7207031 99.529297 C 4.8007031 99.429297 4.9405469 99.360078 5.0605469 99.330078 C 5.2205469 99.330078 5.4 99.409297 5.5 99.529297 L 7.1601562 101.56055 C 7.2001563 101.56055 7.2292969 101.5293 7.2792969 101.5293 L 14.720703 101.5293 C 15.060703 101.5293 15.289141 101.7293 15.369141 102.0293 L 12.939453 102.0293 C 12.599453 102.0793 12.410625 102.55055 12.640625 102.81055 L 13.470703 103.85742 C 14.029941 102.77899 15.146801 102.02734 16.435547 102.02734 L 16.578125 102.02734 C 18.158418 102.02734 19.491598 103.14879 19.835938 104.63086 L 21.279297 102.82031 C 21.499297 102.55031 21.260156 102.06078 20.910156 102.05078 L 18.400391 102.05078 C 18.420391 98.150792 19.000234 98.650391 14.740234 98.650391 L 7.2792969 98.650391 C 6.1992969 98.650391 5.4208594 98.609375 4.8808594 98.609375 L 4.8808594 98.599609 z M 5.0292969 101.06055 C 4.9292969 101.09055 4.83 101.15977 4.75 101.25977 L 0.81054688 106.16016 C 0.61054688 106.44016 0.8409375 106.92945 1.2109375 106.93945 L 3.5996094 106.93945 C 3.5796094 110.87945 3.1497656 110.33984 7.2597656 110.33984 L 11.869141 110.33984 L 11.869141 109.11914 L 11.869141 108.52344 L 11.869141 107.44141 L 11.869141 107.43945 L 7.2792969 107.43945 C 6.9292969 107.43945 6.7091406 107.23945 6.6191406 106.93945 L 9.0605469 106.93945 C 9.4305469 106.93945 9.6909375 106.44016 9.4609375 106.16016 L 5.5 101.25977 C 5.4 101.10977 5.1992969 101.03055 5.0292969 101.06055 z M 16.435547 103.02734 C 15.143818 103.02734 14.083984 104.08518 14.083984 105.37695 L 14.083984 106.60742 L 13.570312 106.60742 C 13.375448 106.60742 13.210603 106.70409 13.119141 106.79102 C 13.027691 106.87792 12.983569 106.95823 12.951172 107.03125 C 12.886382 107.17727 12.867187 107.30479 12.867188 107.44141 L 12.867188 108.52344 L 12.867188 109.11914 L 12.867188 110.67773 L 12.867188 111.50977 L 13.570312 111.50977 L 19.472656 111.50977 L 20.173828 111.50977 L 20.173828 110.67773 L 20.173828 108.52344 L 20.173828 107.44141 C 20.173828 107.3048 20.156597 107.17728 20.091797 107.03125 C 20.059397 106.95825 20.015299 106.87792 19.923828 106.79102 C 19.832368 106.70412 19.667509 106.60742 19.472656 106.60742 L 18.927734 106.60742 L 18.927734 105.37695 C 18.927734 104.08518 17.867902 103.02734 16.576172 103.02734 L 16.435547 103.02734 z M 16.435547 104.2207 L 16.576172 104.2207 C 17.22782 104.2207 17.734375 104.7251 17.734375 105.37695 L 17.734375 106.60742 L 15.277344 106.60742 L 15.277344 105.37695 C 15.277344 104.7251 15.7839 104.2207 16.435547 104.2207 z M 16.435547 105.2207 C 16.301234 105.2207 16.277344 105.24444 16.277344 105.37891 L 16.277344 105.60742 L 16.734375 105.60742 L 16.734375 105.37891 C 16.734375 105.24441 16.712442 105.2207 16.578125 105.2207 L 16.435547 105.2207 z M 4.8808594 117.58984 L 4.8808594 117.59961 C 3.7208594 117.59961 3.5800781 117.90016 3.5800781 119.16016 L 4.7207031 117.7793 C 4.8007031 117.6793 4.9405469 117.63914 5.0605469 117.61914 C 5.2205469 117.61914 5.4 117.6593 5.5 117.7793 L 7.7207031 120.5293 L 14.720703 120.5293 C 15.123595 120.5293 15.408576 120.79174 15.431641 121.20117 C 15.750992 121.09876 16.08404 121.02734 16.435547 121.02734 L 16.578125 121.02734 C 17.24903 121.02734 17.874081 121.23262 18.400391 121.57812 L 18.400391 121.25 C 18.400391 117.05 19.120234 117.61914 14.740234 117.61914 L 7.2792969 117.61914 C 6.1992969 117.61914 5.4208594 117.58984 4.8808594 117.58984 z M 4.9804688 119.33984 C 4.8804688 119.36984 4.81 119.44 4.75 119.5 L 0.80078125 124.43945 C 0.60078125 124.71945 0.8292182 125.2107 1.1992188 125.2207 L 3.5996094 125.2207 L 3.5996094 125.7207 C 3.5996094 129.9807 3.0497656 129.33984 7.2597656 129.33984 L 11.869141 129.33984 L 11.869141 128.11914 L 11.869141 127.52344 L 11.869141 126.44141 C 11.869141 126.43799 11.871073 126.43314 11.871094 126.42969 L 7.2792969 126.42969 C 6.8392969 126.42969 6.5605469 126.13094 6.5605469 125.71094 L 6.5605469 125.21094 L 9.0605469 125.21094 C 9.4305469 125.23094 9.6909375 124.70969 9.4609375 124.42969 L 5.5 119.5 C 5.3820133 119.35252 5.1682348 119.28513 4.9804688 119.33984 z M 12.839844 121.7793 C 12.539844 121.8793 12.410625 122.32055 12.640625 122.56055 L 13.267578 123.34375 C 13.473522 122.72168 13.852237 122.1828 14.353516 121.7793 L 12.839844 121.7793 z M 18.658203 121.7793 C 19.393958 122.37155 19.878978 123.25738 19.916016 124.25781 L 21.279297 122.56055 C 21.499297 122.28055 21.260156 121.7893 20.910156 121.7793 L 18.658203 121.7793 z M 16.435547 122.02734 C 15.143818 122.02734 14.083984 123.08518 14.083984 124.37695 L 14.083984 125.60742 L 13.570312 125.60742 C 13.375448 125.60742 13.210603 125.70409 13.119141 125.79102 C 13.027691 125.87792 12.983569 125.95823 12.951172 126.03125 C 12.886382 126.17727 12.867187 126.30479 12.867188 126.44141 L 12.867188 127.52344 L 12.867188 128.11914 L 12.867188 129.67773 L 12.867188 130.50977 L 13.570312 130.50977 L 19.472656 130.50977 L 20.173828 130.50977 L 20.173828 129.67773 L 20.173828 127.52344 L 20.173828 126.44141 C 20.173828 126.3048 20.156597 126.17728 20.091797 126.03125 C 20.059397 125.95825 20.015299 125.87792 19.923828 125.79102 C 19.832368 125.70412 19.667509 125.60742 19.472656 125.60742 L 18.927734 125.60742 L 18.927734 124.37695 C 18.927734 123.08518 17.867902 122.02734 16.576172 122.02734 L 16.435547 122.02734 z M 16.435547 123.2207 L 16.576172 123.2207 C 17.22782 123.2207 17.734375 123.7251 17.734375 124.37695 L 17.734375 125.60742 L 15.277344 125.60742 L 15.277344 124.37695 C 15.277344 123.7251 15.7839 123.2207 16.435547 123.2207 z M 16.435547 124.2207 C 16.301234 124.2207 16.277344 124.24444 16.277344 124.37891 L 16.277344 124.60742 L 16.734375 124.60742 L 16.734375 124.37891 C 16.734375 124.24441 16.712442 124.2207 16.578125 124.2207 L 16.435547 124.2207 z M 5.9394531 136.58984 L 5.9394531 136.59961 L 8.3105469 139.5293 L 14.730469 139.5293 C 15.131912 139.5293 15.414551 139.79039 15.439453 140.19727 C 15.756409 140.09653 16.087055 140.02734 16.435547 140.02734 L 16.578125 140.02734 C 17.24903 140.02734 17.874081 140.23261 18.400391 140.57812 L 18.400391 140.25 C 18.400391 136.05 19.120234 136.61914 14.740234 136.61914 L 7.2792969 136.61914 C 6.6792969 136.61914 6.3594531 136.59984 5.9394531 136.58984 z M 4.2207031 136.66016 C 3.8207031 136.74016 3.6791406 136.96016 3.6191406 137.41016 L 4.2207031 136.66992 L 4.2207031 136.66016 z M 5.0605469 137.57031 L 5.0605469 137.58984 C 4.9405469 137.58984 4.8197656 137.66953 4.7597656 137.76953 L 0.81054688 142.66992 C 0.57054688 142.96992 0.8109375 143.50023 1.2109375 143.49023 L 3.5996094 143.49023 L 3.5996094 144.71094 C 3.5996094 148.97094 3.0497656 148.33008 7.2597656 148.33008 L 11.869141 148.33008 L 11.869141 147.11914 L 11.869141 146.52344 L 11.869141 145.44141 C 11.869141 145.43799 11.871073 145.43314 11.871094 145.42969 L 7.2792969 145.42969 C 6.8392969 145.42969 6.5605469 145.13094 6.5605469 144.71094 L 6.5605469 143.49023 L 9.0605469 143.49023 C 9.4605469 143.53023 9.7309375 142.95945 9.4609375 142.68945 L 5.5 137.76953 C 5.4 137.63953 5.2305469 137.57031 5.0605469 137.57031 z M 16.435547 141.02734 C 15.143818 141.02734 14.083984 142.08518 14.083984 143.37695 L 14.083984 144.60742 L 13.570312 144.60742 C 13.375448 144.60742 13.210603 144.70409 13.119141 144.79102 C 13.027691 144.87792 12.983569 144.95823 12.951172 145.03125 C 12.886382 145.17727 12.867187 145.30479 12.867188 145.44141 L 12.867188 146.52344 L 12.867188 147.11914 L 12.867188 148.67773 L 12.867188 149.50977 L 13.570312 149.50977 L 19.472656 149.50977 L 20.173828 149.50977 L 20.173828 148.67773 L 20.173828 146.52344 L 20.173828 145.44141 C 20.173828 145.3048 20.156597 145.17728 20.091797 145.03125 C 20.059397 144.95825 20.015299 144.87792 19.923828 144.79102 C 19.832368 144.70412 19.667509 144.60742 19.472656 144.60742 L 18.927734 144.60742 L 18.927734 143.37695 C 18.927734 142.08518 17.867902 141.02734 16.576172 141.02734 L 16.435547 141.02734 z M 12.849609 141.5 C 12.549609 141.6 12.420391 142.0393 12.650391 142.2793 L 13.136719 142.88672 C 13.213026 142.38119 13.390056 141.90696 13.667969 141.5 L 12.849609 141.5 z M 19.34375 141.5 C 19.710704 142.03735 19.927734 142.68522 19.927734 143.37891 L 19.927734 143.79102 C 19.965561 143.80421 20.005506 143.81448 20.044922 143.82617 L 21.289062 142.2793 C 21.509062 141.9993 21.269922 141.51 20.919922 141.5 L 19.34375 141.5 z M 16.435547 142.2207 L 16.576172 142.2207 C 17.22782 142.2207 17.734375 142.7251 17.734375 143.37695 L 17.734375 144.60742 L 15.277344 144.60742 L 15.277344 143.37695 C 15.277344 142.7251 15.7839 142.2207 16.435547 142.2207 z M 16.435547 143.2207 C 16.301234 143.2207 16.277344 143.24444 16.277344 143.37891 L 16.277344 143.60742 L 16.734375 143.60742 L 16.734375 143.37891 C 16.734375 143.24441 16.712442 143.2207 16.578125 143.2207 L 16.435547 143.2207 z M 17.130859 155.59961 C 16.580859 155.57961 15.810469 155.63086 14.730469 155.63086 L 6.5292969 155.63086 L 8.9101562 158.5293 L 14.730469 158.5293 C 15.131912 158.5293 15.414551 158.79039 15.439453 159.19727 C 15.756409 159.09653 16.087055 159.02734 16.435547 159.02734 L 16.578125 159.02734 C 17.24903 159.02734 17.874081 159.23261 18.400391 159.57812 L 18.400391 159.25977 C 18.400391 156.10977 18.800391 155.63961 17.150391 155.59961 L 17.130859 155.59961 z M 5.0292969 155.86914 L 5.0292969 155.88086 C 4.9292969 155.90086 4.83 155.98055 4.75 156.06055 L 0.81054688 160.96094 C 0.61054688 161.26094 0.8409375 161.73977 1.2109375 161.75977 L 3.5996094 161.75977 L 3.5996094 163.7207 C 3.5996094 167.9807 3.0497656 167.33984 7.2597656 167.33984 L 11.869141 167.33984 L 11.869141 166.11914 L 11.869141 165.52344 L 11.869141 164.44141 L 11.869141 164.43945 L 7.2792969 164.43945 C 6.8392969 164.43945 6.5605469 164.1407 6.5605469 163.7207 L 6.5605469 161.75 L 9.0605469 161.75 C 9.4305469 161.77 9.6909375 161.2507 9.4609375 160.9707 L 5.5 156.07031 C 5.4 155.92031 5.1992969 155.84914 5.0292969 155.86914 z M 16.435547 160.02734 C 15.143818 160.02734 14.083984 161.08518 14.083984 162.37695 L 14.083984 163.60742 L 13.570312 163.60742 C 13.375448 163.60742 13.210603 163.70409 13.119141 163.79102 C 13.027691 163.87792 12.983569 163.95823 12.951172 164.03125 C 12.886382 164.17727 12.867187 164.30479 12.867188 164.44141 L 12.867188 165.52344 L 12.867188 166.11914 L 12.867188 167.67773 L 12.867188 168.50977 L 13.570312 168.50977 L 19.472656 168.50977 L 20.173828 168.50977 L 20.173828 167.67773 L 20.173828 165.52344 L 20.173828 164.44141 C 20.173828 164.3048 20.156597 164.17728 20.091797 164.03125 C 20.059397 163.95825 20.015299 163.87792 19.923828 163.79102 C 19.832368 163.70412 19.667509 163.60742 19.472656 163.60742 L 18.927734 163.60742 L 18.927734 162.37695 C 18.927734 161.08518 17.867902 160.02734 16.576172 160.02734 L 16.435547 160.02734 z M 12.900391 161.2207 C 12.580391 161.2807 12.419141 161.74 12.619141 162 L 13.085938 162.58594 L 13.085938 162.37891 C 13.085938 161.97087 13.170592 161.58376 13.306641 161.2207 L 12.900391 161.2207 z M 16.435547 161.2207 L 16.576172 161.2207 C 17.22782 161.2207 17.734375 161.7251 17.734375 162.37695 L 17.734375 163.60742 L 15.277344 163.60742 L 15.277344 162.37695 C 15.277344 161.7251 15.7839 161.2207 16.435547 161.2207 z M 19.708984 161.23047 C 19.842743 161.59081 19.927734 161.97449 19.927734 162.37891 L 19.927734 162.79102 C 20.119162 162.85779 20.322917 162.91147 20.484375 163 L 21.279297 162.00977 C 21.499297 161.72977 21.260156 161.24047 20.910156 161.23047 L 19.708984 161.23047 z M 16.435547 162.2207 C 16.301234 162.2207 16.277344 162.24444 16.277344 162.37891 L 16.277344 162.60742 L 16.734375 162.60742 L 16.734375 162.37891 C 16.734375 162.24441 16.712442 162.2207 16.578125 162.2207 L 16.435547 162.2207 z M 5.0996094 174.49023 L 5.1308594 174.5 C 4.9808594 174.5 4.83 174.56922 4.75 174.69922 L 0.80078125 179.59961 C 0.56078125 179.86961 0.7992182 180.42039 1.1992188 180.40039 L 3.5996094 180.40039 L 3.5996094 182.7207 C 3.5996094 186.9807 3.0497656 186.33984 7.2597656 186.33984 L 11.869141 186.33984 L 11.869141 185.11914 L 11.869141 184.52344 L 11.869141 183.44141 L 11.869141 183.43945 L 7.25 183.43945 C 6.82 183.43945 6.5507814 183.1407 6.5507812 182.7207 L 6.5507812 180.41992 L 9.0507812 180.41992 C 9.4307824 180.44992 9.7092187 179.87984 9.4492188 179.58984 L 5.4804688 174.68945 C 5.3804688 174.55945 5.2496094 174.49023 5.0996094 174.49023 z M 17.150391 174.58008 L 17.130859 174.59961 C 16.580859 174.57961 15.810469 174.63086 14.730469 174.63086 L 6.8300781 174.63086 L 9.1796875 177.5293 L 14.699219 177.5293 C 15.104107 177.5293 15.391475 177.79407 15.412109 178.20703 C 15.737096 178.1006 16.076913 178.02734 16.435547 178.02734 L 16.578125 178.02734 C 17.24903 178.02734 17.874081 178.2326 18.400391 178.57812 L 18.400391 178.24023 C 18.400391 175.09023 18.800391 174.62008 17.150391 174.58008 z M 16.435547 179.02734 C 15.143818 179.02734 14.083984 180.08518 14.083984 181.37695 L 14.083984 182.60742 L 13.570312 182.60742 C 13.375448 182.60742 13.210603 182.70409 13.119141 182.79102 C 13.027691 182.87792 12.983569 182.95823 12.951172 183.03125 C 12.886382 183.17727 12.867187 183.30479 12.867188 183.44141 L 12.867188 184.52344 L 12.867188 185.11914 L 12.867188 186.67773 L 12.867188 187.50977 L 13.570312 187.50977 L 19.472656 187.50977 L 20.173828 187.50977 L 20.173828 186.67773 L 20.173828 184.52344 L 20.173828 183.44141 C 20.173828 183.3048 20.156597 183.17728 20.091797 183.03125 C 20.059397 182.95825 20.015299 182.87792 19.923828 182.79102 C 19.832368 182.70412 19.667509 182.60742 19.472656 182.60742 L 18.927734 182.60742 L 18.927734 181.37695 C 18.927734 180.08518 17.867902 179.02734 16.576172 179.02734 L 16.435547 179.02734 z M 16.435547 180.2207 L 16.576172 180.2207 C 17.22782 180.2207 17.734375 180.7251 17.734375 181.37695 L 17.734375 182.60742 L 15.277344 182.60742 L 15.277344 181.37695 C 15.277344 180.7251 15.7839 180.2207 16.435547 180.2207 z M 19.816406 180.57031 C 19.882311 180.83091 19.927734 181.09907 19.927734 181.37891 L 19.927734 181.79102 C 20.168811 181.87511 20.455966 181.91694 20.613281 182.06641 C 20.630645 182.0829 20.639883 182.10199 20.65625 182.11914 L 21.259766 181.36914 C 21.479766 181.06914 21.240625 180.59031 20.890625 180.57031 L 19.816406 180.57031 z M 12.820312 180.58984 C 12.520316 180.68984 12.389141 181.11914 12.619141 181.36914 L 12.990234 181.83203 C 13.022029 181.82207 13.055579 181.81406 13.085938 181.80273 L 13.085938 181.37891 C 13.085938 181.10616 13.128698 180.84442 13.191406 180.58984 L 12.820312 180.58984 z M 16.435547 181.2207 C 16.301234 181.2207 16.277344 181.24444 16.277344 181.37891 L 16.277344 181.60742 L 16.734375 181.60742 L 16.734375 181.37891 C 16.734375 181.24441 16.712442 181.2207 16.578125 181.2207 L 16.435547 181.2207 z M 4.9609375 193.15039 L 4.9707031 193.16016 C 4.8707031 193.19016 4.8 193.25984 4.75 193.33984 L 0.81054688 198.24023 C 0.61054688 198.54023 0.8409375 199.01906 1.2109375 199.03906 L 3.5996094 199.03906 L 3.5996094 201.7207 C 3.5996094 205.9807 3.0497656 205.33984 7.2597656 205.33984 L 11.869141 205.33984 L 11.869141 204.11914 L 11.869141 203.52344 L 11.869141 202.44141 C 11.869141 202.44141 11.869141 202.43945 11.869141 202.43945 L 7.2695312 202.43945 C 6.8295312 202.43945 6.5507814 202.1407 6.5507812 201.7207 L 6.5507812 199.01953 L 9.0507812 199.01953 C 9.4207814 199.04953 9.6792188 198.54 9.4492188 198.25 L 5.4902344 193.34961 C 5.3702344 193.17961 5.1509375 193.10039 4.9609375 193.15039 z M 17.150391 193.58008 L 17.130859 193.58984 C 16.580859 193.56984 15.810469 193.61914 14.730469 193.61914 L 7.0996094 193.61914 L 9.4199219 196.46094 L 9.4492188 196.51953 L 14.699219 196.51953 C 15.106887 196.51953 15.397075 196.78718 15.414062 197.20508 C 15.738375 197.09913 16.077769 197.02734 16.435547 197.02734 L 16.578125 197.02734 C 17.24903 197.02734 17.874081 197.23259 18.400391 197.57812 L 18.400391 197.24023 C 18.400391 194.09023 18.800391 193.62008 17.150391 193.58008 z M 16.435547 198.02734 C 15.143818 198.02734 14.083984 199.08518 14.083984 200.37695 L 14.083984 201.60742 L 13.570312 201.60742 C 13.375448 201.60742 13.210603 201.70409 13.119141 201.79102 C 13.027691 201.87792 12.983569 201.95823 12.951172 202.03125 C 12.886382 202.17727 12.867187 202.30479 12.867188 202.44141 L 12.867188 203.52344 L 12.867188 204.11914 L 12.867188 205.67773 L 12.867188 206.50977 L 13.570312 206.50977 L 19.472656 206.50977 L 20.173828 206.50977 L 20.173828 205.67773 L 20.173828 203.52344 L 20.173828 202.44141 C 20.173828 202.3048 20.156597 202.17728 20.091797 202.03125 C 20.059397 201.95825 20.015299 201.87792 19.923828 201.79102 C 19.832368 201.70412 19.667509 201.60742 19.472656 201.60742 L 18.927734 201.60742 L 18.927734 200.37695 C 18.927734 199.08518 17.867902 198.02734 16.576172 198.02734 L 16.435547 198.02734 z M 16.435547 199.2207 L 16.576172 199.2207 C 17.22782 199.2207 17.734375 199.7251 17.734375 200.37695 L 17.734375 201.60742 L 15.277344 201.60742 L 15.277344 200.37695 C 15.277344 199.7251 15.7839 199.2207 16.435547 199.2207 z M 12.919922 199.93945 C 12.559922 199.95945 12.359141 200.48023 12.619141 200.74023 L 12.751953 200.9043 C 12.862211 200.87013 12.980058 200.84224 13.085938 200.80273 L 13.085938 200.37891 C 13.085938 200.22863 13.111295 200.08474 13.130859 199.93945 L 12.919922 199.93945 z M 19.882812 199.93945 C 19.902378 200.08474 19.927734 200.22863 19.927734 200.37891 L 19.927734 200.79102 C 20.168811 200.87511 20.455966 200.91694 20.613281 201.06641 C 20.691227 201.14046 20.749315 201.22305 20.806641 201.30273 L 21.259766 200.74023 C 21.519766 200.46023 21.260625 199.90945 20.890625 199.93945 L 19.882812 199.93945 z M 16.435547 200.2207 C 16.301234 200.2207 16.277344 200.24444 16.277344 200.37891 L 16.277344 200.60742 L 16.734375 200.60742 L 16.734375 200.37891 C 16.734375 200.24441 16.712442 200.2207 16.578125 200.2207 L 16.435547 200.2207 z ' fill='#{hex-color($highlight-text-color)}' stroke-width='0' /></svg>"); + } + + &:hover i.fa-retweet { + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='209' width='22'><path d='M 4.9707031 3.1503906 L 4.9707031 3.1601562 C 4.8707031 3.1901563 4.8 3.2598438 4.75 3.3398438 L 0.80078125 8.2402344 C 0.60078125 8.5402344 0.8292187 9.0190625 1.1992188 9.0390625 L 3.5996094 9.0390625 L 3.5996094 11.720703 C 3.5996094 15.980703 3.0497656 15.339844 7.2597656 15.339844 L 11.869141 15.339844 L 11.869141 14.119141 L 11.869141 13.523438 L 11.869141 12.441406 C 11.869141 12.441406 11.869141 12.439453 11.869141 12.439453 L 7.2695312 12.439453 C 6.8295312 12.439453 6.5507814 12.140703 6.5507812 11.720703 L 6.5507812 9.0195312 L 9.0507812 9.0195312 C 9.4207813 9.0495313 9.6792188 8.54 9.4492188 8.25 L 5.5 3.3496094 C 5.38 3.1796094 5.1607031 3.1003906 4.9707031 3.1503906 z M 17.150391 3.5800781 L 17.130859 3.5898438 C 16.580859 3.5698436 15.810469 3.609375 14.730469 3.609375 L 7.0996094 3.609375 L 9.4199219 6.4609375 L 9.4492188 6.5195312 L 14.699219 6.5195312 C 15.106887 6.5195312 15.397113 6.7872181 15.414062 7.2050781 C 15.738375 7.0991315 16.077769 7.0273437 16.435547 7.0273438 L 16.578125 7.0273438 C 17.24903 7.0273438 17.874081 7.2325787 18.400391 7.578125 L 18.400391 7.2402344 C 18.400391 4.0902344 18.800391 3.6200781 17.150391 3.5800781 z M 16.435547 8.0273438 C 15.143818 8.0273438 14.083984 9.0851838 14.083984 10.376953 L 14.083984 11.607422 L 13.570312 11.607422 C 13.375448 11.607422 13.210603 11.704118 13.119141 11.791016 C 13.027691 11.877916 12.983569 11.958238 12.951172 12.03125 C 12.886382 12.177277 12.867187 12.304789 12.867188 12.441406 L 12.867188 13.523438 L 12.867188 14.119141 L 12.867188 15.677734 L 12.867188 16.509766 L 13.570312 16.509766 L 19.472656 16.509766 L 20.173828 16.509766 L 20.173828 15.677734 L 20.173828 13.523438 L 20.173828 12.441406 C 20.173828 12.304794 20.156597 12.177281 20.091797 12.03125 C 20.059397 11.95824 20.015299 11.877916 19.923828 11.791016 C 19.832368 11.704116 19.667509 11.607422 19.472656 11.607422 L 18.927734 11.607422 L 18.927734 10.376953 C 18.927734 9.0851838 17.867902 8.0273438 16.576172 8.0273438 L 16.435547 8.0273438 z M 16.435547 9.2207031 L 16.576172 9.2207031 C 17.22782 9.2207031 17.734375 9.7251013 17.734375 10.376953 L 17.734375 11.607422 L 15.277344 11.607422 L 15.277344 10.376953 C 15.277344 9.7251013 15.7839 9.2207031 16.435547 9.2207031 z M 12.919922 9.9394531 C 12.559922 9.9594531 12.359141 10.480234 12.619141 10.740234 L 12.751953 10.904297 C 12.862211 10.870135 12.980058 10.842244 13.085938 10.802734 L 13.085938 10.378906 C 13.085938 10.228632 13.111295 10.084741 13.130859 9.9394531 L 12.919922 9.9394531 z M 19.882812 9.9394531 C 19.902378 10.084741 19.927734 10.228632 19.927734 10.378906 L 19.927734 10.791016 C 20.168811 10.875098 20.455966 10.916935 20.613281 11.066406 C 20.691227 11.140457 20.749315 11.223053 20.806641 11.302734 L 21.259766 10.740234 C 21.519766 10.460234 21.260625 9.9094531 20.890625 9.9394531 L 19.882812 9.9394531 z M 16.435547 10.220703 C 16.301234 10.220703 16.277344 10.244432 16.277344 10.378906 L 16.277344 10.607422 L 16.734375 10.607422 L 16.734375 10.378906 C 16.734375 10.244433 16.712442 10.220703 16.578125 10.220703 L 16.435547 10.220703 z ' fill='#{hex-color(lighten($action-button-color, 7%))}' stroke-width='0'/><path d='M 7.7792969 19.650391 L 7.7792969 19.660156 C 7.5392969 19.680156 7.3398437 19.910156 7.3398438 20.160156 L 7.3398438 22.619141 L 7.2792969 22.619141 C 6.1992969 22.619141 5.4208594 22.589844 4.8808594 22.589844 C 3.2408594 22.589844 3.6308594 23.020234 3.6308594 26.240234 L 3.6308594 30.710938 C 3.6308594 34.970937 3.0692969 34.330078 7.2792969 34.330078 L 8.5 34.330078 L 7.1992188 33.269531 C 7.0992188 33.189531 7.02 33.070703 7 32.970703 C 6.98 32.800703 7.0592186 32.619531 7.1992188 32.519531 L 8.5292969 31.419922 L 7.2792969 31.419922 C 6.8392969 31.419922 6.5605469 31.120703 6.5605469 30.720703 L 6.5605469 26.240234 C 6.5605469 25.800234 6.8392969 25.519531 7.2792969 25.519531 L 7.3398438 25.519531 L 7.3398438 28.019531 C 7.3398438 28.399531 7.8801564 28.650391 8.1601562 28.400391 L 13.060547 24.470703 C 13.310547 24.290703 13.310547 23.869453 13.060547 23.689453 L 8.1601562 19.769531 C 8.0601563 19.669531 7.9192969 19.630391 7.7792969 19.650391 z M 17.119141 22.580078 L 17.119141 22.589844 C 16.579141 22.569844 15.820703 22.609375 14.720703 22.609375 L 13.470703 22.609375 L 14.769531 23.679688 C 14.869531 23.749688 14.950703 23.879766 14.970703 24.009766 C 14.990703 24.169766 14.909531 24.310156 14.769531 24.410156 L 13.439453 25.509766 L 14.720703 25.509766 C 15.129702 25.509766 15.41841 25.778986 15.433594 26.199219 C 15.752266 26.097283 16.084896 26.027344 16.435547 26.027344 L 16.578125 26.027344 C 17.236645 26.027344 17.848901 26.228565 18.369141 26.5625 L 18.369141 26.240234 C 18.369141 23.090234 18.769141 22.620078 17.119141 22.580078 z M 16.435547 27.027344 C 15.143818 27.027344 14.083984 28.085184 14.083984 29.376953 L 14.083984 30.607422 L 13.570312 30.607422 C 13.375452 30.607422 13.210603 30.704118 13.119141 30.791016 C 13.027691 30.877916 12.983569 30.958238 12.951172 31.03125 C 12.886382 31.177277 12.867184 31.304789 12.867188 31.441406 L 12.867188 32.523438 L 12.867188 33.119141 L 12.867188 34.677734 L 12.867188 35.509766 L 13.570312 35.509766 L 19.472656 35.509766 L 20.173828 35.509766 L 20.173828 34.677734 L 20.173828 32.523438 L 20.173828 31.441406 C 20.173828 31.304794 20.156597 31.177281 20.091797 31.03125 C 20.059397 30.95824 20.015299 30.877916 19.923828 30.791016 C 19.832368 30.704116 19.667509 30.607422 19.472656 30.607422 L 18.927734 30.607422 L 18.927734 29.376953 C 18.927734 28.085184 17.867902 27.027344 16.576172 27.027344 L 16.435547 27.027344 z M 16.435547 28.220703 L 16.576172 28.220703 C 17.22782 28.220703 17.734375 28.725101 17.734375 29.376953 L 17.734375 30.607422 L 15.277344 30.607422 L 15.277344 29.376953 C 15.277344 28.725101 15.7839 28.220703 16.435547 28.220703 z M 13.109375 29.150391 L 8.9199219 32.509766 C 8.6599219 32.689766 8.6599219 33.109063 8.9199219 33.289062 L 11.869141 35.648438 L 11.869141 34.677734 L 11.869141 33.119141 L 11.869141 32.523438 L 11.869141 31.441406 C 11.869141 31.217489 11.912641 30.907486 12.037109 30.626953 C 12.093758 30.499284 12.228597 30.257492 12.429688 30.066406 C 12.580253 29.92335 12.859197 29.887344 13.085938 29.802734 L 13.085938 29.378906 C 13.085938 29.300761 13.104 29.227272 13.109375 29.150391 z M 16.435547 29.220703 C 16.301234 29.220703 16.277344 29.244432 16.277344 29.378906 L 16.277344 29.607422 L 16.734375 29.607422 L 16.734375 29.378906 C 16.734375 29.244433 16.712442 29.220703 16.578125 29.220703 L 16.435547 29.220703 z M 12.943359 36.509766 L 13.820312 37.210938 C 14.090314 37.460938 14.639141 37.210078 14.619141 36.830078 L 14.619141 36.509766 L 13.570312 36.509766 L 12.943359 36.509766 z M 10.330078 38.650391 L 10.339844 38.660156 C 10.099844 38.680156 9.9001562 38.910156 9.9101562 39.160156 L 9.9101562 41.630859 L 7.3007812 41.630859 C 6.2207812 41.630859 5.4403906 41.589844 4.9003906 41.589844 C 3.2603906 41.589844 3.6503906 42.020234 3.6503906 45.240234 L 3.6503906 49.710938 C 3.6503906 53.370936 3.4202344 53.409141 5.9902344 53.369141 L 4.6503906 52.269531 C 4.5503906 52.189531 4.4692187 52.070703 4.4492188 51.970703 C 4.4492188 51.800703 4.5203906 51.619531 4.6503906 51.519531 L 6.609375 49.919922 C 6.579375 49.859922 6.5703125 49.790703 6.5703125 49.720703 L 6.5703125 45.240234 C 6.5703125 44.800234 6.8490625 44.519531 7.2890625 44.519531 L 9.9003906 44.519531 L 9.9003906 47.019531 C 9.9003906 47.379531 10.399219 47.620391 10.699219 47.400391 L 15.630859 43.470703 C 15.870859 43.290703 15.870859 42.869453 15.630859 42.689453 L 10.689453 38.769531 C 10.589453 38.689531 10.460078 38.640391 10.330078 38.650391 z M 16.869141 41.585938 C 16.616211 41.581522 16.322969 41.584844 15.980469 41.589844 L 15.970703 41.589844 L 17.310547 42.689453 C 17.410547 42.759453 17.489766 42.889531 17.509766 43.019531 C 17.529766 43.179531 17.479609 43.319922 17.349609 43.419922 L 15.390625 45.019531 C 15.406724 45.075878 15.427133 45.132837 15.4375 45.197266 C 15.754974 45.096169 16.086404 45.027344 16.435547 45.027344 L 16.578125 45.027344 C 17.24129 45.027344 17.858323 45.230088 18.380859 45.568359 L 18.380859 45.25 C 18.380859 42.0475 18.639648 41.616836 16.869141 41.585938 z M 16.435547 46.027344 C 15.143818 46.027344 14.083984 47.085184 14.083984 48.376953 L 14.083984 49.607422 L 13.570312 49.607422 C 13.375448 49.607422 13.210603 49.704118 13.119141 49.791016 C 13.027691 49.877916 12.983569 49.958238 12.951172 50.03125 C 12.886382 50.177277 12.867187 50.304789 12.867188 50.441406 L 12.867188 51.523438 L 12.867188 52.119141 L 12.867188 53.677734 L 12.867188 54.509766 L 13.570312 54.509766 L 19.472656 54.509766 L 20.173828 54.509766 L 20.173828 53.677734 L 20.173828 51.523438 L 20.173828 50.441406 C 20.173828 50.304794 20.156597 50.177281 20.091797 50.03125 C 20.059397 49.95824 20.015299 49.877916 19.923828 49.791016 C 19.832368 49.704116 19.667509 49.607422 19.472656 49.607422 L 18.927734 49.607422 L 18.927734 48.376953 C 18.927734 47.085184 17.867902 46.027344 16.576172 46.027344 L 16.435547 46.027344 z M 16.435547 47.220703 L 16.576172 47.220703 C 17.22782 47.220703 17.734375 47.725101 17.734375 48.376953 L 17.734375 49.607422 L 15.277344 49.607422 L 15.277344 48.376953 C 15.277344 47.725101 15.7839 47.220703 16.435547 47.220703 z M 11.470703 47.490234 C 11.410703 47.510234 11.349063 47.539844 11.289062 47.589844 L 6.3496094 51.519531 C 6.1096094 51.699531 6.1096094 52.120781 6.3496094 52.300781 L 11.289062 56.220703 C 11.569064 56.440703 12.070312 56.199844 12.070312 55.839844 L 12.070312 55.509766 L 11.869141 55.509766 L 11.869141 53.677734 L 11.869141 52.119141 L 11.869141 51.523438 L 11.869141 50.441406 C 11.869141 50.217489 11.912641 49.907486 12.037109 49.626953 C 12.043809 49.611855 12.061451 49.584424 12.070312 49.566406 L 12.070312 47.960938 C 12.070312 47.660938 11.770703 47.430234 11.470703 47.490234 z M 16.435547 48.220703 C 16.301234 48.220703 16.277344 48.244432 16.277344 48.378906 L 16.277344 48.607422 L 16.734375 48.607422 L 16.734375 48.378906 C 16.734375 48.244433 16.712442 48.220703 16.578125 48.220703 L 16.435547 48.220703 z M 13.060547 57.650391 L 13.060547 57.660156 C 12.830547 57.690156 12.660156 57.920156 12.660156 58.160156 L 12.660156 60.630859 L 7.2792969 60.630859 C 6.1992969 60.630859 5.4208594 60.589844 4.8808594 60.589844 C 3.2408594 60.589844 3.6308594 61.020234 3.6308594 64.240234 L 3.6308594 69.109375 L 6.5605469 66.740234 L 6.5605469 64.240234 C 6.5605469 63.800234 6.8392969 63.519531 7.2792969 63.519531 L 12.660156 63.519531 L 12.660156 66.019531 C 12.660156 66.299799 12.960394 66.500006 13.226562 66.474609 C 13.625751 65.076914 14.904956 64.035678 16.421875 64.029297 L 18.380859 62.470703 C 18.620859 62.290703 18.620859 61.869453 18.380859 61.689453 L 13.439453 57.769531 C 13.339453 57.669531 13.200547 57.630391 13.060547 57.650391 z M 18.359375 63.810547 L 17.800781 64.269531 C 18.004793 64.350836 18.198411 64.450249 18.380859 64.568359 L 18.380859 64.25 L 18.380859 63.810547 L 18.359375 63.810547 z M 16.435547 65.027344 C 15.143818 65.027344 14.083984 66.085184 14.083984 67.376953 L 14.083984 68.607422 L 13.570312 68.607422 C 13.375448 68.607422 13.210603 68.704118 13.119141 68.791016 C 13.027691 68.877916 12.983569 68.958238 12.951172 69.03125 C 12.886382 69.177277 12.867187 69.304789 12.867188 69.441406 L 12.867188 70.523438 L 12.867188 71.119141 L 12.867188 72.677734 L 12.867188 73.509766 L 13.570312 73.509766 L 19.472656 73.509766 L 20.173828 73.509766 L 20.173828 72.677734 L 20.173828 70.523438 L 20.173828 69.441406 C 20.173828 69.304794 20.156597 69.177281 20.091797 69.03125 C 20.059397 68.95824 20.015299 68.877916 19.923828 68.791016 C 19.832368 68.704116 19.667509 68.607422 19.472656 68.607422 L 18.927734 68.607422 L 18.927734 67.376953 C 18.927734 66.085184 17.867902 65.027344 16.576172 65.027344 L 16.435547 65.027344 z M 16.435547 66.220703 L 16.576172 66.220703 C 17.22782 66.220703 17.734375 66.725101 17.734375 67.376953 L 17.734375 68.607422 L 15.277344 68.607422 L 15.277344 67.376953 C 15.277344 66.725101 15.7839 66.220703 16.435547 66.220703 z M 8.7207031 66.509766 C 8.6507031 66.529766 8.5895312 66.559375 8.5195312 66.609375 L 3.5996094 70.519531 C 3.3496094 70.699531 3.3496094 71.120781 3.5996094 71.300781 L 8.5292969 75.220703 C 8.8092969 75.440703 9.3105469 75.199844 9.3105469 74.839844 L 9.3105469 72.339844 L 11.869141 72.339844 L 11.869141 71.119141 L 11.869141 70.523438 L 11.869141 69.449219 L 9.3203125 69.449219 L 9.3203125 66.980469 C 9.3203125 66.680469 9.0007031 66.449766 8.7207031 66.509766 z M 16.435547 67.220703 C 16.301234 67.220703 16.277344 67.244432 16.277344 67.378906 L 16.277344 67.607422 L 16.734375 67.607422 L 16.734375 67.378906 C 16.734375 67.244433 16.712442 67.220703 16.578125 67.220703 L 16.435547 67.220703 z M 19.248047 78.800781 C 19.148558 78.831033 19.050295 78.90106 18.970703 78.970703 L 18.070312 79.869141 C 17.630312 79.569141 16.710703 79.619141 14.720703 79.619141 L 7.2792969 79.619141 C 6.1992969 79.619141 5.4208594 79.589844 4.8808594 79.589844 C 3.2408594 79.589844 3.6308594 80.020234 3.6308594 83.240234 L 3.6308594 83.939453 L 6.5605469 84.240234 L 6.5605469 83.240234 C 6.5605469 82.800234 6.8392969 82.519531 7.2792969 82.519531 L 14.720703 82.519531 C 14.920703 82.519531 15.090703 82.600703 15.220703 82.720703 L 13.419922 84.519531 C 13.279464 84.665607 13.281282 84.881022 13.363281 85.054688 C 13.880838 83.867655 15.067337 83.027344 16.435547 83.027344 L 16.578125 83.027344 C 18.290465 83.027344 19.703357 84.345788 19.890625 86.011719 L 19.960938 86.019531 C 20.240938 86.049531 20.520234 85.770234 20.490234 85.490234 L 19.789062 79.240234 C 19.789062 78.973661 19.498025 78.767523 19.25 78.800781 L 19.248047 78.800781 z M 16.435547 84.027344 C 15.143818 84.027344 14.083984 85.085184 14.083984 86.376953 L 14.083984 87.607422 L 13.570312 87.607422 C 13.375448 87.607422 13.210603 87.704118 13.119141 87.791016 C 13.027691 87.877916 12.983569 87.958238 12.951172 88.03125 C 12.886382 88.177277 12.867187 88.304789 12.867188 88.441406 L 12.867188 89.523438 L 12.867188 90.119141 L 12.867188 91.677734 L 12.867188 92.509766 L 13.570312 92.509766 L 19.472656 92.509766 L 20.173828 92.509766 L 20.173828 91.677734 L 20.173828 89.523438 L 20.173828 88.441406 C 20.173828 88.304794 20.156597 88.177281 20.091797 88.03125 C 20.059397 87.95824 20.015299 87.877916 19.923828 87.791016 C 19.832368 87.704116 19.667509 87.607422 19.472656 87.607422 L 18.927734 87.607422 L 18.927734 86.376953 C 18.927734 85.085184 17.867902 84.027344 16.576172 84.027344 L 16.435547 84.027344 z M 2.0507812 84.900391 C 1.8507824 84.970391 1.6907031 85.199453 1.7207031 85.439453 L 2.4199219 91.689453 C 2.4399219 92.049453 3 92.240929 3.25 91.960938 L 4.0507812 91.160156 C 4.0707812 91.160156 4.0898437 91.140156 4.0898438 91.160156 C 4.5498437 91.400156 5.4595313 91.330078 7.2695312 91.330078 L 11.869141 91.330078 L 11.869141 90.119141 L 11.869141 89.523438 L 11.869141 88.441406 C 11.869141 88.437991 11.871073 88.433136 11.871094 88.429688 L 7.2792969 88.429688 C 7.1292969 88.429688 6.9808594 88.400078 6.8808594 88.330078 L 8.8007812 86.400391 C 9.1007822 86.160391 8.8992969 85.600547 8.5292969 85.560547 L 2.25 84.910156 L 2.0507812 84.910156 L 2.0507812 84.900391 z M 16.435547 85.220703 L 16.576172 85.220703 C 17.22782 85.220703 17.734375 85.725101 17.734375 86.376953 L 17.734375 87.607422 L 15.277344 87.607422 L 15.277344 86.376953 C 15.277344 85.725101 15.7839 85.220703 16.435547 85.220703 z M 4.8808594 98.599609 C 3.5508594 98.599609 3.5400781 99.080402 3.5800781 100.90039 L 4.7207031 99.529297 C 4.8007031 99.429297 4.9405469 99.360078 5.0605469 99.330078 C 5.2205469 99.330078 5.4 99.409297 5.5 99.529297 L 7.1601562 101.56055 C 7.2001563 101.56055 7.2292969 101.5293 7.2792969 101.5293 L 14.720703 101.5293 C 15.060703 101.5293 15.289141 101.7293 15.369141 102.0293 L 12.939453 102.0293 C 12.599453 102.0793 12.410625 102.55055 12.640625 102.81055 L 13.470703 103.85742 C 14.029941 102.77899 15.146801 102.02734 16.435547 102.02734 L 16.578125 102.02734 C 18.158418 102.02734 19.491598 103.14879 19.835938 104.63086 L 21.279297 102.82031 C 21.499297 102.55031 21.260156 102.06078 20.910156 102.05078 L 18.400391 102.05078 C 18.420391 98.150792 19.000234 98.650391 14.740234 98.650391 L 7.2792969 98.650391 C 6.1992969 98.650391 5.4208594 98.609375 4.8808594 98.609375 L 4.8808594 98.599609 z M 5.0292969 101.06055 C 4.9292969 101.09055 4.83 101.15977 4.75 101.25977 L 0.81054688 106.16016 C 0.61054688 106.44016 0.8409375 106.92945 1.2109375 106.93945 L 3.5996094 106.93945 C 3.5796094 110.87945 3.1497656 110.33984 7.2597656 110.33984 L 11.869141 110.33984 L 11.869141 109.11914 L 11.869141 108.52344 L 11.869141 107.44141 L 11.869141 107.43945 L 7.2792969 107.43945 C 6.9292969 107.43945 6.7091406 107.23945 6.6191406 106.93945 L 9.0605469 106.93945 C 9.4305469 106.93945 9.6909375 106.44016 9.4609375 106.16016 L 5.5 101.25977 C 5.4 101.10977 5.1992969 101.03055 5.0292969 101.06055 z M 16.435547 103.02734 C 15.143818 103.02734 14.083984 104.08518 14.083984 105.37695 L 14.083984 106.60742 L 13.570312 106.60742 C 13.375448 106.60742 13.210603 106.70409 13.119141 106.79102 C 13.027691 106.87792 12.983569 106.95823 12.951172 107.03125 C 12.886382 107.17727 12.867187 107.30479 12.867188 107.44141 L 12.867188 108.52344 L 12.867188 109.11914 L 12.867188 110.67773 L 12.867188 111.50977 L 13.570312 111.50977 L 19.472656 111.50977 L 20.173828 111.50977 L 20.173828 110.67773 L 20.173828 108.52344 L 20.173828 107.44141 C 20.173828 107.3048 20.156597 107.17728 20.091797 107.03125 C 20.059397 106.95825 20.015299 106.87792 19.923828 106.79102 C 19.832368 106.70412 19.667509 106.60742 19.472656 106.60742 L 18.927734 106.60742 L 18.927734 105.37695 C 18.927734 104.08518 17.867902 103.02734 16.576172 103.02734 L 16.435547 103.02734 z M 16.435547 104.2207 L 16.576172 104.2207 C 17.22782 104.2207 17.734375 104.7251 17.734375 105.37695 L 17.734375 106.60742 L 15.277344 106.60742 L 15.277344 105.37695 C 15.277344 104.7251 15.7839 104.2207 16.435547 104.2207 z M 16.435547 105.2207 C 16.301234 105.2207 16.277344 105.24444 16.277344 105.37891 L 16.277344 105.60742 L 16.734375 105.60742 L 16.734375 105.37891 C 16.734375 105.24441 16.712442 105.2207 16.578125 105.2207 L 16.435547 105.2207 z M 4.8808594 117.58984 L 4.8808594 117.59961 C 3.7208594 117.59961 3.5800781 117.90016 3.5800781 119.16016 L 4.7207031 117.7793 C 4.8007031 117.6793 4.9405469 117.63914 5.0605469 117.61914 C 5.2205469 117.61914 5.4 117.6593 5.5 117.7793 L 7.7207031 120.5293 L 14.720703 120.5293 C 15.123595 120.5293 15.408576 120.79174 15.431641 121.20117 C 15.750992 121.09876 16.08404 121.02734 16.435547 121.02734 L 16.578125 121.02734 C 17.24903 121.02734 17.874081 121.23262 18.400391 121.57812 L 18.400391 121.25 C 18.400391 117.05 19.120234 117.61914 14.740234 117.61914 L 7.2792969 117.61914 C 6.1992969 117.61914 5.4208594 117.58984 4.8808594 117.58984 z M 4.9804688 119.33984 C 4.8804688 119.36984 4.81 119.44 4.75 119.5 L 0.80078125 124.43945 C 0.60078125 124.71945 0.8292182 125.2107 1.1992188 125.2207 L 3.5996094 125.2207 L 3.5996094 125.7207 C 3.5996094 129.9807 3.0497656 129.33984 7.2597656 129.33984 L 11.869141 129.33984 L 11.869141 128.11914 L 11.869141 127.52344 L 11.869141 126.44141 C 11.869141 126.43799 11.871073 126.43314 11.871094 126.42969 L 7.2792969 126.42969 C 6.8392969 126.42969 6.5605469 126.13094 6.5605469 125.71094 L 6.5605469 125.21094 L 9.0605469 125.21094 C 9.4305469 125.23094 9.6909375 124.70969 9.4609375 124.42969 L 5.5 119.5 C 5.3820133 119.35252 5.1682348 119.28513 4.9804688 119.33984 z M 12.839844 121.7793 C 12.539844 121.8793 12.410625 122.32055 12.640625 122.56055 L 13.267578 123.34375 C 13.473522 122.72168 13.852237 122.1828 14.353516 121.7793 L 12.839844 121.7793 z M 18.658203 121.7793 C 19.393958 122.37155 19.878978 123.25738 19.916016 124.25781 L 21.279297 122.56055 C 21.499297 122.28055 21.260156 121.7893 20.910156 121.7793 L 18.658203 121.7793 z M 16.435547 122.02734 C 15.143818 122.02734 14.083984 123.08518 14.083984 124.37695 L 14.083984 125.60742 L 13.570312 125.60742 C 13.375448 125.60742 13.210603 125.70409 13.119141 125.79102 C 13.027691 125.87792 12.983569 125.95823 12.951172 126.03125 C 12.886382 126.17727 12.867187 126.30479 12.867188 126.44141 L 12.867188 127.52344 L 12.867188 128.11914 L 12.867188 129.67773 L 12.867188 130.50977 L 13.570312 130.50977 L 19.472656 130.50977 L 20.173828 130.50977 L 20.173828 129.67773 L 20.173828 127.52344 L 20.173828 126.44141 C 20.173828 126.3048 20.156597 126.17728 20.091797 126.03125 C 20.059397 125.95825 20.015299 125.87792 19.923828 125.79102 C 19.832368 125.70412 19.667509 125.60742 19.472656 125.60742 L 18.927734 125.60742 L 18.927734 124.37695 C 18.927734 123.08518 17.867902 122.02734 16.576172 122.02734 L 16.435547 122.02734 z M 16.435547 123.2207 L 16.576172 123.2207 C 17.22782 123.2207 17.734375 123.7251 17.734375 124.37695 L 17.734375 125.60742 L 15.277344 125.60742 L 15.277344 124.37695 C 15.277344 123.7251 15.7839 123.2207 16.435547 123.2207 z M 16.435547 124.2207 C 16.301234 124.2207 16.277344 124.24444 16.277344 124.37891 L 16.277344 124.60742 L 16.734375 124.60742 L 16.734375 124.37891 C 16.734375 124.24441 16.712442 124.2207 16.578125 124.2207 L 16.435547 124.2207 z M 5.9394531 136.58984 L 5.9394531 136.59961 L 8.3105469 139.5293 L 14.730469 139.5293 C 15.131912 139.5293 15.414551 139.79039 15.439453 140.19727 C 15.756409 140.09653 16.087055 140.02734 16.435547 140.02734 L 16.578125 140.02734 C 17.24903 140.02734 17.874081 140.23261 18.400391 140.57812 L 18.400391 140.25 C 18.400391 136.05 19.120234 136.61914 14.740234 136.61914 L 7.2792969 136.61914 C 6.6792969 136.61914 6.3594531 136.59984 5.9394531 136.58984 z M 4.2207031 136.66016 C 3.8207031 136.74016 3.6791406 136.96016 3.6191406 137.41016 L 4.2207031 136.66992 L 4.2207031 136.66016 z M 5.0605469 137.57031 L 5.0605469 137.58984 C 4.9405469 137.58984 4.8197656 137.66953 4.7597656 137.76953 L 0.81054688 142.66992 C 0.57054688 142.96992 0.8109375 143.50023 1.2109375 143.49023 L 3.5996094 143.49023 L 3.5996094 144.71094 C 3.5996094 148.97094 3.0497656 148.33008 7.2597656 148.33008 L 11.869141 148.33008 L 11.869141 147.11914 L 11.869141 146.52344 L 11.869141 145.44141 C 11.869141 145.43799 11.871073 145.43314 11.871094 145.42969 L 7.2792969 145.42969 C 6.8392969 145.42969 6.5605469 145.13094 6.5605469 144.71094 L 6.5605469 143.49023 L 9.0605469 143.49023 C 9.4605469 143.53023 9.7309375 142.95945 9.4609375 142.68945 L 5.5 137.76953 C 5.4 137.63953 5.2305469 137.57031 5.0605469 137.57031 z M 16.435547 141.02734 C 15.143818 141.02734 14.083984 142.08518 14.083984 143.37695 L 14.083984 144.60742 L 13.570312 144.60742 C 13.375448 144.60742 13.210603 144.70409 13.119141 144.79102 C 13.027691 144.87792 12.983569 144.95823 12.951172 145.03125 C 12.886382 145.17727 12.867187 145.30479 12.867188 145.44141 L 12.867188 146.52344 L 12.867188 147.11914 L 12.867188 148.67773 L 12.867188 149.50977 L 13.570312 149.50977 L 19.472656 149.50977 L 20.173828 149.50977 L 20.173828 148.67773 L 20.173828 146.52344 L 20.173828 145.44141 C 20.173828 145.3048 20.156597 145.17728 20.091797 145.03125 C 20.059397 144.95825 20.015299 144.87792 19.923828 144.79102 C 19.832368 144.70412 19.667509 144.60742 19.472656 144.60742 L 18.927734 144.60742 L 18.927734 143.37695 C 18.927734 142.08518 17.867902 141.02734 16.576172 141.02734 L 16.435547 141.02734 z M 12.849609 141.5 C 12.549609 141.6 12.420391 142.0393 12.650391 142.2793 L 13.136719 142.88672 C 13.213026 142.38119 13.390056 141.90696 13.667969 141.5 L 12.849609 141.5 z M 19.34375 141.5 C 19.710704 142.03735 19.927734 142.68522 19.927734 143.37891 L 19.927734 143.79102 C 19.965561 143.80421 20.005506 143.81448 20.044922 143.82617 L 21.289062 142.2793 C 21.509062 141.9993 21.269922 141.51 20.919922 141.5 L 19.34375 141.5 z M 16.435547 142.2207 L 16.576172 142.2207 C 17.22782 142.2207 17.734375 142.7251 17.734375 143.37695 L 17.734375 144.60742 L 15.277344 144.60742 L 15.277344 143.37695 C 15.277344 142.7251 15.7839 142.2207 16.435547 142.2207 z M 16.435547 143.2207 C 16.301234 143.2207 16.277344 143.24444 16.277344 143.37891 L 16.277344 143.60742 L 16.734375 143.60742 L 16.734375 143.37891 C 16.734375 143.24441 16.712442 143.2207 16.578125 143.2207 L 16.435547 143.2207 z M 17.130859 155.59961 C 16.580859 155.57961 15.810469 155.63086 14.730469 155.63086 L 6.5292969 155.63086 L 8.9101562 158.5293 L 14.730469 158.5293 C 15.131912 158.5293 15.414551 158.79039 15.439453 159.19727 C 15.756409 159.09653 16.087055 159.02734 16.435547 159.02734 L 16.578125 159.02734 C 17.24903 159.02734 17.874081 159.23261 18.400391 159.57812 L 18.400391 159.25977 C 18.400391 156.10977 18.800391 155.63961 17.150391 155.59961 L 17.130859 155.59961 z M 5.0292969 155.86914 L 5.0292969 155.88086 C 4.9292969 155.90086 4.83 155.98055 4.75 156.06055 L 0.81054688 160.96094 C 0.61054688 161.26094 0.8409375 161.73977 1.2109375 161.75977 L 3.5996094 161.75977 L 3.5996094 163.7207 C 3.5996094 167.9807 3.0497656 167.33984 7.2597656 167.33984 L 11.869141 167.33984 L 11.869141 166.11914 L 11.869141 165.52344 L 11.869141 164.44141 L 11.869141 164.43945 L 7.2792969 164.43945 C 6.8392969 164.43945 6.5605469 164.1407 6.5605469 163.7207 L 6.5605469 161.75 L 9.0605469 161.75 C 9.4305469 161.77 9.6909375 161.2507 9.4609375 160.9707 L 5.5 156.07031 C 5.4 155.92031 5.1992969 155.84914 5.0292969 155.86914 z M 16.435547 160.02734 C 15.143818 160.02734 14.083984 161.08518 14.083984 162.37695 L 14.083984 163.60742 L 13.570312 163.60742 C 13.375448 163.60742 13.210603 163.70409 13.119141 163.79102 C 13.027691 163.87792 12.983569 163.95823 12.951172 164.03125 C 12.886382 164.17727 12.867187 164.30479 12.867188 164.44141 L 12.867188 165.52344 L 12.867188 166.11914 L 12.867188 167.67773 L 12.867188 168.50977 L 13.570312 168.50977 L 19.472656 168.50977 L 20.173828 168.50977 L 20.173828 167.67773 L 20.173828 165.52344 L 20.173828 164.44141 C 20.173828 164.3048 20.156597 164.17728 20.091797 164.03125 C 20.059397 163.95825 20.015299 163.87792 19.923828 163.79102 C 19.832368 163.70412 19.667509 163.60742 19.472656 163.60742 L 18.927734 163.60742 L 18.927734 162.37695 C 18.927734 161.08518 17.867902 160.02734 16.576172 160.02734 L 16.435547 160.02734 z M 12.900391 161.2207 C 12.580391 161.2807 12.419141 161.74 12.619141 162 L 13.085938 162.58594 L 13.085938 162.37891 C 13.085938 161.97087 13.170592 161.58376 13.306641 161.2207 L 12.900391 161.2207 z M 16.435547 161.2207 L 16.576172 161.2207 C 17.22782 161.2207 17.734375 161.7251 17.734375 162.37695 L 17.734375 163.60742 L 15.277344 163.60742 L 15.277344 162.37695 C 15.277344 161.7251 15.7839 161.2207 16.435547 161.2207 z M 19.708984 161.23047 C 19.842743 161.59081 19.927734 161.97449 19.927734 162.37891 L 19.927734 162.79102 C 20.119162 162.85779 20.322917 162.91147 20.484375 163 L 21.279297 162.00977 C 21.499297 161.72977 21.260156 161.24047 20.910156 161.23047 L 19.708984 161.23047 z M 16.435547 162.2207 C 16.301234 162.2207 16.277344 162.24444 16.277344 162.37891 L 16.277344 162.60742 L 16.734375 162.60742 L 16.734375 162.37891 C 16.734375 162.24441 16.712442 162.2207 16.578125 162.2207 L 16.435547 162.2207 z M 5.0996094 174.49023 L 5.1308594 174.5 C 4.9808594 174.5 4.83 174.56922 4.75 174.69922 L 0.80078125 179.59961 C 0.56078125 179.86961 0.7992182 180.42039 1.1992188 180.40039 L 3.5996094 180.40039 L 3.5996094 182.7207 C 3.5996094 186.9807 3.0497656 186.33984 7.2597656 186.33984 L 11.869141 186.33984 L 11.869141 185.11914 L 11.869141 184.52344 L 11.869141 183.44141 L 11.869141 183.43945 L 7.25 183.43945 C 6.82 183.43945 6.5507814 183.1407 6.5507812 182.7207 L 6.5507812 180.41992 L 9.0507812 180.41992 C 9.4307824 180.44992 9.7092187 179.87984 9.4492188 179.58984 L 5.4804688 174.68945 C 5.3804688 174.55945 5.2496094 174.49023 5.0996094 174.49023 z M 17.150391 174.58008 L 17.130859 174.59961 C 16.580859 174.57961 15.810469 174.63086 14.730469 174.63086 L 6.8300781 174.63086 L 9.1796875 177.5293 L 14.699219 177.5293 C 15.104107 177.5293 15.391475 177.79407 15.412109 178.20703 C 15.737096 178.1006 16.076913 178.02734 16.435547 178.02734 L 16.578125 178.02734 C 17.24903 178.02734 17.874081 178.2326 18.400391 178.57812 L 18.400391 178.24023 C 18.400391 175.09023 18.800391 174.62008 17.150391 174.58008 z M 16.435547 179.02734 C 15.143818 179.02734 14.083984 180.08518 14.083984 181.37695 L 14.083984 182.60742 L 13.570312 182.60742 C 13.375448 182.60742 13.210603 182.70409 13.119141 182.79102 C 13.027691 182.87792 12.983569 182.95823 12.951172 183.03125 C 12.886382 183.17727 12.867187 183.30479 12.867188 183.44141 L 12.867188 184.52344 L 12.867188 185.11914 L 12.867188 186.67773 L 12.867188 187.50977 L 13.570312 187.50977 L 19.472656 187.50977 L 20.173828 187.50977 L 20.173828 186.67773 L 20.173828 184.52344 L 20.173828 183.44141 C 20.173828 183.3048 20.156597 183.17728 20.091797 183.03125 C 20.059397 182.95825 20.015299 182.87792 19.923828 182.79102 C 19.832368 182.70412 19.667509 182.60742 19.472656 182.60742 L 18.927734 182.60742 L 18.927734 181.37695 C 18.927734 180.08518 17.867902 179.02734 16.576172 179.02734 L 16.435547 179.02734 z M 16.435547 180.2207 L 16.576172 180.2207 C 17.22782 180.2207 17.734375 180.7251 17.734375 181.37695 L 17.734375 182.60742 L 15.277344 182.60742 L 15.277344 181.37695 C 15.277344 180.7251 15.7839 180.2207 16.435547 180.2207 z M 19.816406 180.57031 C 19.882311 180.83091 19.927734 181.09907 19.927734 181.37891 L 19.927734 181.79102 C 20.168811 181.87511 20.455966 181.91694 20.613281 182.06641 C 20.630645 182.0829 20.639883 182.10199 20.65625 182.11914 L 21.259766 181.36914 C 21.479766 181.06914 21.240625 180.59031 20.890625 180.57031 L 19.816406 180.57031 z M 12.820312 180.58984 C 12.520316 180.68984 12.389141 181.11914 12.619141 181.36914 L 12.990234 181.83203 C 13.022029 181.82207 13.055579 181.81406 13.085938 181.80273 L 13.085938 181.37891 C 13.085938 181.10616 13.128698 180.84442 13.191406 180.58984 L 12.820312 180.58984 z M 16.435547 181.2207 C 16.301234 181.2207 16.277344 181.24444 16.277344 181.37891 L 16.277344 181.60742 L 16.734375 181.60742 L 16.734375 181.37891 C 16.734375 181.24441 16.712442 181.2207 16.578125 181.2207 L 16.435547 181.2207 z M 4.9609375 193.15039 L 4.9707031 193.16016 C 4.8707031 193.19016 4.8 193.25984 4.75 193.33984 L 0.81054688 198.24023 C 0.61054688 198.54023 0.8409375 199.01906 1.2109375 199.03906 L 3.5996094 199.03906 L 3.5996094 201.7207 C 3.5996094 205.9807 3.0497656 205.33984 7.2597656 205.33984 L 11.869141 205.33984 L 11.869141 204.11914 L 11.869141 203.52344 L 11.869141 202.44141 C 11.869141 202.44141 11.869141 202.43945 11.869141 202.43945 L 7.2695312 202.43945 C 6.8295312 202.43945 6.5507814 202.1407 6.5507812 201.7207 L 6.5507812 199.01953 L 9.0507812 199.01953 C 9.4207814 199.04953 9.6792188 198.54 9.4492188 198.25 L 5.4902344 193.34961 C 5.3702344 193.17961 5.1509375 193.10039 4.9609375 193.15039 z M 17.150391 193.58008 L 17.130859 193.58984 C 16.580859 193.56984 15.810469 193.61914 14.730469 193.61914 L 7.0996094 193.61914 L 9.4199219 196.46094 L 9.4492188 196.51953 L 14.699219 196.51953 C 15.106887 196.51953 15.397075 196.78718 15.414062 197.20508 C 15.738375 197.09913 16.077769 197.02734 16.435547 197.02734 L 16.578125 197.02734 C 17.24903 197.02734 17.874081 197.23259 18.400391 197.57812 L 18.400391 197.24023 C 18.400391 194.09023 18.800391 193.62008 17.150391 193.58008 z M 16.435547 198.02734 C 15.143818 198.02734 14.083984 199.08518 14.083984 200.37695 L 14.083984 201.60742 L 13.570312 201.60742 C 13.375448 201.60742 13.210603 201.70409 13.119141 201.79102 C 13.027691 201.87792 12.983569 201.95823 12.951172 202.03125 C 12.886382 202.17727 12.867187 202.30479 12.867188 202.44141 L 12.867188 203.52344 L 12.867188 204.11914 L 12.867188 205.67773 L 12.867188 206.50977 L 13.570312 206.50977 L 19.472656 206.50977 L 20.173828 206.50977 L 20.173828 205.67773 L 20.173828 203.52344 L 20.173828 202.44141 C 20.173828 202.3048 20.156597 202.17728 20.091797 202.03125 C 20.059397 201.95825 20.015299 201.87792 19.923828 201.79102 C 19.832368 201.70412 19.667509 201.60742 19.472656 201.60742 L 18.927734 201.60742 L 18.927734 200.37695 C 18.927734 199.08518 17.867902 198.02734 16.576172 198.02734 L 16.435547 198.02734 z M 16.435547 199.2207 L 16.576172 199.2207 C 17.22782 199.2207 17.734375 199.7251 17.734375 200.37695 L 17.734375 201.60742 L 15.277344 201.60742 L 15.277344 200.37695 C 15.277344 199.7251 15.7839 199.2207 16.435547 199.2207 z M 12.919922 199.93945 C 12.559922 199.95945 12.359141 200.48023 12.619141 200.74023 L 12.751953 200.9043 C 12.862211 200.87013 12.980058 200.84224 13.085938 200.80273 L 13.085938 200.37891 C 13.085938 200.22863 13.111295 200.08474 13.130859 199.93945 L 12.919922 199.93945 z M 19.882812 199.93945 C 19.902378 200.08474 19.927734 200.22863 19.927734 200.37891 L 19.927734 200.79102 C 20.168811 200.87511 20.455966 200.91694 20.613281 201.06641 C 20.691227 201.14046 20.749315 201.22305 20.806641 201.30273 L 21.259766 200.74023 C 21.519766 200.46023 21.260625 199.90945 20.890625 199.93945 L 19.882812 199.93945 z M 16.435547 200.2207 C 16.301234 200.2207 16.277344 200.24444 16.277344 200.37891 L 16.277344 200.60742 L 16.734375 200.60742 L 16.734375 200.37891 C 16.734375 200.24441 16.712442 200.2207 16.578125 200.2207 L 16.435547 200.2207 z ' fill='#{hex-color($highlight-text-color)}' stroke-width='0' /></svg>"); + } + } + + &.disabled { + i.fa-retweet, + &:hover i.fa-retweet { + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' height='209' width='22'><path d='M 18.972656 1.2011719 C 18.829825 1.1881782 18.685932 1.2302188 18.572266 1.3300781 L 15.990234 3.5996094 C 15.58109 3.6070661 15.297269 3.609375 14.730469 3.609375 L 7.0996094 3.609375 L 9.4199219 6.4609375 L 9.4492188 6.5195312 L 12.664062 6.5195312 L 6.5761719 11.867188 C 6.5674697 11.818249 6.5507813 11.773891 6.5507812 11.720703 L 6.5507812 9.0195312 L 9.0507812 9.0195312 C 9.4207813 9.0495313 9.6792188 8.54 9.4492188 8.25 L 5.5 3.3496094 C 5.38 3.1796094 5.1607031 3.1003906 4.9707031 3.1503906 L 4.9707031 3.1601562 C 4.8707031 3.1901563 4.8 3.2598438 4.75 3.3398438 L 0.80078125 8.2402344 C 0.60078125 8.5402344 0.8292187 9.0190625 1.1992188 9.0390625 L 3.5996094 9.0390625 L 3.5996094 11.720703 C 3.5996094 13.045739 3.5690668 13.895038 3.6503906 14.4375 L 2.6152344 15.347656 C 2.3879011 15.547375 2.3754917 15.901081 2.5859375 16.140625 L 3.1464844 16.78125 C 3.3569308 17.020794 3.7101667 17.053234 3.9375 16.853516 L 19.892578 2.8359375 C 20.119911 2.6362188 20.134275 2.282513 19.923828 2.0429688 L 19.361328 1.4023438 C 19.256105 1.282572 19.115488 1.2141655 18.972656 1.2011719 z M 18.410156 6.7753906 L 15.419922 9.4042969 L 15.419922 9.9394531 L 14.810547 9.9394531 L 13.148438 11.400391 L 16.539062 15.640625 C 16.719062 15.890625 17.140313 15.890625 17.320312 15.640625 L 21.259766 10.740234 C 21.519766 10.460234 21.260625 9.9094531 20.890625 9.9394531 L 18.400391 9.9394531 L 18.400391 7.2402344 C 18.400391 7.0470074 18.407711 6.9489682 18.410156 6.7753906 z M 11.966797 12.439453 L 8.6679688 15.339844 L 14.919922 15.339844 L 12.619141 12.5 C 12.589141 12.48 12.590313 12.459453 12.570312 12.439453 L 11.966797 12.439453 z' fill='#{hex-color(darken($action-button-color, 13%))}' stroke-width='0'/></svg>"); + } + } + + .media-modal__overlay .picture-in-picture__footer & { + i.fa-retweet { + background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='209'><path d='M4.97 3.16c-.1.03-.17.1-.22.18L.8 8.24c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77L5.5 3.35c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.02-2.4.02H7.1l2.32 2.85.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($white)}' stroke-width='0'/><path d='M7.78 19.66c-.24.02-.44.25-.44.5v2.46h-.06c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v4.47c0 4.26-.56 3.62 3.65 3.62H8.5l-1.3-1.06c-.1-.08-.18-.2-.2-.3-.02-.17.06-.35.2-.45l1.33-1.1H7.28c-.44 0-.72-.3-.72-.7v-4.48c0-.44.28-.72.72-.72h.06v2.5c0 .38.54.63.82.38l4.9-3.93c.25-.18.25-.6 0-.78l-4.9-3.92c-.1-.1-.24-.14-.38-.12zm9.34 2.93c-.54-.02-1.3.02-2.4.02h-1.25l1.3 1.07c.1.07.18.2.2.33.02.16-.06.3-.2.4l-1.33 1.1h1.28c.42 0 .72.28.72.72v4.47c0 .42-.3.72-.72.72h-.1v-2.47c0-.3-.3-.53-.6-.47-.07 0-.14.05-.2.1l-4.9 3.93c-.26.18-.26.6 0 .78l4.9 3.92c.27.25.82 0 .8-.38v-2.5h.1c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.15.4-3.62-1.25-3.66zM10.34 38.66c-.24.02-.44.25-.43.5v2.47H7.3c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.47c0 3.66-.23 3.7 2.34 3.66l-1.34-1.1c-.1-.08-.18-.2-.2-.3 0-.17.07-.35.2-.45l1.96-1.6c-.03-.06-.04-.13-.04-.2v-4.48c0-.44.28-.72.72-.72H9.9v2.5c0 .36.5.6.8.38l4.93-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.08-.23-.13-.36-.12zm5.63 2.93l1.34 1.1c.1.07.18.2.2.33.02.16-.03.3-.16.4l-1.96 1.6c.02.07.06.13.06.22v4.47c0 .42-.3.72-.72.72h-2.66v-2.47c0-.3-.3-.53-.6-.47-.06.02-.12.05-.18.1l-4.94 3.93c-.24.18-.24.6 0 .78l4.94 3.92c.28.22.78-.02.78-.38v-2.5h2.66c4.27 0 3.65.67 3.65-3.62v-4.47c0-3.66.34-3.7-2.4-3.66zM13.06 57.66c-.23.03-.4.26-.4.5v2.47H7.28c-1.08 0-1.86-.04-2.4-.04-1.64 0-1.25.43-1.25 3.65v4.87l2.93-2.37v-2.5c0-.44.28-.72.72-.72h5.38v2.5c0 .36.5.6.78.38l4.94-3.93c.24-.18.24-.6 0-.78l-4.94-3.92c-.1-.1-.24-.14-.38-.12zm5.3 6.15l-2.92 2.4v2.52c0 .42-.3.72-.72.72h-5.4v-2.47c0-.3-.32-.53-.6-.47-.07.02-.13.05-.2.1L3.6 70.52c-.25.18-.25.6 0 .78l4.93 3.92c.28.22.78-.02.78-.38v-2.5h5.42c4.27 0 3.65.67 3.65-3.62v-4.47-.44zM19.25 78.8c-.1.03-.2.1-.28.17l-.9.9c-.44-.3-1.36-.25-3.35-.25H7.28c-1.08 0-1.86-.03-2.4-.03-1.64 0-1.25.43-1.25 3.65v.7l2.93.3v-1c0-.44.28-.72.72-.72h7.44c.2 0 .37.08.5.2l-1.8 1.8c-.25.26-.08.76.27.8l6.27.7c.28.03.56-.25.53-.53l-.7-6.25c0-.27-.3-.48-.55-.44zm-17.2 6.1c-.2.07-.36.3-.33.54l.7 6.25c.02.36.58.55.83.27l.8-.8c.02 0 .04-.02.04 0 .46.24 1.37.17 3.18.17h7.44c4.27 0 3.65.67 3.65-3.62v-.75l-2.93-.3v1.05c0 .42-.3.72-.72.72H7.28c-.15 0-.3-.03-.4-.1L8.8 86.4c.3-.24.1-.8-.27-.84l-6.28-.65h-.2zM4.88 98.6c-1.33 0-1.34.48-1.3 2.3l1.14-1.37c.08-.1.22-.17.34-.2.16 0 .34.08.44.2l1.66 2.03c.04 0 .07-.03.12-.03h7.44c.34 0 .57.2.65.5h-2.43c-.34.05-.53.52-.3.78l3.92 4.95c.18.24.6.24.78 0l3.94-4.94c.22-.27-.02-.76-.37-.77H18.4c.02-3.9.6-3.4-3.66-3.4H7.28c-1.08 0-1.86-.04-2.4-.04zm.15 2.46c-.1.03-.2.1-.28.2l-3.94 4.9c-.2.28.03.77.4.78H3.6c-.02 3.94-.45 3.4 3.66 3.4h7.44c3.65 0 3.74.3 3.7-2.25l-1.1 1.34c-.1.1-.2.17-.32.2-.16 0-.34-.08-.44-.2l-1.65-2.03c-.06.02-.1.04-.18.04H7.28c-.35 0-.57-.2-.66-.5h2.44c.37 0 .63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.23-.47-.2zM4.88 117.6c-1.16 0-1.3.3-1.3 1.56l1.14-1.38c.08-.1.22-.14.34-.16.16 0 .34.04.44.16l2.22 2.75h7c.42 0 .72.28.72.72v.53h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-.53c0-4.2.72-3.63-3.66-3.63H7.28c-1.08 0-1.86-.03-2.4-.03zm.1 1.74c-.1.03-.17.1-.23.16L.8 124.44c-.2.28.03.77.4.78H3.6v.5c0 4.26-.55 3.62 3.66 3.62h7.44c1.03 0 1.74.02 2.28 0-.16.02-.34-.03-.44-.15l-2.22-2.76H7.28c-.44 0-.72-.3-.72-.72v-.5h2.5c.37.02.63-.5.4-.78L5.5 119.5c-.12-.15-.34-.22-.53-.16zm12.02 10c1.2-.02 1.4-.25 1.4-1.53l-1.1 1.36c-.07.1-.17.17-.3.18zM5.94 136.6l2.37 2.93h6.42c.42 0 .72.28.72.72v1.25h-2.6c-.3.1-.43.54-.2.78l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.25c0-4.2.72-3.63-3.66-3.63H7.28c-.6 0-.92-.02-1.34-.03zm-1.72.06c-.4.08-.54.3-.6.75l.6-.74zm.84.93c-.12 0-.24.08-.3.18l-3.95 4.9c-.24.3 0 .83.4.82H3.6v1.22c0 4.26-.55 3.62 3.66 3.62h7.44c.63 0 .97.02 1.4.03l-2.37-2.93H7.28c-.44 0-.72-.3-.72-.72v-1.22h2.5c.4.04.67-.53.4-.8l-3.96-4.92c-.1-.13-.27-.2-.44-.2zm13.28 10.03l-.56.7c.36-.07.5-.3.56-.7zM17.13 155.6c-.55-.02-1.32.03-2.4.03h-8.2l2.38 2.9h5.82c.42 0 .72.28.72.72v1.97H12.9c-.32.06-.48.52-.28.78l3.94 4.94c.2.23.6.22.78-.03l3.94-4.9c.22-.28-.02-.77-.37-.78H18.4v-1.97c0-3.15.4-3.62-1.25-3.66zm-12.1.28c-.1.02-.2.1-.28.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v1.96c0 4.26-.55 3.62 3.66 3.62h8.24l-2.36-2.9H7.28c-.44 0-.72-.3-.72-.72v-1.97h2.5c.37.02.63-.5.4-.78l-3.96-4.9c-.1-.15-.3-.22-.47-.2zM5.13 174.5c-.15 0-.3.07-.38.2L.8 179.6c-.24.27 0 .82.4.8H3.6v2.32c0 4.26-.55 3.62 3.66 3.62h7.94l-2.35-2.9h-5.6c-.43 0-.7-.3-.7-.72v-2.3h2.5c.38.03.66-.54.4-.83l-3.97-4.9c-.1-.13-.23-.2-.38-.2zm12 .1c-.55-.02-1.32.03-2.4.03H6.83l2.35 2.9h5.52c.42 0 .72.28.72.72v2.34h-2.6c-.3.1-.43.53-.2.78l3.92 4.9c.18.24.6.24.78 0l3.94-4.9c.22-.3-.02-.78-.37-.8H18.4v-2.33c0-3.15.4-3.62-1.25-3.66zM4.97 193.16c-.1.03-.17.1-.22.18l-3.94 4.9c-.2.3.03.78.4.8H3.6v2.68c0 4.26-.55 3.62 3.66 3.62h7.66l-2.3-2.84c-.03-.02-.03-.04-.05-.06H7.27c-.44 0-.72-.3-.72-.72v-2.7h2.5c.37.03.63-.48.4-.77l-3.96-4.9c-.12-.17-.34-.25-.53-.2zm12.16.43c-.55-.02-1.32.03-2.4.03H7.1l2.32 2.84.03.06h5.25c.42 0 .72.28.72.72v2.7h-2.5c-.36.02-.56.54-.3.8l3.92 4.9c.18.25.6.25.78 0l3.94-4.9c.26-.28 0-.83-.37-.8H18.4v-2.7c0-3.15.4-3.62-1.25-3.66z' fill='#{hex-color($highlight-text-color)}' stroke-width='0'/></svg>"); + } + } } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 17206977026684fe1cc92fc590354eb663584cb8..d6385f161cc8fd283c914b2280c40e63e0ea17c8 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -154,6 +154,11 @@ display: block; width: 100%; } + + .layout-multiple-columns &.button--with-bell { + font-size: 12px; + padding: 0 8px; + } } .column__wrapper { @@ -172,6 +177,7 @@ cursor: pointer; transition: all 100ms ease-in; transition-property: background-color, color; + text-decoration: none; &:hover, &:active, @@ -245,6 +251,20 @@ background: rgba($base-overlay-background, 0.9); } } + + &--with-counter { + display: inline-flex; + align-items: center; + width: auto !important; + } + + &__counter { + display: inline-block; + width: 14px; + margin-left: 4px; + font-size: 12px; + font-weight: 500; + } } .text-icon-button { @@ -779,6 +799,10 @@ cursor: pointer; } +.status__content { + clear: both; +} + .status__content, .reply-indicator__content { position: relative; @@ -812,6 +836,7 @@ p { margin-bottom: 20px; white-space: pre-wrap; + unicode-bidi: plaintext; &:last-child { margin-bottom: 0; @@ -821,6 +846,7 @@ a { color: $secondary-text-color; text-decoration: none; + unicode-bidi: isolate; &:hover { text-decoration: underline; @@ -980,14 +1006,6 @@ outline: 0; background: lighten($ui-base-color, 4%); - .status.status-direct { - background: lighten($ui-base-color, 12%); - - &.muted { - background: transparent; - } - } - .detailed-status, .detailed-status__action-bar { background: lighten($ui-base-color, 8%); @@ -1022,11 +1040,6 @@ margin-top: 8px; } - &.status-direct:not(.read) { - background: lighten($ui-base-color, 8%); - border-bottom-color: lighten($ui-base-color, 12%); - } - &.light { .status__relative-time, .status__visibility-icon { @@ -1064,27 +1077,16 @@ } } -.notification-favourite { - .status.status-direct { - background: transparent; - - .icon-button.disabled { - color: lighten($action-button-color, 13%); - } - } -} - .status__relative-time, -.status__visibility-icon, .notification__relative_time { color: $dark-text-color; float: right; font-size: 14px; + padding-bottom: 1px; } .status__visibility-icon { - margin-left: 4px; - margin-right: 4px; + padding: 0 4px; } .status__display-name { @@ -1162,28 +1164,14 @@ align-items: center; display: flex; margin-top: 8px; - - &__counter { - display: inline-flex; - margin-right: 11px; - align-items: center; - - .status__action-bar-button { - margin-right: 4px; - } - - &__label { - display: inline-block; - width: 14px; - font-size: 12px; - font-weight: 500; - color: $action-button-color; - } - } } .status__action-bar-button { margin-right: 18px; + + &.icon-button--with-counter { + margin-right: 14px; + } } .status__action-bar-dropdown { @@ -1671,11 +1659,11 @@ a.account__display-name { } } -.star-icon.active { +.icon-button.star-icon.active { color: $gold-star; } -.bookmark-icon.active { +.icon-button.bookmark-icon.active { color: $red-bookmark; } @@ -1739,6 +1727,20 @@ a.account__display-name { align-items: center; justify-content: center; flex-direction: column; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ + + * { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ + } + + &::-webkit-scrollbar, + *::-webkit-scrollbar { + width: 0; + height: 0; + background: transparent; /* Chrome/Safari/Webkit */ + } .image-loader__preview-canvas { max-width: $media-modal-media-max-width; @@ -2440,6 +2442,17 @@ a.account__display-name { line-height: 14px; color: $primary-text-color; } + + &__issue-badge { + position: absolute; + left: 11px; + bottom: 1px; + display: block; + background: $error-red; + border-radius: 50%; + width: 0.625rem; + height: 0.625rem; + } } .column-link--transparent .icon-with-badge__badge { @@ -2990,7 +3003,7 @@ a.account__display-name { } } -.no-reduce-motion button.icon-button i.fa-retweet { +button.icon-button i.fa-retweet { background-position: 0 0; height: 19px; transition: background-position 0.9s steps(10); @@ -3001,21 +3014,16 @@ a.account__display-name { &::before { display: none !important; } - } -.no-reduce-motion button.icon-button.active i.fa-retweet { +button.icon-button.active i.fa-retweet { transition-duration: 0.9s; background-position: 0 100%; } -.reduce-motion button.icon-button i.fa-retweet { - color: $action-button-color; - transition: color 100ms ease-in; -} - +.reduce-motion button.icon-button i.fa-retweet, .reduce-motion button.icon-button.active i.fa-retweet { - color: $highlight-text-color; + transition: none; } .status-card { @@ -3456,6 +3464,12 @@ a.status-card.compact:hover { } } +.column-header__permission-btn { + display: inline; + font-weight: inherit; + text-decoration: underline; +} + .column-header__setting-arrows { float: right; @@ -3479,6 +3493,15 @@ a.status-card.compact:hover { cursor: pointer; } +.column-header__issue-btn { + color: $warning-red; + + &:hover { + color: $error-red; + text-decoration: underline; + } +} + .column-header__icon { display: inline-block; margin-right: 5px; @@ -3738,6 +3761,10 @@ a.status-card.compact:hover { margin-bottom: 10px; } +.column-settings__row--with-margin { + margin-bottom: 15px; +} + .column-settings__hashtags { .column-settings__row { margin-bottom: 15px; @@ -3841,7 +3868,7 @@ a.status-card.compact:hover { } .column-settings__row { - .text-btn { + .text-btn:not(.column-header__permission-btn) { margin-bottom: 15px; } } @@ -4424,8 +4451,6 @@ a.status-card.compact:hover { .modal-root { position: relative; - transition: opacity 0.3s linear; - will-change: opacity; z-index: 9999; } @@ -4474,16 +4499,19 @@ a.status-card.compact:hover { height: 100%; position: relative; - .extended-video-player { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; + &__close, + &__zoom-button { + color: rgba($white, 0.7); - video { - max-width: $media-modal-media-max-width; - max-height: $media-modal-media-max-height; + &:hover, + &:focus, + &:active { + color: $white; + background-color: rgba($white, 0.15); + } + + &:focus { + background-color: rgba($white, 0.3); } } } @@ -4520,10 +4548,10 @@ a.status-card.compact:hover { } .media-modal__nav { - background: rgba($base-overlay-background, 0.5); + background: transparent; box-sizing: border-box; border: 0; - color: $primary-text-color; + color: rgba($primary-text-color, 0.7); cursor: pointer; display: flex; align-items: center; @@ -4534,6 +4562,12 @@ a.status-card.compact:hover { position: absolute; top: 0; bottom: 0; + + &:hover, + &:focus, + &:active { + color: $primary-text-color; + } } .media-modal__nav--left { @@ -4544,58 +4578,86 @@ a.status-card.compact:hover { right: 0; } -.media-modal__pagination { - width: 100%; - text-align: center; +.media-modal__overlay { + max-width: 600px; position: absolute; left: 0; - bottom: 20px; - pointer-events: none; -} + right: 0; + bottom: 0; + margin: 0 auto; -.media-modal__meta { - text-align: center; - position: absolute; - left: 0; - bottom: 20px; - width: 100%; - pointer-events: none; + .picture-in-picture__footer { + border-radius: 0; + background: transparent; + padding: 20px 0; - &--shifted { - bottom: 62px; - } + .icon-button { + color: $white; - a { - pointer-events: auto; - text-decoration: none; - font-weight: 500; - color: $ui-secondary-color; + &:hover, + &:focus, + &:active { + color: $white; + background-color: rgba($white, 0.15); + } - &:hover, - &:focus, - &:active { - text-decoration: underline; + &:focus { + background-color: rgba($white, 0.3); + } + + &.active { + color: $highlight-text-color; + + &:hover, + &:focus, + &:active { + background: rgba($highlight-text-color, 0.15); + } + + &:focus { + background: rgba($highlight-text-color, 0.3); + } + } + + &.star-icon.active { + color: $gold-star; + + &:hover, + &:focus, + &:active { + background: rgba($gold-star, 0.15); + } + + &:focus { + background: rgba($gold-star, 0.3); + } + } } } } -.media-modal__page-dot { - display: inline-block; +.media-modal__pagination { + display: flex; + justify-content: center; + margin-bottom: 20px; } -.media-modal__button { - background-color: $primary-text-color; - height: 12px; - width: 12px; - border-radius: 6px; - margin: 10px; +.media-modal__page-dot { + flex: 0 0 auto; + background-color: $white; + opacity: 0.4; + height: 6px; + width: 6px; + border-radius: 50%; + margin: 0 4px; padding: 0; border: 0; font-size: 0; -} + transition: opacity .2s ease-in-out; -.media-modal__button--active { - background-color: $highlight-text-color; + &.active { + opacity: 1; + } } .media-modal__close { @@ -4605,6 +4667,21 @@ a.status-card.compact:hover { z-index: 100; } +.media-modal__zoom-button { + position: absolute; + right: 64px; + top: 8px; + z-index: 100; + pointer-events: auto; + transition: opacity 0.3s linear; + will-change: opacity; +} + +.media-modal__zoom-button--hidden { + pointer-events: none; + opacity: 0; +} + .onboarding-modal, .error-modal, .embed-modal { @@ -5080,6 +5157,22 @@ a.status-card.compact:hover { } } } + + select { + appearance: none; + box-sizing: border-box; + font-size: 14px; + color: $inverted-text-color; + display: inline-block; + width: auto; + outline: 0; + font-family: inherit; + background: $simple-background-color url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(darken($simple-background-color, 14%))}'/></svg>") no-repeat right 8px center / auto 16px; + border: 1px solid darken($simple-background-color, 14%); + border-radius: 4px; + padding: 6px 10px; + padding-right: 30px; + } } .confirmation-modal__container, @@ -5370,7 +5463,6 @@ a.status-card.compact:hover { } .video-player__controls { - padding: 0 15px; padding-top: 10px; background: transparent; } @@ -5489,7 +5581,8 @@ a.status-card.compact:hover { &__buttons-bar { display: flex; justify-content: space-between; - padding-bottom: 10px; + padding-bottom: 8px; + margin: 0 -5px; .video-player__download__icon { color: inherit; @@ -5506,22 +5599,13 @@ a.status-card.compact:hover { overflow: hidden; text-overflow: ellipsis; - &.left { - button { - padding-left: 0; - } - } - - &.right { - button { - padding-right: 0; - } - } + .player-button { + display: inline-block; + outline: 0; - button { flex: 0 0 auto; background: transparent; - padding: 2px 10px; + padding: 5px; font-size: 16px; border: 0; color: rgba($white, 0.75); @@ -5539,6 +5623,7 @@ a.status-card.compact:hover { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; + margin: 0 5px; } &__time-sep, @@ -5658,7 +5743,7 @@ a.status-card.compact:hover { display: block; position: absolute; height: 4px; - top: 10px; + top: 14px; } &__progress, @@ -5667,7 +5752,7 @@ a.status-card.compact:hover { position: absolute; height: 4px; border-radius: 4px; - top: 10px; + top: 14px; background: lighten($ui-highlight-color, 8%); } @@ -5682,7 +5767,7 @@ a.status-card.compact:hover { border-radius: 50%; width: 12px; height: 12px; - top: 6px; + top: 10px; margin-left: -6px; background: lighten($ui-highlight-color, 8%); box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2); @@ -5706,7 +5791,7 @@ a.status-card.compact:hover { &.detailed, &.fullscreen { .video-player__buttons { - button { + .player-button { padding-top: 10px; padding-bottom: 10px; } @@ -5961,6 +6046,10 @@ a.status-card.compact:hover { } } +.column-settings__row .radio-button { + display: block; +} + .radio-button { font-size: 14px; position: relative; @@ -6525,6 +6614,10 @@ noscript { padding: 2px; } + & > .icon-button { + margin-right: 8px; + } + .button { margin: 0 8px; } @@ -7034,3 +7127,133 @@ noscript { } } } + +.notification, +.status__wrapper { + position: relative; + + &.unread { + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + pointer-events: 0; + width: 100%; + height: 100%; + border-left: 2px solid $highlight-text-color; + pointer-events: none; + } + } +} + +.picture-in-picture { + position: fixed; + bottom: 20px; + right: 20px; + width: 300px; + + &__footer { + border-radius: 0 0 4px 4px; + background: lighten($ui-base-color, 4%); + padding: 10px; + padding-top: 12px; + display: flex; + justify-content: space-between; + } + + &__header { + border-radius: 4px 4px 0 0; + background: lighten($ui-base-color, 4%); + padding: 10px; + display: flex; + justify-content: space-between; + + &__account { + display: flex; + text-decoration: none; + } + + .account__avatar { + margin-right: 10px; + } + + .display-name { + color: $primary-text-color; + text-decoration: none; + + strong, + span { + display: block; + text-overflow: ellipsis; + overflow: hidden; + } + + span { + color: $darker-text-color; + } + } + } + + .video-player, + .audio-player { + border-radius: 0; + } +} + +.picture-in-picture-placeholder { + box-sizing: border-box; + border: 2px dashed lighten($ui-base-color, 8%); + background: $base-shadow-color; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-top: 10px; + font-size: 16px; + font-weight: 500; + cursor: pointer; + color: $darker-text-color; + + i { + display: block; + font-size: 24px; + font-weight: 400; + margin-bottom: 10px; + } + + &:hover, + &:focus, + &:active { + border-color: lighten($ui-base-color, 12%); + } +} + +.notifications-permission-banner { + padding: 30px; + border-bottom: 1px solid lighten($ui-base-color, 8%); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + + &__close { + position: absolute; + top: 10px; + right: 10px; + } + + h2 { + font-size: 16px; + font-weight: 500; + margin-bottom: 15px; + text-align: center; + } + + p { + color: $darker-text-color; + margin-bottom: 15px; + text-align: center; + } +} diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index 51d9b46b0f34fd0de7b7eba43c76b82710d75f6c..e40ad18fffecb2587c63a588424a83bd8abe6730 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -444,6 +444,10 @@ } } + .logo-button { + padding: 3px 15px; + } + &__image { border-radius: 4px 4px 0 0; overflow: hidden; diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 7a0b2f9a398391c0a74580dd079143a47a7ea4a0..e0604303bfaf76427d1f020aa2185a4e04e838ba 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -12,6 +12,10 @@ code { } .simple_form { + &.hidden { + display: none; + } + .input { margin-bottom: 15px; overflow: hidden; @@ -100,6 +104,14 @@ code { } } + .title { + color: #d9e1e8; + font-size: 20px; + line-height: 28px; + font-weight: 400; + margin-bottom: 30px; + } + .hint { color: $darker-text-color; @@ -142,7 +154,7 @@ code { } } - .otp-hint { + .authentication-hint { margin-bottom: 25px; } @@ -342,6 +354,7 @@ code { input[type=number], input[type=email], input[type=password], + input[type=url], textarea { box-sizing: border-box; font-size: 16px; @@ -364,10 +377,6 @@ code { box-shadow: none; } - &:focus:invalid:not(:placeholder-shown) { - border-color: lighten($error-red, 12%); - } - &:required:valid { border-color: $valid-value-color; } @@ -383,6 +392,16 @@ code { } } + input[type=text], + input[type=number], + input[type=email], + input[type=password] { + &:focus:invalid:not(:placeholder-shown), + &:required:invalid:not(:placeholder-shown) { + border-color: lighten($error-red, 12%); + } + } + .input.field_with_errors { label { color: lighten($error-red, 12%); @@ -591,6 +610,10 @@ code { color: $error-value-color; } + &.hidden { + display: none; + } + a { display: inline-block; color: $darker-text-color; @@ -977,3 +1000,10 @@ code { flex-direction: row; } } + +.input.user_confirm_password, +.input.user_website { + &:not(.field_with_errors) { + display: none; + } +} diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index fbf26e30bc029020c405c2fd7680d9c80defcd91..baacf46b9fe275a9ec8459357c0b7ae64a503137 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -17,15 +17,38 @@ body.rtl { margin-right: 15px; } - .display-name { + .display-name, + .announcements__item { text-align: right; } + .announcements__item__range { + padding-right: 0; + padding-left: 18px; + } + + .reactions-bar { + margin-left: auto; + margin-right: -2px; + direction: rtl; + } + + .reactions-bar__item__count { + margin-left: 0; + margin-right: 6px; + } + + .announcements__pagination { + right: auto; + left: 0; + } + .notification__message { margin-left: 0; margin-right: 68px; } + .announcements__mastodon, .drawer__inner__mastodon > img { transform: scaleX(-1); } @@ -147,6 +170,11 @@ body.rtl { right: 42px; } + .account__header__tabs__buttons > .icon-button { + margin-right: 0; + margin-left: 8px; + } + .account__avatar-overlay-overlay { right: auto; left: 0; @@ -195,6 +223,7 @@ body.rtl { margin-right: 0; } + .picture-in-picture__header__account .display-name, .detailed-status__display-name .display-name { text-align: right; } @@ -205,6 +234,21 @@ body.rtl { float: right; } + .picture-in-picture__header__account .account__avatar { + margin-right: 0; + margin-left: 10px; + } + + .icon-button__counter { + margin-left: 0; + margin-right: 4px; + } + + .notifications-permission-banner__close { + right: auto; + left: 10px; + } + .detailed-status__favorites, .detailed-status__reblogs { margin-left: 0; @@ -416,4 +460,9 @@ body.rtl { left: auto; right: 0; } + + .picture-in-picture { + right: auto; + left: 20px; + } } diff --git a/app/javascript/styles/mastodon/statuses.scss b/app/javascript/styles/mastodon/statuses.scss index 7ae1c5a2406e3850b90804520e4f108d50908bde..078714325eef308ae143451bb7138e0b36a76c44 100644 --- a/app/javascript/styles/mastodon/statuses.scss +++ b/app/javascript/styles/mastodon/statuses.scss @@ -83,9 +83,14 @@ background: $ui-highlight-color; color: $primary-text-color; text-transform: none; - line-height: 36px; + line-height: 1.2; height: auto; - padding: 3px 15px; + min-height: 36px; + min-width: 88px; + white-space: normal; + overflow-wrap: break-word; + hyphens: auto; + padding: 0 15px; border: 0; svg { @@ -126,6 +131,12 @@ } } +a.button.logo-button { + display: inline-flex; + align-items: center; + justify-content: center; +} + .embed, .public-layout { .status__content[data-spoiler=folded] { diff --git a/app/javascript/styles/mastodon/variables.scss b/app/javascript/styles/mastodon/variables.scss index 8602c3dde9d5a38103805d77de5c76187a8892c2..f463419c8203ca3e6405c900f3732904dc99b40c 100644 --- a/app/javascript/styles/mastodon/variables.scss +++ b/app/javascript/styles/mastodon/variables.scss @@ -36,6 +36,8 @@ $dark-text-color: $ui-base-lighter-color !default; $secondary-text-color: $ui-secondary-color !default; $highlight-text-color: $ui-highlight-color !default; $action-button-color: $ui-base-lighter-color !default; +$passive-text-color: $gold-star !default; +$active-passive-text-color: $success-green !default; // For texts on inverted backgrounds $inverted-text-color: $ui-base-color !default; $lighter-text-color: $ui-base-lighter-color !default; diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index 5b97d1ec4f3e16d999b7a5293c4f168356fa0bbd..5ee4d104bad6d0c4d0edc75fd8a659bc6b616e72 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -2,6 +2,10 @@ margin-bottom: 10px; box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); + &:last-child { + margin-bottom: 0; + } + &__img { width: 100%; position: relative; @@ -442,6 +446,26 @@ vertical-align: initial !important; } + &__interrelationships { + width: 21px; + } + + .fa { + font-size: 16px; + + &.active { + color: $highlight-text-color; + } + + &.passive { + color: $passive-text-color; + } + + &.active.passive { + color: $active-passive-text-color; + } + } + @media screen and (max-width: $no-gap-breakpoint) { tbody td.optional { display: none; diff --git a/app/lib/access_token_extension.rb b/app/lib/access_token_extension.rb new file mode 100644 index 0000000000000000000000000000000000000000..3e184e7753032dd50813170cca6ab3b43ff508d4 --- /dev/null +++ b/app/lib/access_token_extension.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module AccessTokenExtension + extend ActiveSupport::Concern + + included do + after_commit :push_to_streaming_api + end + + def revoke(clock = Time) + update(revoked_at: clock.now.utc) + end + + def push_to_streaming_api + Redis.current.publish("timeline:access_token:#{id}", Oj.dump(event: :kill)) if revoked? || destroyed? + end +end diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 0ce279d287321d5c7aa4e922c3db89cfc1403f64..2b5d3ffc29c7a0379ad1d7cb2925562d47d5d0db 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -71,7 +71,15 @@ class ActivityPub::Activity end def object_uri - @object_uri ||= value_or_id(@object) + @object_uri ||= begin + str = value_or_id(@object) + + if str&.start_with?('bear:') + Addressable::URI.parse(str).query_values['u'] + else + str + end + end end def unsupported_object_type? @@ -110,13 +118,13 @@ class ActivityPub::Activity end def notify_about_reblog(status) - NotifyService.new.call(status.reblog.account, status) + NotifyService.new.call(status.reblog.account, :reblog, status) end def notify_about_mentions(status) status.active_mentions.includes(:account).each do |mention| next unless mention.account.local? && audience_includes?(mention.account) - NotifyService.new.call(mention.account, mention) + NotifyService.new.call(mention.account, :mention, mention) end end @@ -157,6 +165,34 @@ class ActivityPub::Activity fetch_remote_original_status end + def dereference_object! + return unless @object.is_a?(String) + + dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_account: signed_fetch_account) + + @object = dereferencer.object unless dereferencer.object.nil? + end + + def signed_fetch_account + return Account.find(@options[:delivered_to_account_id]) if @options[:delivered_to_account_id].present? + + first_mentioned_local_account || first_local_follower + end + + def first_mentioned_local_account + audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.uniq + local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } + .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + + return if local_usernames.empty? + + Account.local.where(username: local_usernames).first + end + + def first_local_follower + @account.followers.local.first + end + def follow_request_from_object @follow_request ||= FollowRequest.find_by(target_account: @account, uri: object_uri) unless object_uri.nil? end diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 34c646668b15ade966f24dbf28f094758e97e6ab..349e8f77e717d503ddb748f6a8421bb34aed2d0f 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -4,35 +4,50 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity? - original_status = status_from_object + RedisLock.acquire(lock_options) do |lock| + if lock.acquired? + original_status = status_from_object - return reject_payload! if original_status.nil? || !announceable?(original_status) + return reject_payload! if original_status.nil? || !announceable?(original_status) - status = Status.find_by(account: @account, reblog: original_status) + @status = Status.find_by(account: @account, reblog: original_status) - return status unless status.nil? + return @status unless @status.nil? - status = Status.create!( - account: @account, - reblog: original_status, - uri: @json['id'], - created_at: @json['published'], - override_timestamps: @options[:override_timestamps], - visibility: visibility_from_audience - ) + @status = Status.create!( + account: @account, + reblog: original_status, + uri: @json['id'], + created_at: @json['published'], + override_timestamps: @options[:override_timestamps], + visibility: visibility_from_audience + ) - distribute(status) - status + distribute(@status) + else + raise Mastodon::RaceConditionError + end + end + + @status end private + def audience_to + as_array(@json['to']).map { |x| value_or_id(x) } + end + + def audience_cc + as_array(@json['cc']).map { |x| value_or_id(x) } + end + def visibility_from_audience - if equals_or_includes?(@json['to'], ActivityPub::TagManager::COLLECTIONS[:public]) + if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public]) :public - elsif equals_or_includes?(@json['cc'], ActivityPub::TagManager::COLLECTIONS[:public]) + elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public]) :unlisted - elsif equals_or_includes?(@json['to'], @account.followers_url) + elsif audience_to.include?(@account.followers_url) :private else :direct @@ -54,4 +69,8 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def reblog_of_local_status? status_from_uri(object_uri)&.account&.local? end + + def lock_options + { redis: Redis.current, key: "announce:#{@object['id']}" } + end end diff --git a/app/lib/activitypub/activity/block.rb b/app/lib/activitypub/activity/block.rb index a17a2d50a6af0a738b2c36f41bae3afa5dcf309a..90477bf3369dca5416f54bdf813fe3e40400bce3 100644 --- a/app/lib/activitypub/activity/block.rb +++ b/app/lib/activitypub/activity/block.rb @@ -4,7 +4,12 @@ class ActivityPub::Activity::Block < ActivityPub::Activity def perform target_account = account_from_uri(object_uri) - return if target_account.nil? || !target_account.local? || @account.blocking?(target_account) + return if target_account.nil? || !target_account.local? + + if @account.blocking?(target_account) + @account.block_relationships.find_by(target_account: target_account).update(uri: @json['id']) if @json['id'].present? + return + end UnfollowService.new.call(target_account, @account) if target_account.following?(@account) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index e81452e3cae83e398af501225db538be170163b4..6127446763dc02ad915b793f7c0229ce60478f65 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -2,6 +2,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def perform + dereference_object! + case @object['type'] when 'EncryptedMessage' create_encrypted_message @@ -13,7 +15,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity private def create_encrypted_message - return reject_payload! if invalid_origin?(@object['id']) || @options[:delivered_to_account_id].blank? + return reject_payload! if invalid_origin?(object_uri) || @options[:delivered_to_account_id].blank? target_account = Account.find(@options[:delivered_to_account_id]) target_device = target_account.devices.find_by(device_id: @object.dig('to', 'deviceId')) @@ -41,7 +43,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def create_status - return reject_payload! if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity? + return reject_payload! if unsupported_object_type? || invalid_origin?(object_uri) || tombstone_exists? || !related_to_local_activity? RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -63,11 +65,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def audience_to - @object['to'] || @json['to'] + as_array(@object['to'] || @json['to']).map { |x| value_or_id(x) } end def audience_cc - @object['cc'] || @json['cc'] + as_array(@object['cc'] || @json['cc']).map { |x| value_or_id(x) } end def process_status @@ -88,7 +90,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity fetch_replies(@status) check_for_spam distribute(@status) - forward_for_reply if @status.distributable? + forward_for_reply end def find_existing_status @@ -100,8 +102,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def process_status_params @params = begin { - uri: @object['id'], - url: object_url || @object['id'], + uri: object_uri, + url: object_url || object_uri, account: @account, text: text_from_content || '', language: detected_language, @@ -109,7 +111,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity created_at: @object['published'], override_timestamps: @options[:override_timestamps], reply: @object['inReplyTo'].present?, - sensitive: @object['sensitive'] || false, + sensitive: @account.sensitized? || @object['sensitive'] || false, visibility: visibility_from_audience, thread: replied_to_status, conversation: conversation_from_uri(@object['conversation']), @@ -120,7 +122,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def process_audience - (as_array(audience_to) + as_array(audience_cc)).uniq.each do |audience| + (audience_to + audience_cc).uniq.each do |audience| next if audience == ActivityPub::TagManager::COLLECTIONS[:public] # Unlike with tags, there is no point in resolving accounts we don't already @@ -226,6 +228,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: shortcode, uri: uri) emoji.image_remote_url = image_url emoji.save + rescue Seahorse::Client::NetworkingError + nil end def process_attachments @@ -248,6 +252,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity media_attachment.save rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) + rescue Seahorse::Client::NetworkingError + nil end end @@ -311,7 +317,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity RedisLock.acquire(poll_lock_options) do |lock| if lock.acquired? already_voted = poll.votes.where(account: @account).exists? - poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: @object['id']) + poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: object_uri) else raise Mastodon::RaceConditionError end @@ -350,11 +356,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def visibility_from_audience - if equals_or_includes?(audience_to, ActivityPub::TagManager::COLLECTIONS[:public]) + if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public]) :public - elsif equals_or_includes?(audience_cc, ActivityPub::TagManager::COLLECTIONS[:public]) + elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public]) :unlisted - elsif equals_or_includes?(audience_to, @account.followers_url) + elsif audience_to.include?(@account.followers_url) :private else :direct @@ -363,7 +369,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def audience_includes?(account) uri = ActivityPub::TagManager.instance.uri_for(account) - equals_or_includes?(audience_to, uri) || equals_or_includes?(audience_cc, uri) + audience_to.include?(uri) || audience_cc.include?(uri) end def replied_to_status @@ -383,7 +389,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def text_from_content - return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || @object['id']].join(' ')) if converted_object_type? + return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || object_uri].join(' ')) if converted_object_type? if @object['content'].present? @object['content'] @@ -475,19 +481,23 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def addresses_local_accounts? return true if @options[:delivered_to_account_id] - local_usernames = (as_array(audience_to) + as_array(audience_cc)).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + local_usernames = (audience_to + audience_cc).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } return false if local_usernames.empty? Account.local.where(username: local_usernames).exists? end + def tombstone_exists? + Tombstone.exists?(uri: object_uri) + end + def check_for_spam SpamCheck.perform(@status) end def forward_for_reply - return unless @json['signature'].present? && reply_to_local? + return unless @status.distributable? && @json['signature'].present? && reply_to_local? ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url]) end @@ -505,7 +515,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def lock_options - { redis: Redis.current, key: "create:#{@object['id']}" } + { redis: Redis.current, key: "create:#{object_uri}" } end def poll_lock_options diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb index dc9ff580c1ae8b4343d41f38f74a040ff0b99475..2e5293b832ae35b2aecdf136c0112221af83f41b 100644 --- a/app/lib/activitypub/activity/delete.rb +++ b/app/lib/activitypub/activity/delete.rb @@ -13,7 +13,7 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity def delete_person lock_or_return("delete_in_progress:#{@account.id}") do - SuspendAccountService.new.call(@account, reserve_username: false) + DeleteAccountService.new.call(@account, reserve_username: false, skip_activitypub: true) end end diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index ec92f4255f6b0295acc9bb457f90fcc22ce23dd6..0beec68ab382653d622e60402017c590c120acab 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -22,10 +22,10 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity follow_request = FollowRequest.create!(account: @account, target_account: target_account, uri: @json['id']) if target_account.locked? || @account.silenced? - NotifyService.new.call(target_account, follow_request) + NotifyService.new.call(target_account, :follow_request, follow_request) else AuthorizeFollowService.new.call(@account, target_account) - NotifyService.new.call(target_account, ::Follow.find_by(account: @account, target_account: target_account)) + NotifyService.new.call(target_account, :follow, ::Follow.find_by(account: @account, target_account: target_account)) end end diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb index 674d5fe47236302cb3c770c69213dcdc4e556443..c065f01f86005387a38fbd4f70056bb1090c1386 100644 --- a/app/lib/activitypub/activity/like.rb +++ b/app/lib/activitypub/activity/like.rb @@ -7,6 +7,6 @@ class ActivityPub::Activity::Like < ActivityPub::Activity return if original_status.nil? || !original_status.account.local? || delete_arrived_first?(@json['id']) || @account.favourited?(original_status) favourite = original_status.favourites.create!(account: @account) - NotifyService.new.call(original_status.account, favourite) + NotifyService.new.call(original_status.account, :favourite, favourite) end end diff --git a/app/lib/activitypub/activity/move.rb b/app/lib/activitypub/activity/move.rb index 2103f503f20a6c97231f98a2b7c9128501361509..7e073f64d2309cdc212eafec7651a5cf6c34cf21 100644 --- a/app/lib/activitypub/activity/move.rb +++ b/app/lib/activitypub/activity/move.rb @@ -20,6 +20,9 @@ class ActivityPub::Activity::Move < ActivityPub::Activity # Initiate a re-follow for each follower MoveWorker.perform_async(origin_account.id, target_account.id) + rescue + unmark_as_processing! + raise end private diff --git a/app/lib/activitypub/activity/reject.rb b/app/lib/activitypub/activity/reject.rb index 8d771ed81753b311d77403128bd71d1594f1f55d..886dddb23557c43c52aabe6266d6cb73d6b60327 100644 --- a/app/lib/activitypub/activity/reject.rb +++ b/app/lib/activitypub/activity/reject.rb @@ -4,7 +4,7 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity def perform return reject_follow_for_relay if relay_follow? return follow_request_from_object.reject! unless follow_request_from_object.nil? - return UnfollowService.new.call(follow_from_object.target_account, @account) unless follow_from_object.nil? + return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil? case @object['type'] when 'Follow' diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb index 599823c6e25db8ffac3ed5c1a513e92ef40bf7a8..9eff1b71c9db366289b3399d024ee256a33d750d 100644 --- a/app/lib/activitypub/activity/undo.rb +++ b/app/lib/activitypub/activity/undo.rb @@ -13,11 +13,62 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity undo_like when 'Block' undo_block + when nil + handle_reference end end private + def handle_reference + # Some implementations do not inline the object, and as we don't have a + # global index, we have to guess what object it is. + return if object_uri.nil? + + try_undo_announce || try_undo_accept || try_undo_follow || try_undo_like || try_undo_block || delete_later!(object_uri) + end + + def try_undo_announce + status = Status.where.not(reblog_of_id: nil).find_by(uri: object_uri, account: @account) + if status.present? + RemoveStatusService.new.call(status) + true + else + false + end + end + + def try_undo_accept + # We can't currently handle `Undo Accept` as we don't record `Accept`'s uri + false + end + + def try_undo_follow + follow = @account.follow_requests.find_by(uri: object_uri) || @account.active_relationships.find_by(uri: object_uri) + + if follow.present? + follow.destroy + true + else + false + end + end + + def try_undo_like + # There is an index on accounts, but an account may have *many* favs, so this may be too costly + false + end + + def try_undo_block + block = @account.block_relationships.find_by(uri: object_uri) + if block.present? + UnblockService.new.call(@account, block.target_account) + true + else + false + end + end + def undo_announce return if object_uri.nil? diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb index 70035325b65b4dfc02307db5ceceb0df33281ef7..018e2df549299b56644893e856e1097c675328d4 100644 --- a/app/lib/activitypub/activity/update.rb +++ b/app/lib/activitypub/activity/update.rb @@ -4,6 +4,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze def perform + dereference_object! + if equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) update_account elsif equals_or_includes_any?(@object['type'], %w(Question)) diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb index 634ed29fa3dbe01a4db29715ac7536287b440319..2d6b876593752eb48a2af6f29dd707aa1928db03 100644 --- a/app/lib/activitypub/adapter.rb +++ b/app/lib/activitypub/adapter.rb @@ -13,7 +13,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } }, also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } }, emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' }, - featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } }, + featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' }, 'featuredTags' => { '@id' => 'toot:featuredTags', '@type' => '@id' } }, property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' }, atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' }, conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' }, @@ -23,6 +23,7 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' }, voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' }, olm: { 'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId', 'claim' => { '@type' => '@id', '@id' => 'toot:claim' }, 'fingerprintKey' => { '@type' => '@id', '@id' => 'toot:fingerprintKey' }, 'identityKey' => { '@type' => '@id', '@id' => 'toot:identityKey' }, 'devices' => { '@type' => '@id', '@id' => 'toot:devices' }, 'messageFranking' => 'toot:messageFranking', 'messageType' => 'toot:messageType', 'cipherText' => 'toot:cipherText' }, + suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' }, }.freeze def self.default_key_transform diff --git a/app/lib/activitypub/dereferencer.rb b/app/lib/activitypub/dereferencer.rb new file mode 100644 index 0000000000000000000000000000000000000000..bea69608fe228be2e2eb2ee37367fc25923cf185 --- /dev/null +++ b/app/lib/activitypub/dereferencer.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class ActivityPub::Dereferencer + include JsonLdHelper + + def initialize(uri, permitted_origin: nil, signature_account: nil) + @uri = uri + @permitted_origin = permitted_origin + @signature_account = signature_account + end + + def object + @object ||= fetch_object! + end + + private + + def bear_cap? + @uri.start_with?('bear:') + end + + def fetch_object! + if bear_cap? + fetch_with_token! + else + fetch_with_signature! + end + end + + def fetch_with_token! + perform_request(bear_cap['u'], headers: { 'Authorization' => "Bearer #{bear_cap['t']}" }) + end + + def fetch_with_signature! + perform_request(@uri) + end + + def bear_cap + @bear_cap ||= Addressable::URI.parse(@uri).query_values + end + + def perform_request(uri, headers: nil) + return if invalid_origin?(uri) + + req = Request.new(:get, uri) + + req.add_headers('Accept' => 'application/activity+json, application/ld+json') + req.add_headers(headers) if headers + req.on_behalf_of(@signature_account) if @signature_account + + req.perform do |res| + if res.code == 200 + json = body_to_json(res.body_with_limit) + json if json.present? && json['id'] == uri + else + raise Mastodon::UnexpectedResponseError, res unless response_successful?(res) || response_error_unsalvageable?(res) + end + end + end + + def invalid_origin?(uri) + return true if unsupported_uri_scheme?(uri) + + needle = Addressable::URI.parse(uri).host + haystack = Addressable::URI.parse(@permitted_origin).host + + !haystack.casecmp(needle).zero? + end +end diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb index f52a8f406fde3dfd07d7830fe32c929418222346..e853a970e81d2272af6fead2261a5f2187060b41 100644 --- a/app/lib/activitypub/linked_data_signature.rb +++ b/app/lib/activitypub/linked_data_signature.rb @@ -27,7 +27,7 @@ class ActivityPub::LinkedDataSignature document_hash = hash(@json.without('signature')) to_be_verified = options_hash + document_hash - if creator.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), to_be_verified) + if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified) creator end end @@ -44,7 +44,7 @@ class ActivityPub::LinkedDataSignature to_be_signed = options_hash + document_hash keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : creator.keypair - signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest::SHA256.new, to_be_signed)) + signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), to_be_signed)) @json.merge('signature' => options.merge('signatureValue' => signature)) end diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 3f98dad2eb0c1b2452b4b220c43c93d44fc8deef..3f2ae1106b6d11108c81e3b64f78a2e75b85ef60 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -40,6 +40,10 @@ class ActivityPub::TagManager end end + def uri_for_username(username) + account_url(username: username) + end + def generate_uri_for(_target) URI.join(root_url, 'payloads', SecureRandom.uuid) end diff --git a/app/lib/cache_buster.rb b/app/lib/cache_buster.rb new file mode 100644 index 0000000000000000000000000000000000000000..035611518eb52afb879961ddb404a10758a70030 --- /dev/null +++ b/app/lib/cache_buster.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class CacheBuster + def initialize(options = {}) + @secret_header = options[:secret_header] || 'Secret-Header' + @secret = options[:secret] || 'True' + end + + def bust(url) + site = Addressable::URI.parse(url).normalized_site + + request_pool.with(site) do |http_client| + build_request(url, http_client).perform + end + end + + private + + def request_pool + RequestPool.current + end + + def build_request(url, http_client) + Request.new(:get, url, http_client: http_client).tap do |request| + request.add_headers(@secret_header => @secret) + end + end +end diff --git a/app/lib/entity_cache.rb b/app/lib/entity_cache.rb index afdbd70f2646f44828800b6499a0d23fea91a095..89cbf8d2c47bc06c2e53e24f43ac9a401c43ad58 100644 --- a/app/lib/entity_cache.rb +++ b/app/lib/entity_cache.rb @@ -16,7 +16,7 @@ class EntityCache end def emoji(shortcodes, domain) - shortcodes = [shortcodes] unless shortcodes.is_a?(Array) + shortcodes = Array(shortcodes) cached = Rails.cache.read_multi(*shortcodes.map { |shortcode| to_key(:emoji, shortcode, domain) }) uncached_ids = [] diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb index 3362576b0bc6af4caf0bb24ca16a452c9088f09a..7c8e778713a2b38a5c373cd09214b2c5b320f93a 100644 --- a/app/lib/exceptions.rb +++ b/app/lib/exceptions.rb @@ -7,6 +7,7 @@ module Mastodon class HostValidationError < ValidationError; end class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end + class StreamValidationError < ValidationError; end class RaceConditionError < Error; end class RateLimitExceededError < Error; end diff --git a/app/lib/fast_ip_map.rb b/app/lib/fast_ip_map.rb new file mode 100644 index 0000000000000000000000000000000000000000..ba30b45f3320e77f56a5196bf704b170fbd9d3b2 --- /dev/null +++ b/app/lib/fast_ip_map.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class FastIpMap + MAX_IPV4_PREFIX = 32 + MAX_IPV6_PREFIX = 128 + + # @param [Enumerable<IPAddr>] addresses + def initialize(addresses) + @fast_lookup = {} + @ranges = [] + + # Hash look-up is faster but only works for exact matches, so we split + # exact addresses from non-exact ones + addresses.each do |address| + if (address.ipv4? && address.prefix == MAX_IPV4_PREFIX) || (address.ipv6? && address.prefix == MAX_IPV6_PREFIX) + @fast_lookup[address.to_s] = true + else + @ranges << address + end + end + + # We're more likely to hit wider-reaching ranges when checking for + # inclusion, so make sure they're sorted first + @ranges.sort_by!(&:prefix) + end + + # @param [IPAddr] address + # @return [Boolean] + def include?(address) + @fast_lookup[address.to_s] || @ranges.any? { |cidr| cidr.include?(address) } + end +end diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 96fa6cfc06ea529eba59ab49a8af1e56fe25738e..f0ad3e21fe46d7e183e509385a129e0ed5143d52 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -6,31 +6,54 @@ class FeedManager include Singleton include Redisable + # Maximum number of items stored in a single feed MAX_ITEMS = 400 - # Must be <= MAX_ITEMS or the tracking sets will grow forever + # Number of items in the feed since last reblog of status + # before the new reblog will be inserted. Must be <= MAX_ITEMS + # or the tracking sets will grow forever REBLOG_FALLOFF = 40 + # Execute block for every active account + # @yield [Account] + # @return [void] def with_active_accounts(&block) Account.joins(:user).where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago).find_each(&block) end + # Redis key of a feed + # @param [Symbol] type + # @param [Integer] id + # @param [Symbol] subtype + # @return [String] def key(type, id, subtype = nil) return "feed:#{type}:#{id}" unless subtype "feed:#{type}:#{id}:#{subtype}" end - def filter?(timeline_type, status, receiver_id) - if timeline_type == :home - filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status])) - elsif timeline_type == :mentions - filter_from_mentions?(status, receiver_id) + # Check if the status should not be added to a feed + # @param [Symbol] timeline_type + # @param [Status] status + # @param [Account|List] receiver + # @return [Boolean] + def filter?(timeline_type, status, receiver) + case timeline_type + when :home + filter_from_home?(status, receiver.id, build_crutches(receiver.id, [status])) + when :list + filter_from_list?(status, receiver) || filter_from_home?(status, receiver.account_id, build_crutches(receiver.account_id, [status])) + when :mentions + filter_from_mentions?(status, receiver.id) else false end end + # Add a status to a home feed and send a streaming API update + # @param [Account] account + # @param [Status] status + # @return [Boolean] def push_to_home(account, status) return false unless add_to_feed(:home, account.id, status, account.user&.aggregates_reblogs?) @@ -39,6 +62,10 @@ class FeedManager true end + # Remove a status from a home feed and send a streaming API update + # @param [Account] account + # @param [Status] status + # @return [Boolean] def unpush_from_home(account, status) return false unless remove_from_feed(:home, account.id, status, account.user&.aggregates_reblogs?) @@ -46,20 +73,22 @@ class FeedManager true end + # Add a status to a list feed and send a streaming API update + # @param [List] list + # @param [Status] status + # @return [Boolean] def push_to_list(list, status) - if status.reply? && status.in_reply_to_account_id != status.account_id - should_filter = status.in_reply_to_account_id != list.account_id - should_filter &&= !ListAccount.where(list_id: list.id, account_id: status.in_reply_to_account_id).exists? - return false if should_filter - end - - return false unless add_to_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?) + return false if filter_from_list?(status, list) || !add_to_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?) trim(:list, list.id) PushUpdateWorker.perform_async(list.account_id, status.id, "timeline:list:#{list.id}") if push_update_required?("timeline:list:#{list.id}") true end + # Remove a status from a list feed and send a streaming API update + # @param [List] list + # @param [Status] status + # @return [Boolean] def unpush_from_list(list, status) return false unless remove_from_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?) @@ -67,32 +96,11 @@ class FeedManager true end - def trim(type, account_id) - timeline_key = key(type, account_id) - reblog_key = key(type, account_id, 'reblogs') - - # Remove any items past the MAX_ITEMS'th entry in our feed - redis.zremrangebyrank(timeline_key, 0, -(FeedManager::MAX_ITEMS + 1)) - - # Get the score of the REBLOG_FALLOFF'th item in our feed, and stop - # tracking anything after it for deduplication purposes. - falloff_rank = FeedManager::REBLOG_FALLOFF - 1 - falloff_range = redis.zrevrange(timeline_key, falloff_rank, falloff_rank, with_scores: true) - falloff_score = falloff_range&.first&.last&.to_i || 0 - - # Get any reblogs we might have to clean up after. - redis.zrangebyscore(reblog_key, 0, falloff_score).each do |reblogged_id| - # Remove it from the set of reblogs we're tracking *first* to avoid races. - redis.zrem(reblog_key, reblogged_id) - # Just drop any set we might have created to track additional reblogs. - # This means that if this reblog is deleted, we won't automatically insert - # another reblog, but also that any new reblog can be inserted into the - # feed. - redis.del(key(type, account_id, "reblogs:#{reblogged_id}")) - end - end - - def merge_into_timeline(from_account, into_account) + # Fill a home feed with an account's statuses + # @param [Account] from_account + # @param [Account] into_account + # @return [void] + def merge_into_home(from_account, into_account) timeline_key = key(:home, into_account.id) aggregate = into_account.user&.aggregates_reblogs? query = from_account.statuses.where(visibility: [:public, :unlisted, :private]).includes(:preloadable_poll, reblog: :account).limit(FeedManager::MAX_ITEMS / 4) @@ -114,7 +122,37 @@ class FeedManager trim(:home, into_account.id) end - def unmerge_from_timeline(from_account, into_account) + # Fill a list feed with an account's statuses + # @param [Account] from_account + # @param [List] list + # @return [void] + def merge_into_list(from_account, list) + timeline_key = key(:list, list.id) + aggregate = list.account.user&.aggregates_reblogs? + query = from_account.statuses.where(visibility: [:public, :unlisted, :private]).includes(:preloadable_poll, reblog: :account).limit(FeedManager::MAX_ITEMS / 4) + + if redis.zcard(timeline_key) >= FeedManager::MAX_ITEMS / 4 + oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i + query = query.where('id > ?', oldest_home_score) + end + + statuses = query.to_a + crutches = build_crutches(list.account_id, statuses) + + statuses.each do |status| + next if filter_from_home?(status, list.account_id, crutches) || filter_from_list?(status, list) + + add_to_feed(:list, list.id, status, aggregate) + end + + trim(:list, list.id) + end + + # Remove an account's statuses from a home feed + # @param [Account] from_account + # @param [Account] into_account + # @return [void] + def unmerge_from_home(from_account, into_account) timeline_key = key(:home, into_account.id) oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true)&.first&.last&.to_i || 0 @@ -123,14 +161,31 @@ class FeedManager end end - def clear_from_timeline(account, target_account) - # Clear from timeline all statuses from or mentionning target_account + # Remove an account's statuses from a list feed + # @param [Account] from_account + # @param [List] list + # @return [void] + def unmerge_from_list(from_account, list) + timeline_key = key(:list, list.id) + oldest_list_score = redis.zrange(timeline_key, 0, 0, with_scores: true)&.first&.last&.to_i || 0 + + from_account.statuses.select('id, reblog_of_id').where('id > ?', oldest_list_score).reorder(nil).find_each do |status| + remove_from_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?) + end + end + + # Clear all statuses from or mentioning target_account from a home feed + # @param [Account] account + # @param [Account] target_account + # @return [void] + def clear_from_home(account, target_account) timeline_key = key(:home, account.id) timeline_status_ids = redis.zrange(timeline_key, 0, -1) statuses = Status.where(id: timeline_status_ids).select(:id, :reblog_of_id, :account_id).to_a reblogged_ids = Status.where(id: statuses.map(&:reblog_of_id).compact, account: target_account).pluck(:id) with_mentions_ids = Mention.active.where(status_id: statuses.flat_map { |s| [s.id, s.reblog_of_id] }.compact, account: target_account).pluck(:status_id) - target_statuses = statuses.filter do |status| + + target_statuses = statuses.select do |status| status.account_id == target_account.id || reblogged_ids.include?(status.reblog_of_id) || with_mentions_ids.include?(status.id) || with_mentions_ids.include?(status.reblog_of_id) end @@ -139,12 +194,15 @@ class FeedManager end end - def populate_feed(account) + # Populate home feed of account from scratch + # @param [Account] account + # @return [void] + def populate_home(account) limit = FeedManager::MAX_ITEMS / 2 aggregate = account.user&.aggregates_reblogs? timeline_key = key(:home, account.id) - account.statuses.where.not(visibility: :direct).limit(limit).each do |status| + account.statuses.limit(limit).each do |status| add_to_feed(:home, account.id, status, aggregate) end @@ -172,17 +230,91 @@ class FeedManager end end + # Completely clear multiple feeds at once + # @param [Symbol] type + # @param [Array<Integer>] ids + # @return [void] + def clean_feeds!(type, ids) + reblogged_id_sets = {} + + redis.pipelined do + ids.each do |feed_id| + redis.del(key(type, feed_id)) + reblog_key = key(type, feed_id, 'reblogs') + # We collect a future for this: we don't block while getting + # it, but we can iterate over it later. + reblogged_id_sets[feed_id] = redis.zrange(reblog_key, 0, -1) + redis.del(reblog_key) + end + end + + # Remove all of the reblog tracking keys we just removed the + # references to. + redis.pipelined do + reblogged_id_sets.each do |feed_id, future| + future.value.each do |reblogged_id| + reblog_set_key = key(type, feed_id, "reblogs:#{reblogged_id}") + redis.del(reblog_set_key) + end + end + end + end + private - def push_update_required?(timeline_id) - redis.exists?("subscribed:#{timeline_id}") + # Trim a feed to maximum size by removing older items + # @param [Symbol] type + # @param [Integer] timeline_id + # @return [void] + def trim(type, timeline_id) + timeline_key = key(type, timeline_id) + reblog_key = key(type, timeline_id, 'reblogs') + + # Remove any items past the MAX_ITEMS'th entry in our feed + redis.zremrangebyrank(timeline_key, 0, -(FeedManager::MAX_ITEMS + 1)) + + # Get the score of the REBLOG_FALLOFF'th item in our feed, and stop + # tracking anything after it for deduplication purposes. + falloff_rank = FeedManager::REBLOG_FALLOFF + falloff_range = redis.zrevrange(timeline_key, falloff_rank, falloff_rank, with_scores: true) + falloff_score = falloff_range&.first&.last&.to_i + + return if falloff_score.nil? + + # Get any reblogs we might have to clean up after. + redis.zrangebyscore(reblog_key, 0, falloff_score).each do |reblogged_id| + # Remove it from the set of reblogs we're tracking *first* to avoid races. + redis.zrem(reblog_key, reblogged_id) + # Just drop any set we might have created to track additional reblogs. + # This means that if this reblog is deleted, we won't automatically insert + # another reblog, but also that any new reblog can be inserted into the + # feed. + redis.del(key(type, timeline_id, "reblogs:#{reblogged_id}")) + end end + # Check if there is a streaming API client connected + # for the given feed + # @param [String] timeline_key + # @return [Boolean] + def push_update_required?(timeline_key) + redis.exists?("subscribed:#{timeline_key}") + end + + # Check if the account is blocking or muting any of the given accounts + # @param [Integer] receiver_id + # @param [Array<Integer>] account_ids + # @param [Symbol] context def blocks_or_mutes?(receiver_id, account_ids, context) Block.where(account_id: receiver_id, target_account_id: account_ids).any? || (context == :home ? Mute.where(account_id: receiver_id, target_account_id: account_ids).any? : Mute.where(account_id: receiver_id, target_account_id: account_ids, hide_notifications: true).any?) end + # Check if status should not be added to the home feed + # @param [Status] status + # @param [Integer] receiver_id + # @param [Hash] crutches + # @return [Boolean] def filter_from_home?(status, receiver_id, crutches) return false if receiver_id == status.account_id return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?) @@ -215,6 +347,11 @@ class FeedManager false end + # Check if status should not be added to the mentions feed + # @see NotifyService + # @param [Status] status + # @param [Integer] receiver_id + # @return [Boolean] def filter_from_mentions?(status, receiver_id) return true if receiver_id == status.account_id return true if phrase_filtered?(status, receiver_id, :notifications) @@ -231,6 +368,27 @@ class FeedManager should_filter end + # Check if status should not be added to the list feed + # @param [Status] status + # @param [List] list + # @return [Boolean] + def filter_from_list?(status, list) + if status.reply? && status.in_reply_to_account_id != status.account_id + should_filter = status.in_reply_to_account_id != list.account_id + should_filter &&= !list.show_followed? + should_filter &&= !(list.show_list? && ListAccount.where(list_id: list.id, account_id: status.in_reply_to_account_id).exists?) + + return !!should_filter + end + + false + end + + # Check if the status hits a phrase filter + # @param [Status] status + # @param [Integer] receiver_id + # @param [Symbol] context + # @return [Boolean] def phrase_filtered?(status, receiver_id, context) active_filters = Rails.cache.fetch("filters:#{receiver_id}") { CustomFilter.where(account_id: receiver_id).active_irreversible.to_a }.to_a @@ -266,6 +424,11 @@ class FeedManager # added, and false if it was not added to the feed. Note that this is # an internal helper: callers must call trim or push updates if # either action is appropriate. + # @param [Symbol] timeline_type + # @param [Integer] account_id + # @param [Status] status + # @param [Boolean] aggregate_reblogs + # @return [Boolean] def add_to_feed(timeline_type, account_id, status, aggregate_reblogs = true) timeline_key = key(timeline_type, account_id) reblog_key = key(timeline_type, account_id, 'reblogs') @@ -278,14 +441,12 @@ class FeedManager return false if !rank.nil? && rank < FeedManager::REBLOG_FALLOFF - reblog_rank = redis.zrevrank(reblog_key, status.reblog_of_id) - - if reblog_rank.nil? + # The ordered set at `reblog_key` holds statuses which have a reblog + # in the top `REBLOG_FALLOFF` statuses of the timeline + if redis.zadd(reblog_key, status.id, status.reblog_of_id, nx: true) # This is not something we've already seen reblogged, so we - # can just add it to the feed (and note that we're - # reblogging it). + # can just add it to the feed (and note that we're reblogging it). redis.zadd(timeline_key, status.id, status.id) - redis.zadd(reblog_key, status.id, status.reblog_of_id) else # Another reblog of the same status was already in the # REBLOG_FALLOFF most recent statuses, so we note that this @@ -299,9 +460,7 @@ class FeedManager # delay of the worker deliverying the original status, the late addition # by merging timelines, and other reasons. # If such a reblog already exists, just do not re-insert it into the feed. - rank = redis.zrevrank(reblog_key, status.id) - - return false unless rank.nil? + return false unless redis.zscore(reblog_key, status.id).nil? redis.zadd(timeline_key, status.id, status.id) end @@ -313,6 +472,11 @@ class FeedManager # with reblogs, and returning true if a status was removed. As with # `add_to_feed`, this does not trigger push updates, so callers must # do so if appropriate. + # @param [Symbol] timeline_type + # @param [Integer] account_id + # @param [Status] status + # @param [Boolean] aggregate_reblogs + # @return [Boolean] def remove_from_feed(timeline_type, account_id, status, aggregate_reblogs = true) timeline_key = key(timeline_type, account_id) reblog_key = key(timeline_type, account_id, 'reblogs') @@ -347,6 +511,11 @@ class FeedManager redis.zrem(timeline_key, status.id) end + # Pre-fetch various objects and relationships for given statuses that + # are going to be checked by the filtering methods + # @param [Integer] receiver_id + # @param [Array<Status>] statuses + # @return [Hash] def build_crutches(receiver_id, statuses) crutches = {} diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index e6f5d7a6327969a990f12bab33ff0e26dc79530d..7f217ae9f688a6b024fb8fdd2457cc5eb30c188f 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -135,6 +135,7 @@ class Formatter end end + # rubocop:disable Metrics/BlockNesting def encode_custom_emojis(html, emojis, animate = false) return html if emojis.empty? @@ -189,6 +190,7 @@ class Formatter html end + # rubocop:enable Metrics/BlockNesting def rewrite(text, entities) text = text.to_s diff --git a/app/lib/request.rb b/app/lib/request.rb index bcba1eebf645c8eaa078e6e2e3e3dbe30df5eb28..38048dad7b552e1718ce50710311b358c4d166e4 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -114,7 +114,7 @@ class Request def signature algorithm = 'rsa-sha256' - signature = Base64.strict_encode64(@keypair.sign(OpenSSL::Digest::SHA256.new, signed_string)) + signature = Base64.strict_encode64(@keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string)) "keyId=\"#{key_id}\",algorithm=\"#{algorithm}\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\"" end @@ -253,7 +253,15 @@ class Request alias new open def check_private_address(address) - raise Mastodon::HostValidationError if PrivateAddressCheck.private_address?(IPAddr.new(address.to_s)) + addr = IPAddr.new(address.to_s) + return if private_address_exceptions.any? { |range| range.include?(addr) } + raise Mastodon::HostValidationError if PrivateAddressCheck.private_address?(addr) + end + + def private_address_exceptions + @private_address_exceptions = begin + (ENV['ALLOWED_PRIVATE_ADDRESSES'] || '').split(',').map { |addr| IPAddr.new(addr) } + end end end end diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb index 4ad1199a60442c9788d8c731e963ff31cfd1a62b..8f700197b272a88dc9f6fb1a2bec49b1465b1cfe 100644 --- a/app/lib/sanitize_config.rb +++ b/app/lib/sanitize_config.rb @@ -18,6 +18,7 @@ class Sanitize gopher xmpp magnet + gemini ).freeze CLASS_WHITELIST_TRANSFORMER = lambda do |env| diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb index 3bec9bd569d0ecc9ee923f18294a3bcf59842f03..ef694205c43dacd966d2eb69903f0c568fad2e78 100644 --- a/app/lib/settings/scoped_settings.rb +++ b/app/lib/settings/scoped_settings.rb @@ -11,7 +11,6 @@ module Settings @object = object end - # rubocop:disable Style/MethodMissingSuper def method_missing(method, *args) method_name = method.to_s # set a value for a variable @@ -24,7 +23,6 @@ module Settings self[method_name] end end - # rubocop:enable Style/MethodMissingSuper def respond_to_missing?(*) true diff --git a/app/lib/sidekiq_error_handler.rb b/app/lib/sidekiq_error_handler.rb index b07817d4556b2d37059471aa97b9b4b27069f7a2..ab555b1be3eb893923e7520c0051d12123abb116 100644 --- a/app/lib/sidekiq_error_handler.rb +++ b/app/lib/sidekiq_error_handler.rb @@ -17,8 +17,10 @@ class SidekiqErrorHandler private + # rubocop:disable Naming/MethodParameterName def limit_backtrace_and_raise(e) e.set_backtrace(e.backtrace.first(BACKTRACE_LIMIT)) raise e end + # rubocop:enable Naming/MethodParameterName end diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb new file mode 100644 index 0000000000000000000000000000000000000000..35b191dadb0bc777d2a4f7570dc8ad7e98e07933 --- /dev/null +++ b/app/lib/status_reach_finder.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +class StatusReachFinder + def initialize(status) + @status = status + end + + def inboxes + Account.where(id: reached_account_ids).inboxes + end + + private + + def reached_account_ids + [ + replied_to_account_id, + reblog_of_account_id, + mentioned_account_ids, + reblogs_account_ids, + favourites_account_ids, + replies_account_ids, + ].tap do |arr| + arr.flatten! + arr.compact! + arr.uniq! + end + end + + def replied_to_account_id + @status.in_reply_to_account_id + end + + def reblog_of_account_id + @status.reblog.account_id if @status.reblog? + end + + def mentioned_account_ids + @status.mentions.pluck(:account_id) + end + + def reblogs_account_ids + @status.reblogs.pluck(:account_id) + end + + def favourites_account_ids + @status.favourites.pluck(:account_id) + end + + def replies_account_ids + @status.replies.pluck(:account_id) + end +end diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index fa8255faab159edbbfa0ecf5fcb57024c528d686..e37bc6d9f11437a0f53794da3aedbae7b126635d 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -27,6 +27,7 @@ class UserSettingsDecorator user.settings['display_media'] = display_media_preference if change?('setting_display_media') user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers') user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion') + user.settings['disable_swiping'] = disable_swiping_preference if change?('setting_disable_swiping') user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') user.settings['noindex'] = noindex_preference if change?('setting_noindex') user.settings['theme'] = theme_preference if change?('setting_theme') @@ -88,6 +89,10 @@ class UserSettingsDecorator boolean_cast_setting 'setting_reduce_motion' end + def disable_swiping_preference + boolean_cast_setting 'setting_disable_swiping' + end + def noindex_preference boolean_cast_setting 'setting_noindex' end diff --git a/app/lib/webfinger.rb b/app/lib/webfinger.rb new file mode 100644 index 0000000000000000000000000000000000000000..c7aa43bb334efc18508e2a9754d27fe825aad298 --- /dev/null +++ b/app/lib/webfinger.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +class Webfinger + class Error < StandardError; end + class GoneError < Error; end + class RedirectError < StandardError; end + + class Response + def initialize(body) + @json = Oj.load(body, mode: :strict) + end + + def subject + @json['subject'] + end + + def link(rel, attribute) + links.dig(rel, attribute) + end + + private + + def links + @links ||= @json['links'].map { |link| [link['rel'], link] }.to_h + end + end + + def initialize(uri) + _, @domain = uri.split('@') + + raise ArgumentError, 'Webfinger requested for local account' if @domain.nil? + + @uri = uri + end + + def perform + Response.new(body_from_webfinger) + rescue Oj::ParseError + raise Webfinger::Error, "Invalid JSON in response for #{@uri}" + rescue Addressable::URI::InvalidURIError + raise Webfinger::Error, "Invalid URI for #{@uri}" + end + + private + + def body_from_webfinger(url = standard_url, use_fallback = true) + webfinger_request(url).perform do |res| + if res.code == 200 + res.body_with_limit + elsif res.code == 404 && use_fallback + body_from_host_meta + elsif res.code == 410 + raise Webfinger::GoneError, "#{@uri} is gone from the server" + else + raise Webfinger::Error, "Request for #{@uri} returned HTTP #{res.code}" + end + end + end + + def body_from_host_meta + host_meta_request.perform do |res| + if res.code == 200 + body_from_webfinger(url_from_template(res.body_with_limit), false) + else + raise Webfinger::Error, "Request for #{@uri} returned HTTP #{res.code}" + end + end + end + + def url_from_template(str) + link = Nokogiri::XML(str).at_xpath('//xmlns:Link[@rel="lrdd"]') + + if link.present? + link['template'].gsub('{uri}', @uri) + else + raise Webfinger::Error, "Request for #{@uri} returned host-meta without link to Webfinger" + end + rescue Nokogiri::XML::XPath::SyntaxError + raise Webfinger::Error, "Invalid XML encountered in host-meta for #{@uri}" + end + + def host_meta_request + Request.new(:get, host_meta_url).add_headers('Accept' => 'application/xrd+xml, application/xml, text/xml') + end + + def webfinger_request(url) + Request.new(:get, url).add_headers('Accept' => 'application/jrd+json, application/json') + end + + def standard_url + "https://#{@domain}/.well-known/webfinger?resource=#{@uri}" + end + + def host_meta_url + "https://#{@domain}/.well-known/host-meta" + end +end diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 9d8a7886c2732c174ffb5a1ece1ac9bc83601eb6..54db892ccc6e767ae4c7d1cf344deeabccf33ed3 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -10,7 +10,7 @@ class NotificationMailer < ApplicationMailer @me = recipient @status = notification.target_status - return if @me.user.disabled? || @status.nil? + return unless @me.user.functional? && @status.present? locale_for_account(@me) do thread_by_conversation(@status.conversation) @@ -22,7 +22,7 @@ class NotificationMailer < ApplicationMailer @me = recipient @account = notification.from_account - return if @me.user.disabled? + return unless @me.user.functional? locale_for_account(@me) do mail to: @me.user.email, subject: I18n.t('notification_mailer.follow.subject', name: @account.acct) @@ -34,7 +34,7 @@ class NotificationMailer < ApplicationMailer @account = notification.from_account @status = notification.target_status - return if @me.user.disabled? || @status.nil? + return unless @me.user.functional? && @status.present? locale_for_account(@me) do thread_by_conversation(@status.conversation) @@ -47,7 +47,7 @@ class NotificationMailer < ApplicationMailer @account = notification.from_account @status = notification.target_status - return if @me.user.disabled? || @status.nil? + return unless @me.user.functional? && @status.present? locale_for_account(@me) do thread_by_conversation(@status.conversation) @@ -59,7 +59,7 @@ class NotificationMailer < ApplicationMailer @me = recipient @account = notification.from_account - return if @me.user.disabled? + return unless @me.user.functional? locale_for_account(@me) do mail to: @me.user.email, subject: I18n.t('notification_mailer.follow_request.subject', name: @account.acct) @@ -67,7 +67,7 @@ class NotificationMailer < ApplicationMailer end def digest(recipient, **opts) - return if recipient.user.disabled? + return unless recipient.user.functional? @me = recipient @since = opts[:since] || [@me.user.last_emailed_at, (@me.user.current_sign_in_at + 1.day)].compact.max @@ -88,8 +88,10 @@ class NotificationMailer < ApplicationMailer def thread_by_conversation(conversation) return if conversation.nil? + msg_id = "<conversation-#{conversation.id}.#{conversation.created_at.strftime('%Y-%m-%d')}@#{Rails.configuration.x.local_domain}>" + headers['In-Reply-To'] = msg_id - headers['References'] = msg_id + headers['References'] = msg_id end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 2cd58e60a7e963c414ae4078c21c7249f3b90382..95996ba3ff9d8c92fc2423322a041899cb3592c7 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -15,7 +15,7 @@ class UserMailer < Devise::Mailer @token = token @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.unconfirmed_email.presence || @resource.email, @@ -29,7 +29,7 @@ class UserMailer < Devise::Mailer @token = token @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.reset_password_instructions.subject') @@ -40,7 +40,7 @@ class UserMailer < Devise::Mailer @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.password_change.subject') @@ -51,7 +51,7 @@ class UserMailer < Devise::Mailer @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.email_changed.subject') @@ -62,7 +62,7 @@ class UserMailer < Devise::Mailer @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_enabled.subject') @@ -73,7 +73,7 @@ class UserMailer < Devise::Mailer @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_disabled.subject') @@ -84,18 +84,64 @@ class UserMailer < Devise::Mailer @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('devise.mailer.two_factor_recovery_codes_changed.subject') end end + def webauthn_enabled(user, **) + @resource = user + @instance = Rails.configuration.x.local_domain + + return unless @resource.active_for_authentication? + + I18n.with_locale(@resource.locale || I18n.default_locale) do + mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_enabled.subject') + end + end + + def webauthn_disabled(user, **) + @resource = user + @instance = Rails.configuration.x.local_domain + + return unless @resource.active_for_authentication? + + I18n.with_locale(@resource.locale || I18n.default_locale) do + mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_disabled.subject') + end + end + + def webauthn_credential_added(user, webauthn_credential) + @resource = user + @instance = Rails.configuration.x.local_domain + @webauthn_credential = webauthn_credential + + return unless @resource.active_for_authentication? + + I18n.with_locale(@resource.locale || I18n.default_locale) do + mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_credential.added.subject') + end + end + + def webauthn_credential_deleted(user, webauthn_credential) + @resource = user + @instance = Rails.configuration.x.local_domain + @webauthn_credential = webauthn_credential + + return unless @resource.active_for_authentication? + + I18n.with_locale(@resource.locale || I18n.default_locale) do + mail to: @resource.email, subject: I18n.t('devise.mailer.webauthn_credential.deleted.subject') + end + end + def welcome(user) @resource = user @instance = Rails.configuration.x.local_domain - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('user_mailer.welcome.subject') @@ -107,7 +153,7 @@ class UserMailer < Devise::Mailer @instance = Rails.configuration.x.local_domain @backup = backup - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, subject: I18n.t('user_mailer.backup_ready.subject') @@ -135,7 +181,7 @@ class UserMailer < Devise::Mailer @detection = Browser.new(user_agent) @timestamp = timestamp.to_time.utc - return if @resource.disabled? + return unless @resource.active_for_authentication? I18n.with_locale(@resource.locale || I18n.default_locale) do mail to: @resource.email, diff --git a/app/models/account.rb b/app/models/account.rb index 6b7ebda9e67f0e18cfa742e4c83c2fbcfd9daa0a..e6cf03fa84e9cd54aee8f8165d75d26a79109775 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -50,6 +50,8 @@ # avatar_storage_schema_version :integer # header_storage_schema_version :integer # devices_url :string +# sensitized_at :datetime +# suspension_origin :integer # class Account < ApplicationRecord @@ -65,6 +67,8 @@ class Account < ApplicationRecord include Paginable include AccountCounters include DomainNormalizable + include DomainMaterializable + include AccountMerging TRUST_LEVELS = { untrusted: 0, @@ -72,6 +76,7 @@ class Account < ApplicationRecord }.freeze enum protocol: [:ostatus, :activitypub] + enum suspension_origin: [:local, :remote], _prefix: true validates :username, presence: true validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? } @@ -92,13 +97,14 @@ class Account < ApplicationRecord scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) } scope :silenced, -> { where.not(silenced_at: nil) } scope :suspended, -> { where.not(suspended_at: nil) } + scope :sensitized, -> { where.not(sensitized_at: nil) } scope :without_suspended, -> { where(suspended_at: nil) } scope :without_silenced, -> { where(silenced_at: nil) } + scope :without_instance_actor, -> { where.not(id: -99) } scope :recent, -> { reorder(id: :desc) } scope :bots, -> { where(actor_type: %w(Application Service)) } scope :groups, -> { where(actor_type: 'Group') } scope :alphabetic, -> { order(domain: :asc, username: :asc) } - scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') } scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) } scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) } scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } @@ -217,28 +223,45 @@ class Account < ApplicationRecord end def suspended? - suspended_at.present? + suspended_at.present? && !instance_actor? end - def suspend!(date = Time.now.utc) + def suspended_permanently? + suspended? && deletion_request.nil? + end + + def suspended_temporarily? + suspended? && deletion_request.present? + end + + def suspend!(date: Time.now.utc, origin: :local) transaction do - user&.disable! if local? - update!(suspended_at: date) + create_deletion_request! + update!(suspended_at: date, suspension_origin: origin) end end def unsuspend! transaction do - user&.enable! if local? - update!(suspended_at: nil) + deletion_request&.destroy! + update!(suspended_at: nil, suspension_origin: nil) end end + def sensitized? + sensitized_at.present? + end + + def sensitize!(date = Time.now.utc) + update!(sensitized_at: date) + end + + def unsensitize! + update!(sensitized_at: nil) + end + def memorialize! - transaction do - user&.disable! if local? - update!(memorial: true) - end + update!(memorial: true) end def sign? @@ -355,6 +378,12 @@ class Account < ApplicationRecord shared_inbox_url.presence || inbox_url end + def synchronization_uri_prefix + return 'local' if local? + + @synchronization_uri_prefix ||= uri[/http(s?):\/\/[^\/]+\//] + end + class Field < ActiveModelSerializers::Model attributes :name, :value, :verified_at, :account, :errors @@ -410,12 +439,8 @@ class Account < ApplicationRecord super - %w(statuses_count following_count followers_count) end - def domains - reorder(nil).pluck(Arel.sql('distinct accounts.domain')) - end - def inboxes - urls = reorder(nil).where(protocol: :activitypub).pluck(Arel.sql("distinct coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url)")) + urls = reorder(nil).where(protocol: :activitypub).group(:preferred_inbox_url).pluck(Arel.sql("coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url) AS preferred_inbox_url")) DeliveryFailureTracker.without_unavailable(urls) end @@ -553,17 +578,6 @@ class Account < ApplicationRecord end def clean_feed_manager - reblog_key = FeedManager.instance.key(:home, id, 'reblogs') - reblogged_id_set = Redis.current.zrange(reblog_key, 0, -1) - - Redis.current.pipelined do - Redis.current.del(FeedManager.instance.key(:home, id)) - Redis.current.del(reblog_key) - - reblogged_id_set.each do |reblogged_id| - reblog_set_key = FeedManager.instance.key(:home, id, "reblogs:#{reblogged_id}") - Redis.current.del(reblog_set_key) - end - end + FeedManager.instance.clean_feeds!(:home, [id]) end end diff --git a/app/models/account_alias.rb b/app/models/account_alias.rb index 792e9e8d4da7574bd2e7acdd079fe6488d9f02fb..3d659142a05548022c60f04e72591c836cdecde3 100644 --- a/app/models/account_alias.rb +++ b/app/models/account_alias.rb @@ -33,7 +33,7 @@ class AccountAlias < ApplicationRecord def set_uri target_account = ResolveAccountService.new.call(acct) self.uri = ActivityPub::TagManager.instance.uri_for(target_account) unless target_account.nil? - rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error + rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error # Validation will take care of it end diff --git a/app/models/account_conversation.rb b/app/models/account_conversation.rb index b43816588521b479130462aaf501a3cad7773a6e..56fd13543c8cf3f153ee71777d430c1d9a4cd88d 100644 --- a/app/models/account_conversation.rb +++ b/app/models/account_conversation.rb @@ -36,17 +36,18 @@ class AccountConversation < ApplicationRecord end class << self - def paginate_by_id(limit, options = {}) + def to_a_paginated_by_id(limit, options = {}) if options[:min_id] - paginate_by_min_id(limit, options[:min_id]).reverse + paginate_by_min_id(limit, options[:min_id], options[:max_id]).reverse else - paginate_by_max_id(limit, options[:max_id], options[:since_id]) + paginate_by_max_id(limit, options[:max_id], options[:since_id]).to_a end end - def paginate_by_min_id(limit, min_id = nil) + def paginate_by_min_id(limit, min_id = nil, max_id = nil) query = order(arel_table[:last_status_id].asc).limit(limit) query = query.where(arel_table[:last_status_id].gt(min_id)) if min_id.present? + query = query.where(arel_table[:last_status_id].lt(max_id)) if max_id.present? query end diff --git a/app/models/account_deletion_request.rb b/app/models/account_deletion_request.rb new file mode 100644 index 0000000000000000000000000000000000000000..7d0c346cc27e2806049db0fa27ce8530dd75a22d --- /dev/null +++ b/app/models/account_deletion_request.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: account_deletion_requests +# +# id :bigint(8) not null, primary key +# account_id :bigint(8) +# created_at :datetime not null +# updated_at :datetime not null +# +class AccountDeletionRequest < ApplicationRecord + DELAY_TO_DELETION = 30.days.freeze + + belongs_to :account + + def due_at + created_at + DELAY_TO_DELETION + end +end diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index 7b6012e0fa78ec2948d3008cf5dc8accff831212..2b001385f2d8a1091c1f9686bbeb3ce03bcfb170 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -45,7 +45,7 @@ class AccountFilter def scope_for(key, value) case key.to_s when 'local' - Account.local + Account.local.without_instance_actor when 'remote' Account.remote when 'by_domain' diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb index 681b5b2cd0bc9e76d1f08e2d1a8c72dd7a26d3f3..4fae98ed7260d525ed7bddabde9990b91f252d0c 100644 --- a/app/models/account_migration.rb +++ b/app/models/account_migration.rb @@ -54,7 +54,7 @@ class AccountMigration < ApplicationRecord def set_target_account self.target_account = ResolveAccountService.new.call(acct) - rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error + rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error # Validation will take care of it end diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb index c84e4217c8c6b11d5a0770ff443a6de39db1afd6..e70b54d79b93df00916053708e1ba0aabd9c790c 100644 --- a/app/models/account_stat.rb +++ b/app/models/account_stat.rb @@ -21,26 +21,26 @@ class AccountStat < ApplicationRecord def increment_count!(key) update(attributes_for_increment(key)) - rescue ActiveRecord::StaleObjectError + rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotUnique begin reload_with_id rescue ActiveRecord::RecordNotFound - # Nothing to do - else - retry + return end + + retry end def decrement_count!(key) - update(key => [public_send(key) - 1, 0].max) - rescue ActiveRecord::StaleObjectError + update(attributes_for_decrement(key)) + rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotUnique begin reload_with_id rescue ActiveRecord::RecordNotFound - # Nothing to do - else - retry + return end + + retry end private @@ -51,8 +51,13 @@ class AccountStat < ApplicationRecord attrs end + def attributes_for_decrement(key) + attrs = { key => [public_send(key) - 1, 0].max } + attrs + end + def reload_with_id - self.id = find_by!(account: account).id if new_record? + self.id = self.class.find_by!(account: account).id if new_record? reload end end diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb index 157e6c04d1eb39d41872f3c07f1054179c6d66af..5efc924d5f7ae36a7fb038ff4c2fbfe06a157416 100644 --- a/app/models/account_warning.rb +++ b/app/models/account_warning.rb @@ -13,7 +13,7 @@ # class AccountWarning < ApplicationRecord - enum action: %i(none disable silence suspend), _suffix: :action + enum action: %i(none disable sensitive silence suspend), _suffix: :action belongs_to :account, inverse_of: :account_warnings belongs_to :target_account, class_name: 'Account', inverse_of: :targeted_account_warnings diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb index b30a823699e3df2573e9b4e2f4993dfaa588c574..bf222391f7e9c114bab81a36676d95421001cd21 100644 --- a/app/models/admin/account_action.rb +++ b/app/models/admin/account_action.rb @@ -8,6 +8,7 @@ class Admin::AccountAction TYPES = %w( none disable + sensitive silence suspend ).freeze @@ -64,6 +65,8 @@ class Admin::AccountAction case type when 'disable' handle_disable! + when 'sensitive' + handle_sensitive! when 'silence' handle_silence! when 'suspend' @@ -109,6 +112,12 @@ class Admin::AccountAction target_account.user&.disable! end + def handle_sensitive! + authorize(target_account, :sensitive?) + log_action(:sensitive, target_account) + target_account.sensitize! + end + def handle_silence! authorize(target_account, :silence?) log_action(:silence, target_account) @@ -118,7 +127,7 @@ class Admin::AccountAction def handle_suspend! authorize(target_account, :suspend?) log_action(:suspend, target_account) - target_account.suspend! + target_account.suspend!(origin: :local) end def text_for_warning @@ -134,7 +143,7 @@ class Admin::AccountAction end def process_email! - UserMailer.warning(target_account.user, warning, status_ids).deliver_now! if warnable? + UserMailer.warning(target_account.user, warning, status_ids).deliver_later! if warnable? end def warnable? @@ -142,7 +151,7 @@ class Admin::AccountAction end def status_ids - @report.status_ids if @report && include_statuses + report.status_ids if report && include_statuses end def reports diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 0ba7e1609449eb9ccf433a4775120e24fb61eb88..3a1b67e06752c7c5f1235673fb04c7972a6e04a5 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -35,9 +35,11 @@ class Admin::ActionLogFilter reopen_report: { target_type: 'Report', action: 'reopen' }.freeze, reset_password_user: { target_type: 'User', action: 'reset_password' }.freeze, resolve_report: { target_type: 'Report', action: 'resolve' }.freeze, + sensitive_account: { target_type: 'Account', action: 'sensitive' }.freeze, silence_account: { target_type: 'Account', action: 'silence' }.freeze, suspend_account: { target_type: 'Account', action: 'suspend' }.freeze, unassigned_report: { target_type: 'Report', action: 'unassigned' }.freeze, + unsensitive_account: { target_type: 'Account', action: 'unsensitive' }.freeze, unsilence_account: { target_type: 'Account', action: 'unsilence' }.freeze, unsuspend_account: { target_type: 'Account', action: 'unsuspend' }.freeze, update_announcement: { target_type: 'Announcement', action: 'update' }.freeze, diff --git a/app/models/announcement.rb b/app/models/announcement.rb index c493604c22bbd32a38da5fcdd013168ace681a15..f8183aabce47673597f992a1ed53e5489fe686cf 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -22,6 +22,7 @@ class Announcement < ApplicationRecord scope :published, -> { where(published: true) } scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where('announcement_mutes.id IS NULL') } scope :chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) ASC')) } + scope :reverse_chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) DESC')) } has_many :announcement_mutes, dependent: :destroy has_many :announcement_reactions, dependent: :destroy diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb index d5144d4b8ea27a1e253c58ad3abbebae529132a4..b5f12c9a56556d32a4ad4ab779e3c32ed3011baa 100644 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account_associations.rb @@ -63,5 +63,8 @@ module AccountAssociations # Hashtags has_and_belongs_to_many :tags has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account + + # Account deletion requests + has_one :deletion_request, class_name: 'AccountDeletionRequest', inverse_of: :account, dependent: :destroy end end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index be7211f2cad29aee750a7f27ca309d9f786b296e..974f57820d08332436492d5b0b3bc2cb65fdfa35 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -8,6 +8,7 @@ module AccountInteractions Follow.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow, mapping| mapping[follow.target_account_id] = { reblogs: follow.show_reblogs?, + notify: follow.notify?, } end end @@ -36,6 +37,7 @@ module AccountInteractions FollowRequest.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |follow_request, mapping| mapping[follow_request.target_account_id] = { reblogs: follow_request.show_reblogs?, + notify: follow_request.notify?, } end end @@ -95,25 +97,29 @@ module AccountInteractions has_many :announcement_mutes, dependent: :destroy end - def follow!(other_account, reblogs: nil, uri: nil, rate_limit: false) - reblogs = true if reblogs.nil? - - rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit) + def follow!(other_account, reblogs: nil, notify: nil, uri: nil, rate_limit: false, bypass_limit: false) + rel = active_relationships.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, uri: uri, rate_limit: rate_limit, bypass_follow_limit: bypass_limit) .find_or_create_by!(target_account: other_account) - rel.update!(show_reblogs: reblogs) + rel.show_reblogs = reblogs unless reblogs.nil? + rel.notify = notify unless notify.nil? + + rel.save! if rel.changed? + remove_potential_friendship(other_account) rel end - def request_follow!(other_account, reblogs: nil, uri: nil, rate_limit: false) - reblogs = true if reblogs.nil? - - rel = follow_requests.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit) + def request_follow!(other_account, reblogs: nil, notify: nil, uri: nil, rate_limit: false, bypass_limit: false) + rel = follow_requests.create_with(show_reblogs: reblogs.nil? ? true : reblogs, notify: notify.nil? ? false : notify, uri: uri, rate_limit: rate_limit, bypass_follow_limit: bypass_limit) .find_or_create_by!(target_account: other_account) - rel.update!(show_reblogs: reblogs) + rel.show_reblogs = reblogs unless reblogs.nil? + rel.notify = notify unless notify.nil? + + rel.save! if rel.changed? + remove_potential_friendship(other_account) rel @@ -125,9 +131,12 @@ module AccountInteractions .find_or_create_by!(target_account: other_account) end - def mute!(other_account, notifications: nil) + def mute!(other_account, notifications: nil, duration: 0) notifications = true if notifications.nil? - mute = mute_relationships.create_with(hide_notifications: notifications).find_or_create_by!(target_account: other_account) + mute = mute_relationships.create_with(hide_notifications: notifications).find_or_initialize_by(target_account: other_account) + mute.expires_in = duration.zero? ? nil : duration + mute.save! + remove_potential_friendship(other_account) # When toggling a mute between hiding and allowing notifications, the mute will already exist, so the find_or_create_by! call will return the existing Mute without updating the hide_notifications attribute. Therefore, we check that hide_notifications? is what we want and set it if it isn't. @@ -234,6 +243,26 @@ module AccountInteractions .where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) end + def remote_followers_hash(url_prefix) + Rails.cache.fetch("followers_hash:#{id}:#{url_prefix}") do + digest = "\x00" * 32 + followers.where(Account.arel_table[:uri].matches(url_prefix + '%', false, true)).pluck_each(:uri) do |uri| + Xorcist.xor!(digest, Digest::SHA256.digest(uri)) + end + digest.unpack('H*')[0] + end + end + + def local_followers_hash + Rails.cache.fetch("followers_hash:#{id}:local") do + digest = "\x00" * 32 + followers.where(domain: nil).pluck_each(:username) do |username| + Xorcist.xor!(digest, Digest::SHA256.digest(ActivityPub::TagManager.instance.uri_for_username(username))) + end + digest.unpack('H*')[0] + end + end + private def remove_potential_friendship(other_account, mutual = false) diff --git a/app/models/concerns/account_merging.rb b/app/models/concerns/account_merging.rb new file mode 100644 index 0000000000000000000000000000000000000000..c3b7018f2c3db57aa04a14d96070465d8ece227a --- /dev/null +++ b/app/models/concerns/account_merging.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module AccountMerging + extend ActiveSupport::Concern + + def merge_with!(other_account) + # Since it's the same remote resource, the remote resource likely + # already believes we are following/blocking, so it's safe to + # re-attribute the relationships too. However, during the presence + # of the index bug users could have *also* followed the reference + # account already, therefore mass update will not work and we need + # to check for (and skip past) uniqueness errors + + owned_classes = [ + Status, StatusPin, MediaAttachment, Poll, Report, Tombstone, Favourite, + Follow, FollowRequest, Block, Mute, AccountIdentityProof, + AccountModerationNote, AccountPin, AccountStat, ListAccount, + PollVote, Mention, AccountDeletionRequest, AccountNote + ] + + owned_classes.each do |klass| + klass.where(account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + target_classes = [ + Follow, FollowRequest, Block, Mute, AccountModerationNote, AccountPin, + AccountNote + ] + + target_classes.each do |klass| + klass.where(target_account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:target_account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + # Some follow relationships have moved, so the cache is stale + Rails.cache.delete_matched("followers_hash:#{id}:*") + Rails.cache.delete_matched("relationships:#{id}:*") + Rails.cache.delete_matched("relationships:*:#{id}") + end +end diff --git a/app/models/concerns/domain_materializable.rb b/app/models/concerns/domain_materializable.rb new file mode 100644 index 0000000000000000000000000000000000000000..88337f8c00094c9c504d4929224819f2cae739a9 --- /dev/null +++ b/app/models/concerns/domain_materializable.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module DomainMaterializable + extend ActiveSupport::Concern + + included do + after_create_commit :refresh_instances_view + end + + def refresh_instances_view + Instance.refresh unless domain.nil? || Instance.where(domain: domain).exists? + end +end diff --git a/app/models/concerns/expireable.rb b/app/models/concerns/expireable.rb index f7d2bab498a19571cf375be43355f93c8de98edf..a66a4661b1cca3a8fcf64211f13a81cfd018bb3c 100644 --- a/app/models/concerns/expireable.rb +++ b/app/models/concerns/expireable.rb @@ -6,7 +6,15 @@ module Expireable included do scope :expired, -> { where.not(expires_at: nil).where('expires_at < ?', Time.now.utc) } - attr_reader :expires_in + def expires_in + return @expires_in if defined?(@expires_in) + + if expires_at.nil? + nil + else + (expires_at - created_at).to_i + end + end def expires_in=(interval) self.expires_at = interval.to_i.seconds.from_now if interval.present? diff --git a/app/models/concerns/follow_limitable.rb b/app/models/concerns/follow_limitable.rb new file mode 100644 index 0000000000000000000000000000000000000000..c64060d6e56b46c63bf11d547d87c73e00f8ca72 --- /dev/null +++ b/app/models/concerns/follow_limitable.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module FollowLimitable + extend ActiveSupport::Concern + + included do + validates_with FollowLimitValidator, on: :create, unless: :bypass_follow_limit? + end + + def bypass_follow_limit=(value) + @bypass_follow_limit = value + end + + def bypass_follow_limit? + @bypass_follow_limit + end +end diff --git a/app/models/concerns/paginable.rb b/app/models/concerns/paginable.rb index 8863094f7d467be0ac73ae1279648d9f24b4347d..62e39f6714ab860f467055fbe7e2975c86b89afe 100644 --- a/app/models/concerns/paginable.rb +++ b/app/models/concerns/paginable.rb @@ -14,18 +14,19 @@ module Paginable # Differs from :paginate_by_max_id in that it gives the results immediately following min_id, # whereas since_id gives the items with largest id, but with since_id as a cutoff. # Results will be in ascending order by id. - scope :paginate_by_min_id, ->(limit, min_id = nil) { + scope :paginate_by_min_id, ->(limit, min_id = nil, max_id = nil) { query = reorder(arel_table[:id]).limit(limit) query = query.where(arel_table[:id].gt(min_id)) if min_id.present? + query = query.where(arel_table[:id].lt(max_id)) if max_id.present? query } - scope :paginate_by_id, ->(limit, options = {}) { + def self.to_a_paginated_by_id(limit, options = {}) if options[:min_id].present? - paginate_by_min_id(limit, options[:min_id]).reverse + paginate_by_min_id(limit, options[:min_id], options[:max_id]).reverse else - paginate_by_max_id(limit, options[:max_id], options[:since_id]) + paginate_by_max_id(limit, options[:max_id], options[:since_id]).to_a end - } + end end end diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index c6d0c7f1f440a8f1a42564ea885f076709dde38f..56b9c0164221f1ddb3e37e3c229684c1f68e8a68 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -29,7 +29,7 @@ module Remotable rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" raise e unless suppress_errors - rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError => e + rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" end diff --git a/app/models/domain_allow.rb b/app/models/domain_allow.rb index 5fe0e3a29c340d8a2da1dfdbdea1e32577b0880f..4b0a89c184cff14804f9d7f53ccad48daae121a6 100644 --- a/app/models/domain_allow.rb +++ b/app/models/domain_allow.rb @@ -12,6 +12,7 @@ class DomainAllow < ApplicationRecord include DomainNormalizable + include DomainMaterializable validates :domain, presence: true, uniqueness: true, domain: true diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 2b18e01fadd9ca4df1b53cce99bb193064dca8c1..bba04c60395ed1ec597ef89d76a59013ab833e23 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -12,10 +12,12 @@ # reject_reports :boolean default(FALSE), not null # private_comment :text # public_comment :text +# obfuscate :boolean default(FALSE), not null # class DomainBlock < ApplicationRecord include DomainNormalizable + include DomainMaterializable enum severity: [:silence, :suspend, :noop] @@ -72,4 +74,23 @@ class DomainBlock < ApplicationRecord scope = suspend? ? accounts.where(suspended_at: created_at) : accounts.where(silenced_at: created_at) scope.count end + + def public_domain + return domain unless obfuscate? + + length = domain.size + visible_ratio = length / 4 + + domain.chars.map.with_index do |chr, i| + if i > visible_ratio && i < length - visible_ratio && chr != '.' + '*' + else + chr + end + end.join + end + + def domain_digest + Digest::SHA256.hexdigest(domain) + end end diff --git a/app/models/export.rb b/app/models/export.rb index cab01f11ad004c7e3e76b72dc3769eb25ce994bd..5216eed5ea7613dec39a1e46095b82c542a29def 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -9,6 +9,14 @@ class Export @account = account end + def to_bookmarks_csv + CSV.generate do |csv| + account.bookmarks.includes(:status).reorder(id: :desc).each do |bookmark| + csv << [ActivityPub::TagManager.instance.uri_for(bookmark.status)] + end + end + end + def to_blocked_accounts_csv to_csv account.blocking.select(:username, :domain) end @@ -55,6 +63,10 @@ class Export account.statuses_count end + def total_bookmarks + account.bookmarks.count + end + def total_follows account.following_count end diff --git a/app/models/favourite.rb b/app/models/favourite.rb index bf0ec4449c4615c6aee68c89b5c890bd18831330..35028b7dd339d7fa561bcee8fba7b1feaf774b60 100644 --- a/app/models/favourite.rb +++ b/app/models/favourite.rb @@ -36,7 +36,7 @@ class Favourite < ApplicationRecord end def decrement_cache_counters - return if association(:status).loaded? && (status.marked_for_destruction? || status.marked_for_mass_destruction?) + return if association(:status).loaded? && status.marked_for_destruction? status&.decrement_count!(:favourites_count) end end diff --git a/app/models/feed.rb b/app/models/feed.rb index 36e0c1e0a09b94375a4ba3d2178c5dd00b7df0e0..f51dcfab1dad66affbea0199b22aa7033db33d8e 100644 --- a/app/models/feed.rb +++ b/app/models/feed.rb @@ -20,12 +20,12 @@ class Feed protected def from_redis(limit, max_id, since_id, min_id) + max_id = '+inf' if max_id.blank? if min_id.blank? - max_id = '+inf' if max_id.blank? since_id = '-inf' if since_id.blank? unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:first).map(&:to_i) else - unhydrated = redis.zrangebyscore(key, "(#{min_id}", '+inf', limit: [0, limit], with_scores: true).map(&:first).map(&:to_i) + unhydrated = redis.zrangebyscore(key, "(#{min_id}", "(#{max_id}", limit: [0, limit], with_scores: true).map(&:first).map(&:to_i) end Status.where(id: unhydrated).cache_ids diff --git a/app/models/follow.rb b/app/models/follow.rb index f3e48a2ed7e73f3239eaac68e35af4286a973487..a5e3fe8099516c717b184316a3d455b4650a8782 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -10,12 +10,14 @@ # target_account_id :bigint(8) not null # show_reblogs :boolean default(TRUE), not null # uri :string +# notify :boolean default(FALSE), not null # class Follow < ApplicationRecord include Paginable include RelationshipCacheable include RateLimitable + include FollowLimitable rate_limit by: :account, family: :follows @@ -25,7 +27,6 @@ class Follow < ApplicationRecord has_one :notification, as: :activity, dependent: :destroy validates :account_id, uniqueness: { scope: :target_account_id } - validates_with FollowLimitValidator, on: :create scope :recent, -> { reorder(id: :desc) } @@ -34,14 +35,16 @@ class Follow < ApplicationRecord end def revoke_request! - FollowRequest.create!(account: account, target_account: target_account, show_reblogs: show_reblogs, uri: uri) + FollowRequest.create!(account: account, target_account: target_account, show_reblogs: show_reblogs, notify: notify, uri: uri) destroy! end before_validation :set_uri, only: :create after_create :increment_cache_counters + after_create :invalidate_hash_cache after_destroy :remove_endorsements after_destroy :decrement_cache_counters + after_destroy :invalidate_hash_cache private @@ -62,4 +65,10 @@ class Follow < ApplicationRecord account&.decrement_count!(:following_count) target_account&.decrement_count!(:followers_count) end + + def invalidate_hash_cache + return if account.local? && target_account.local? + + Rails.cache.delete("followers_hash:#{target_account_id}:#{account.synchronization_uri_prefix}") + end end diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index 3325e264cce33f0cd9a1f7ce30f63169a176ea26..59fefcdf64e402cb87671676421fb56beabd41bd 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -10,12 +10,14 @@ # target_account_id :bigint(8) not null # show_reblogs :boolean default(TRUE), not null # uri :string +# notify :boolean default(FALSE), not null # class FollowRequest < ApplicationRecord include Paginable include RelationshipCacheable include RateLimitable + include FollowLimitable rate_limit by: :account, family: :follows @@ -25,10 +27,9 @@ class FollowRequest < ApplicationRecord has_one :notification, as: :activity, dependent: :destroy validates :account_id, uniqueness: { scope: :target_account_id } - validates_with FollowLimitValidator, on: :create def authorize! - account.follow!(target_account, reblogs: show_reblogs, uri: uri) + account.follow!(target_account, reblogs: show_reblogs, notify: notify, uri: uri) MergeWorker.perform_async(target_account.id, account.id) if account.local? destroy! end diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb index 0b285fde92caa40d895f558d6aa9a0ff9bd116b6..26d6d3abfc00a932dd1d18f04f7a2c09053d1cc1 100644 --- a/app/models/form/account_batch.rb +++ b/app/models/form/account_batch.rb @@ -9,6 +9,8 @@ class Form::AccountBatch def save case action + when 'follow' + follow! when 'unfollow' unfollow! when 'remove_from_followers' @@ -24,6 +26,12 @@ class Form::AccountBatch private + def follow! + accounts.find_each do |target_account| + FollowService.new.call(current_account, target_account) + end + end + def unfollow! accounts.find_each do |target_account| UnfollowService.new.call(current_account, target_account) @@ -43,7 +51,7 @@ class Form::AccountBatch end def account_domains - accounts.pluck(Arel.sql('distinct domain')).compact + accounts.group(:domain).pluck(:domain).compact end def accounts @@ -69,6 +77,6 @@ class Form::AccountBatch records = accounts.includes(:user) records.each { |account| authorize(account.user, :reject?) } - .each { |account| SuspendAccountService.new.call(account, reserve_email: false, reserve_username: false) } + .each { |account| DeleteAccountService.new.call(account, reserve_email: false, reserve_username: false) } end end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 390836f287fae9b79f6f3ae013430d725fc1be5c..e9f78da2123ba4833b1047e625d6a5413179fe8d 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -35,6 +35,7 @@ class Form::AdminSettings show_domain_blocks show_domain_blocks_rationale noindex + require_invite_text ).freeze BOOLEAN_KEYS = %i( @@ -51,6 +52,7 @@ class Form::AdminSettings trends trendable_by_default noindex + require_invite_text ).freeze UPLOAD_KEYS = %i( diff --git a/app/models/form/custom_emoji_batch.rb b/app/models/form/custom_emoji_batch.rb index 6b7ea5355dd1dcbd6c14fc0f77a7e02761a1acca..f4fa84c102cacd4f994c2e02f10d0e4f5e4881ce 100644 --- a/app/models/form/custom_emoji_batch.rb +++ b/app/models/form/custom_emoji_batch.rb @@ -30,7 +30,7 @@ class Form::CustomEmojiBatch private def custom_emojis - CustomEmoji.where(id: custom_emoji_ids) + @custom_emojis ||= CustomEmoji.where(id: custom_emoji_ids) end def update! diff --git a/app/models/form/ip_block_batch.rb b/app/models/form/ip_block_batch.rb new file mode 100644 index 0000000000000000000000000000000000000000..f6fe9b59357779c59c3f0db4d91acb3e22d024db --- /dev/null +++ b/app/models/form/ip_block_batch.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class Form::IpBlockBatch + include ActiveModel::Model + include Authorization + include AccountableConcern + + attr_accessor :ip_block_ids, :action, :current_account + + def save + case action + when 'delete' + delete! + end + end + + private + + def ip_blocks + @ip_blocks ||= IpBlock.where(id: ip_block_ids) + end + + def delete! + ip_blocks.each { |ip_block| authorize(ip_block, :destroy?) } + + ip_blocks.each do |ip_block| + ip_block.destroy + log_action :destroy, ip_block + end + end +end diff --git a/app/models/form/redirect.rb b/app/models/form/redirect.rb index a7961f8e8aa00e7b311a3742644e3f79c89ebf61..19ee9faedd046bb420e66a93d123064cf30e8abb 100644 --- a/app/models/form/redirect.rb +++ b/app/models/form/redirect.rb @@ -32,7 +32,7 @@ class Form::Redirect def set_target_account @target_account = ResolveAccountService.new.call(acct) - rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error + rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error # Validation will take care of it end diff --git a/app/models/import.rb b/app/models/import.rb index c78a04d07349215dae3155c4419f5fdf48ad6684..00a54892ef2d4314e4f766ec1703d0431217d5c4 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -24,9 +24,10 @@ class Import < ApplicationRecord belongs_to :account - enum type: [:following, :blocking, :muting, :domain_blocking] + enum type: [:following, :blocking, :muting, :domain_blocking, :bookmarks] validates :type, presence: true + validates_with ImportValidator, on: :create has_attached_file :data validates_attachment_content_type :data, content_type: FILE_TYPES diff --git a/app/models/instance.rb b/app/models/instance.rb index 3c740f8a2bc7dc50554db94fe082a12439fcc2bf..29be036626e75dee42fa32118a1394029ac6cb13 100644 --- a/app/models/instance.rb +++ b/app/models/instance.rb @@ -1,26 +1,63 @@ # frozen_string_literal: true +# == Schema Information +# +# Table name: instances +# +# domain :string primary key +# accounts_count :bigint(8) +# -class Instance - include ActiveModel::Model +class Instance < ApplicationRecord + self.primary_key = :domain - attr_accessor :domain, :accounts_count, :domain_block + has_many :accounts, foreign_key: :domain, primary_key: :domain - def initialize(resource) - @domain = resource.domain - @accounts_count = resource.respond_to?(:accounts_count) ? resource.accounts_count : nil - @domain_block = resource.is_a?(DomainBlock) ? resource : DomainBlock.rule_for(domain) - @domain_allow = resource.is_a?(DomainAllow) ? resource : DomainAllow.rule_for(domain) + belongs_to :domain_block, foreign_key: :domain, primary_key: :domain + belongs_to :domain_allow, foreign_key: :domain, primary_key: :domain + + scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } + + def self.refresh + Scenic.database.refresh_materialized_view(table_name, concurrently: true, cascade: false) end - def countable? - @accounts_count.present? + def readonly? + true end - def to_param - domain + def delivery_failure_tracker + @delivery_failure_tracker ||= DeliveryFailureTracker.new(domain) + end + + def following_count + @following_count ||= Follow.where(account: accounts).count + end + + def followers_count + @followers_count ||= Follow.where(target_account: accounts).count + end + + def reports_count + @reports_count ||= Report.where(target_account: accounts).count end - def cache_key + def blocks_count + @blocks_count ||= Block.where(target_account: accounts).count + end + + def public_comment + domain_block&.public_comment + end + + def private_comment + domain_block&.private_comment + end + + def media_storage + @media_storage ||= MediaAttachment.where(account: accounts).sum(:file_file_size) + end + + def to_param domain end end diff --git a/app/models/instance_filter.rb b/app/models/instance_filter.rb index 9c467bc276c55d97aa7c3c27606fdefa49e9dc77..0598d8fead628dd9687b48af9ba975bdd1dea067 100644 --- a/app/models/instance_filter.rb +++ b/app/models/instance_filter.rb @@ -13,18 +13,27 @@ class InstanceFilter end def results - if params[:limited].present? - scope = DomainBlock - scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present? - scope.order(id: :desc) - elsif params[:allowed].present? - scope = DomainAllow - scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present? - scope.order(id: :desc) + scope = Instance.includes(:domain_block, :domain_allow).order(accounts_count: :desc) + + params.each do |key, value| + scope.merge!(scope_for(key, value.to_s.strip)) if value.present? + end + + scope + end + + private + + def scope_for(key, value) + case key.to_s + when 'limited' + Instance.joins(:domain_block).reorder(Arel.sql('domain_blocks.id desc')) + when 'allowed' + Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc')) + when 'by_domain' + Instance.matches_domain(value) else - scope = Account.remote - scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present? - scope.by_domain_accounts + raise "Unknown filter: #{key}" end end end diff --git a/app/models/invite.rb b/app/models/invite.rb index 29d25eae801c3ea576bf45cffbd05d92024424f5..7ea4e2f9841b0d8042db34d5eee3c1f9b5f981f5 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -28,7 +28,7 @@ class Invite < ApplicationRecord before_validation :set_code def valid_for_use? - (max_uses.nil? || uses < max_uses) && !expired? && !(user.nil? || user.disabled?) + (max_uses.nil? || uses < max_uses) && !expired? && user&.functional? end private diff --git a/app/models/ip_block.rb b/app/models/ip_block.rb new file mode 100644 index 0000000000000000000000000000000000000000..aedd3ca0d4d91e6173a8ef3fd9402ddee676d1a4 --- /dev/null +++ b/app/models/ip_block.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: ip_blocks +# +# id :bigint(8) not null, primary key +# created_at :datetime not null +# updated_at :datetime not null +# expires_at :datetime +# ip :inet default(#<IPAddr: IPv4:0.0.0.0/255.255.255.255>), not null +# severity :integer default(NULL), not null +# comment :text default(""), not null +# + +class IpBlock < ApplicationRecord + CACHE_KEY = 'blocked_ips' + + include Expireable + + enum severity: { + sign_up_requires_approval: 5000, + no_access: 9999, + } + + validates :ip, :severity, presence: true + + after_commit :reset_cache + + class << self + def blocked?(remote_ip) + blocked_ips_map = Rails.cache.fetch(CACHE_KEY) { FastIpMap.new(IpBlock.where(severity: :no_access).pluck(:ip)) } + blocked_ips_map.include?(remote_ip) + end + end + + private + + def reset_cache + Rails.cache.delete(CACHE_KEY) + end +end diff --git a/app/models/list.rb b/app/models/list.rb index c9c94fca1dc40e681f3ca3f45282dc23a87a3ae2..cdc6ebdb37a8f256e2b9bda598a8d704d6b47b9d 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -3,11 +3,12 @@ # # Table name: lists # -# id :bigint(8) not null, primary key -# account_id :bigint(8) not null -# title :string default(""), not null -# created_at :datetime not null -# updated_at :datetime not null +# id :bigint(8) not null, primary key +# account_id :bigint(8) not null +# title :string default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# replies_policy :integer default("list"), not null # class List < ApplicationRecord @@ -15,6 +16,8 @@ class List < ApplicationRecord PER_ACCOUNT_LIMIT = 50 + enum replies_policy: [:list, :followed, :none], _prefix: :show + belongs_to :account, optional: true has_many :list_accounts, inverse_of: :list, dependent: :destroy @@ -31,17 +34,6 @@ class List < ApplicationRecord private def clean_feed_manager - reblog_key = FeedManager.instance.key(:list, id, 'reblogs') - reblogged_id_set = Redis.current.zrange(reblog_key, 0, -1) - - Redis.current.pipelined do - Redis.current.del(FeedManager.instance.key(:list, id)) - Redis.current.del(reblog_key) - - reblogged_id_set.each do |reblogged_id| - reblog_set_key = FeedManager.instance.key(:list, id, "reblogs:#{reblogged_id}") - Redis.current.del(reblog_set_key) - end - end + FeedManager.instance.clean_feeds!(:list, [id]) end end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 3f2e0ceb1b85a90d164f15ee9cc673753bf46045..663bb0896d4135c95d6e828da5e11fc5c53e918f 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -336,8 +336,9 @@ class MediaAttachment < ApplicationRecord return unless movie.valid? + raise Mastodon::StreamValidationError, 'Video has no video stream' if movie.width.nil? || movie.frame_rate.nil? raise Mastodon::DimensionsValidationError, "#{movie.width}x#{movie.height} videos are not supported" if movie.width * movie.height > MAX_VIDEO_MATRIX_LIMIT - raise Mastodon::DimensionsValidationError, "#{movie.frame_rate.to_i}fps videos are not supported" if movie.frame_rate > MAX_VIDEO_FRAME_RATE + raise Mastodon::DimensionsValidationError, "#{movie.frame_rate.floor}fps videos are not supported" if movie.frame_rate.floor > MAX_VIDEO_FRAME_RATE end def set_meta diff --git a/app/models/mute.rb b/app/models/mute.rb index 0e00c2278f6f6be1a83e620d41730e0f7c6488aa..578345ef644ad4459a90fde1be38c540d7e5cb82 100644 --- a/app/models/mute.rb +++ b/app/models/mute.rb @@ -9,11 +9,13 @@ # account_id :bigint(8) not null # target_account_id :bigint(8) not null # hide_notifications :boolean default(TRUE), not null +# expires_at :datetime # class Mute < ApplicationRecord include Paginable include RelationshipCacheable + include Expireable belongs_to :account belongs_to :target_account, class_name: 'Account' diff --git a/app/models/notification.rb b/app/models/notification.rb index ad7528f505c035f8702fe9e7fdf53af2f5c18ac4..e83123c973184b1f3d09f8ad78ee2423de13777d 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -10,21 +10,34 @@ # updated_at :datetime not null # account_id :bigint(8) not null # from_account_id :bigint(8) not null +# type :string # class Notification < ApplicationRecord + self.inheritance_column = nil + include Paginable include Cacheable - TYPE_CLASS_MAP = { - mention: 'Mention', - reblog: 'Status', - follow: 'Follow', - follow_request: 'FollowRequest', - favourite: 'Favourite', - poll: 'Poll', + LEGACY_TYPE_CLASS_MAP = { + 'Mention' => :mention, + 'Status' => :reblog, + 'Follow' => :follow, + 'FollowRequest' => :follow_request, + 'Favourite' => :favourite, + 'Poll' => :poll, }.freeze + TYPES = %i( + mention + status + reblog + follow + follow_request + favourite + poll + ).freeze + STATUS_INCLUDES = [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account]].freeze belongs_to :account, optional: true @@ -38,26 +51,30 @@ class Notification < ApplicationRecord belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id', optional: true belongs_to :poll, foreign_type: 'Poll', foreign_key: 'activity_id', optional: true - validates :account_id, uniqueness: { scope: [:activity_type, :activity_id] } - validates :activity_type, inclusion: { in: TYPE_CLASS_MAP.values } + validates :type, inclusion: { in: TYPES } + + scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) } scope :browserable, ->(exclude_types = [], account_id = nil) { - types = TYPE_CLASS_MAP.values - activity_types_from_types(exclude_types) + types = TYPES - exclude_types.map(&:to_sym) + if account_id.nil? - where(activity_type: types) + where(type: types) else - where(activity_type: types, from_account_id: account_id) + where(type: types, from_account_id: account_id) end } cache_associated :from_account, status: STATUS_INCLUDES, mention: [status: STATUS_INCLUDES], favourite: [:account, status: STATUS_INCLUDES], follow: :account, follow_request: :account, poll: [status: STATUS_INCLUDES] def type - @type ||= TYPE_CLASS_MAP.invert[activity_type].to_sym + @type ||= (super || LEGACY_TYPE_CLASS_MAP[activity_type]).to_sym end def target_status case type + when :status + status when :reblog status&.reblog when :favourite @@ -86,10 +103,6 @@ class Notification < ApplicationRecord item.target_status.account = accounts[item.target_status.account_id] if item.target_status end end - - def activity_types_from_types(types) - types.map { |type| TYPE_CLASS_MAP[type.to_sym] }.compact - end end after_initialize :set_from_account diff --git a/app/models/poll.rb b/app/models/poll.rb index b5deafcc21fbe442f54b86fb3a0c7bb592c7aac9..e1ca5525219e4eaa67caf0538f69f79a026eb9ed 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -25,7 +25,7 @@ class Poll < ApplicationRecord belongs_to :account belongs_to :status - has_many :votes, class_name: 'PollVote', inverse_of: :poll, dependent: :destroy + has_many :votes, class_name: 'PollVote', inverse_of: :poll, dependent: :delete_all has_many :notifications, as: :activity, dependent: :destroy diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index 235928260d26733dc61ed335da78911f8c330172..a6ec839f805d296991d436d58a55dd4c04c8d08b 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -72,6 +72,7 @@ class PreviewCard < ApplicationRecord class << self private + # rubocop:disable Naming/MethodParameterName def image_styles(f) styles = { original: { @@ -85,6 +86,7 @@ class PreviewCard < ApplicationRecord styles[:original][:format] = 'jpg' if f.instance.image_content_type == 'image/gif' styles end + # rubocop:enable Naming/MethodParameterName end private diff --git a/app/models/public_feed.rb b/app/models/public_feed.rb new file mode 100644 index 0000000000000000000000000000000000000000..c8ce1a1403bb0aa38dd5be11a6b17163e0fd96a6 --- /dev/null +++ b/app/models/public_feed.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +class PublicFeed < Feed + # @param [Account] account + # @param [Hash] options + # @option [Boolean] :with_replies + # @option [Boolean] :with_reblogs + # @option [Boolean] :local + # @option [Boolean] :remote + # @option [Boolean] :only_media + def initialize(account, options = {}) + @account = account + @options = options + end + + # @param [Integer] limit + # @param [Integer] max_id + # @param [Integer] since_id + # @param [Integer] min_id + # @return [Array<Status>] + def get(limit, max_id = nil, since_id = nil, min_id = nil) + scope = public_scope + + scope.merge!(without_replies_scope) unless with_replies? + scope.merge!(without_reblogs_scope) unless with_reblogs? + scope.merge!(local_only_scope) if local_only? + scope.merge!(remote_only_scope) if remote_only? + scope.merge!(account_filters_scope) if account? + scope.merge!(media_only_scope) if media_only? + + scope.cache_ids.to_a_paginated_by_id(limit, max_id: max_id, since_id: since_id, min_id: min_id) + end + + private + + def with_reblogs? + @options[:with_reblogs] + end + + def with_replies? + @options[:with_replies] + end + + def local_only? + @options[:local] + end + + def remote_only? + @options[:remote] + end + + def account? + @account.present? + end + + def media_only? + @options[:only_media] + end + + def public_scope + Status.with_public_visibility.joins(:account).merge(Account.without_suspended.without_silenced) + end + + def local_only_scope + Status.local + end + + def remote_only_scope + Status.remote + end + + def without_replies_scope + Status.without_replies + end + + def without_reblogs_scope + Status.without_reblogs + end + + def media_only_scope + Status.joins(:media_attachments).group(:id) + end + + def account_filters_scope + Status.not_excluded_by_account(@account).tap do |scope| + scope.merge!(Status.not_domain_blocked_by_account(@account)) unless local_only? + scope.merge!(Status.in_chosen_languages(@account)) if @account.chosen_languages.present? + end + end +end diff --git a/app/models/remote_follow.rb b/app/models/remote_follow.rb index 30b84f7d529574b8f6689014f80dadecaf911c6d..911c067133c35fe63a18cc789d497a495985ac6f 100644 --- a/app/models/remote_follow.rb +++ b/app/models/remote_follow.rb @@ -56,7 +56,7 @@ class RemoteFollow if domain.nil? @addressable_template = Addressable::Template.new("#{authorize_interaction_url}?uri={uri}") - elsif redirect_url_link.nil? || redirect_url_link.template.nil? + elsif redirect_uri_template.nil? missing_resource_error else @addressable_template = Addressable::Template.new(redirect_uri_template) @@ -64,16 +64,12 @@ class RemoteFollow end def redirect_uri_template - redirect_url_link.template - end - - def redirect_url_link - acct_resource&.link('http://ostatus.org/schema/1.0/subscribe') + acct_resource&.link('http://ostatus.org/schema/1.0/subscribe', 'template') end def acct_resource @acct_resource ||= webfinger!("acct:#{acct}") - rescue Goldfinger::Error, HTTP::ConnectionError + rescue Webfinger::Error, HTTP::ConnectionError nil end diff --git a/app/models/report.rb b/app/models/report.rb index f31bcfd2e92f146ff91dfd1369eb73706a872185..cd08120e4130a9272c89eadd189936405304607e 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -14,6 +14,7 @@ # target_account_id :bigint(8) not null # assigned_account_id :bigint(8) # uri :string +# forwarded :boolean # class Report < ApplicationRecord diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb index 34d25c83db29f02e1ccbb2ec9ef82ba6640ede70..b0ce9d112828961778c9656b359ef38d4530b03d 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -70,12 +70,16 @@ class SessionActivation < ApplicationRecord end def assign_access_token - superapp = Doorkeeper::Application.find_by(superapp: true) + self.access_token = Doorkeeper::AccessToken.create!(access_token_attributes) + end - self.access_token = Doorkeeper::AccessToken.create!(application_id: superapp&.id, - resource_owner_id: user_id, - scopes: 'read write follow', - expires_in: Doorkeeper.configuration.access_token_expires_in, - use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?) + def access_token_attributes + { + application_id: Doorkeeper::Application.find_by(superapp: true)&.id, + resource_owner_id: user_id, + scopes: 'read write follow', + expires_in: Doorkeeper.configuration.access_token_expires_in, + use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?, + } end end diff --git a/app/models/status.rb b/app/models/status.rb index 71596ec2f8a16c4a03f15f8569ad1fb252fa458c..b426f9d5bcc10b34afd6be671774eb2df483acfd 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -85,23 +85,23 @@ class Status < ApplicationRecord scope :recent, -> { reorder(id: :desc) } scope :remote, -> { where(local: false).where.not(uri: nil) } scope :local, -> { where(local: true).or(where(uri: nil)) } - scope :with_accounts, ->(ids) { where(id: ids).includes(:account) } scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') } scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') } scope :with_public_visibility, -> { where(visibility: :public) } - scope :tagged_with, ->(tag) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag }) } + scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) } + scope :in_chosen_languages, ->(account) { where(language: nil).or where(language: account.chosen_languages) } scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) } scope :including_silenced_accounts, -> { left_outer_joins(:account).where.not(accounts: { silenced_at: nil }) } scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) } scope :not_domain_blocked_by_account, ->(account) { account.excluded_from_timeline_domains.blank? ? left_outer_joins(:account) : left_outer_joins(:account).where('accounts.domain IS NULL OR accounts.domain NOT IN (?)', account.excluded_from_timeline_domains) } - scope :tagged_with_all, ->(tags) { - Array(tags).map(&:id).map(&:to_i).reduce(self) do |result, id| + scope :tagged_with_all, ->(tag_ids) { + Array(tag_ids).reduce(self) do |result, id| result.joins("INNER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}") end } - scope :tagged_with_none, ->(tags) { - Array(tags).map(&:id).map(&:to_i).reduce(self) do |result, id| + scope :tagged_with_none, ->(tag_ids) { + Array(tag_ids).reduce(self) do |result, id| result.joins("LEFT OUTER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}") .where("t#{id}.tag_id IS NULL") end @@ -228,14 +228,6 @@ class Status < ApplicationRecord @emojis = CustomEmoji.from_text(fields.join(' '), account.domain) end - def mark_for_mass_destruction! - @marked_for_mass_destruction = true - end - - def marked_for_mass_destruction? - @marked_for_mass_destruction - end - def replies_count status_stat&.replies_count || 0 end @@ -277,26 +269,6 @@ class Status < ApplicationRecord visibilities.keys - %w(direct limited) end - def in_chosen_languages(account) - where(language: nil).or where(language: account.chosen_languages) - end - - def as_public_timeline(account = nil, local_only = false) - query = timeline_scope(local_only).without_replies - - apply_timeline_filters(query, account, [:local, true].include?(local_only)) - end - - def as_tag_timeline(tag, account = nil, local_only = false) - query = timeline_scope(local_only).tagged_with(tag) - - apply_timeline_filters(query, account, local_only) - end - - def as_outbox_timeline(account) - where(account: account, visibility: :public) - end - def favourites_map(status_ids, account_id) Favourite.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |f, h| h[f.status_id] = true } end @@ -373,51 +345,6 @@ class Status < ApplicationRecord status&.distributable? ? status : nil end.compact end - - private - - def timeline_scope(scope = false) - starting_scope = case scope - when :local, true - Status.local - when :remote - Status.remote - else - Status - end - - starting_scope - .with_public_visibility - .without_reblogs - end - - def apply_timeline_filters(query, account, local_only) - if account.nil? - filter_timeline_default(query) - else - filter_timeline_for_account(query, account, local_only) - end - end - - def filter_timeline_for_account(query, account, local_only) - query = query.not_excluded_by_account(account) - query = query.not_domain_blocked_by_account(account) unless local_only - query = query.in_chosen_languages(account) if account.chosen_languages.present? - query.merge(account_silencing_filter(account)) - end - - def filter_timeline_default(query) - query.excluding_silenced_accounts - end - - def account_silencing_filter(account) - if account.silenced? - including_myself = left_outer_joins(:account).where(account_id: account.id).references(:accounts) - excluding_silenced_accounts.or(including_myself) - else - excluding_silenced_accounts - end - end end def status_stat @@ -495,7 +422,7 @@ class Status < ApplicationRecord end def decrement_counter_caches - return if direct_visibility? || marked_for_mass_destruction? + return if direct_visibility? account&.decrement_count!(:statuses_count) reblog&.decrement_count!(:reblogs_count) if reblog? @@ -505,7 +432,7 @@ class Status < ApplicationRecord def unlink_from_conversations return unless direct_visibility? - mentioned_accounts = mentions.includes(:account).map(&:account) + mentioned_accounts = (association(:mentions).loaded? ? mentions : mentions.includes(:account)).map(&:account) inbox_owners = mentioned_accounts.select(&:local?) + (account.local? ? [account] : []) inbox_owners.each do |inbox_owner| diff --git a/app/models/tag.rb b/app/models/tag.rb index bce76fc1667b43c8d700aa28c2928b21fcf94d64..bb93a52e2e56e6717a6b50c651a069e8367f50a6 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -39,7 +39,7 @@ class Tag < ApplicationRecord scope :listable, -> { where(listable: [true, nil]) } scope :trendable, -> { Setting.trendable_by_default ? where(trendable: [true, nil]) : where(trendable: true) } scope :discoverable, -> { listable.joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) } - scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) } + scope :recently_used, ->(account) { joins(:statuses).where(statuses: { id: account.statuses.select(:id).limit(1000) }).group(:id).order(Arel.sql('count(*) desc')) } scope :matches_name, ->(value) { where(arel_table[:name].matches("#{value}%")) } delegate :accounts_count, @@ -126,7 +126,7 @@ class Tag < ApplicationRecord end def search_for(term, limit = 5, offset = 0, options = {}) - normalized_term = normalize(term.strip).mb_chars.downcase.to_s + normalized_term = normalize(term.strip) pattern = sanitize_sql_like(normalized_term) + '%' query = Tag.listable.where(arel_table[:name].lower.matches(pattern)) query = query.where(arel_table[:name].lower.eq(normalized_term).or(arel_table[:reviewed_at].not_eq(nil))) if options[:exclude_unreviewed] diff --git a/app/models/tag_feed.rb b/app/models/tag_feed.rb new file mode 100644 index 0000000000000000000000000000000000000000..9a16ffc82b312123a1effa1b56f7f87db3845672 --- /dev/null +++ b/app/models/tag_feed.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +class TagFeed < PublicFeed + LIMIT_PER_MODE = 4 + + # @param [Tag] tag + # @param [Account] account + # @param [Hash] options + # @option [Enumerable<String>] :any + # @option [Enumerable<String>] :all + # @option [Enumerable<String>] :none + # @option [Boolean] :local + # @option [Boolean] :remote + # @option [Boolean] :only_media + def initialize(tag, account, options = {}) + @tag = tag + @account = account + @options = options + end + + # @param [Integer] limit + # @param [Integer] max_id + # @param [Integer] since_id + # @param [Integer] min_id + # @return [Array<Status>] + def get(limit, max_id = nil, since_id = nil, min_id = nil) + scope = public_scope + + scope.merge!(tagged_with_any_scope) + scope.merge!(tagged_with_all_scope) + scope.merge!(tagged_with_none_scope) + scope.merge!(local_only_scope) if local_only? + scope.merge!(remote_only_scope) if remote_only? + scope.merge!(account_filters_scope) if account? + scope.merge!(media_only_scope) if media_only? + + scope.cache_ids.to_a_paginated_by_id(limit, max_id: max_id, since_id: since_id, min_id: min_id) + end + + private + + def tagged_with_any_scope + Status.group(:id).tagged_with(tags_for(Array(@tag.name) | Array(@options[:any]))) + end + + def tagged_with_all_scope + Status.group(:id).tagged_with_all(tags_for(@options[:all])) + end + + def tagged_with_none_scope + Status.group(:id).tagged_with_none(tags_for(@options[:none])) + end + + def tags_for(names) + Tag.matching_name(Array(names).take(LIMIT_PER_MODE)).pluck(:id) if names.present? + end +end diff --git a/app/models/unavailable_domain.rb b/app/models/unavailable_domain.rb index e2918b5860472a263dfa3527ff027629cc0ec7d1..5e8870bde03049b84e328f3af81da4d2a6e5a6dd 100644 --- a/app/models/unavailable_domain.rb +++ b/app/models/unavailable_domain.rb @@ -12,6 +12,8 @@ class UnavailableDomain < ApplicationRecord include DomainNormalizable + validates :domain, presence: true, uniqueness: true + after_commit :reset_cache! private diff --git a/app/models/user.rb b/app/models/user.rb index 306e2d4355c771ab46c9852321d425f9cda95f4b..f8c8a6ab550c82f081e81fa6c52968c16dae113f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,6 +40,8 @@ # approved :boolean default(TRUE), not null # sign_in_token :string # sign_in_token_sent_at :datetime +# webauthn_id :string +# sign_up_ip :inet # class User < ApplicationRecord @@ -61,7 +63,7 @@ class User < ApplicationRecord devise :two_factor_backupable, otp_number_of_backup_codes: 10 - devise :registerable, :recoverable, :rememberable, :trackable, :validatable, + devise :registerable, :recoverable, :rememberable, :validatable, :confirmable include Omniauthable @@ -77,15 +79,24 @@ class User < ApplicationRecord has_many :backups, inverse_of: :user has_many :invites, inverse_of: :user has_many :markers, inverse_of: :user, dependent: :destroy + has_many :webauthn_credentials, dependent: :destroy has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy - accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? } + accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text } + validates :invite_request, presence: true, on: :create, if: :invite_text_required? validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale? validates_with BlacklistedEmailValidator, on: :create validates_with EmailMxValidator, if: :validate_email_dns? validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create + # Those are honeypot/antispam fields + attr_accessor :registration_form_time, :website, :confirm_password + + validates_with RegistrationFormTimeValidator, on: :create + validates :website, absence: true, on: :create + validates :confirm_password, absence: true, on: :create + scope :recent, -> { order(id: :desc) } scope :pending, -> { where(approved: false) } scope :approved, -> { where(approved: true) } @@ -95,7 +106,7 @@ class User < ApplicationRecord scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) } scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended_at: nil }) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } - scope :matches_ip, ->(value) { left_joins(:session_activations).where('users.current_sign_in_ip <<= ?', value).or(left_joins(:session_activations).where('users.last_sign_in_ip <<= ?', value)).or(left_joins(:session_activations).where('session_activations.ip <<= ?', value)) } + scope :matches_ip, ->(value) { left_joins(:session_activations).where('users.current_sign_in_ip <<= ?', value).or(left_joins(:session_activations).where('users.sign_up_ip <<= ?', value)).or(left_joins(:session_activations).where('users.last_sign_in_ip <<= ?', value)).or(left_joins(:session_activations).where('session_activations.ip <<= ?', value)) } scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) } before_validation :sanitize_languages @@ -113,10 +124,11 @@ class User < ApplicationRecord :reduce_motion, :system_font_ui, :noindex, :theme, :display_media, :hide_network, :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images, + :disable_swiping, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code, :sign_in_token_attempt - attr_writer :external + attr_writer :external, :bypass_invite_request_check def confirmed? confirmed_at.present? @@ -161,12 +173,30 @@ class User < ApplicationRecord prepare_new_user! if new_user && approved? end + def update_sign_in!(request, new_sign_in: false) + old_current, new_current = current_sign_in_at, Time.now.utc + self.last_sign_in_at = old_current || new_current + self.current_sign_in_at = new_current + + old_current, new_current = current_sign_in_ip, request.remote_ip + self.last_sign_in_ip = old_current || new_current + self.current_sign_in_ip = new_current + + if new_sign_in + self.sign_in_count ||= 0 + self.sign_in_count += 1 + end + + save(validate: false) unless new_record? + prepare_returning_user! + end + def pending? !approved? end def active_for_authentication? - true + !account.memorial? end def suspicious_sign_in?(ip) @@ -174,7 +204,7 @@ class User < ApplicationRecord end def functional? - confirmed? && approved? && !disabled? && !account.suspended? && account.moved_to_account_id.nil? + confirmed? && approved? && !disabled? && !account.suspended? && !account.memorial? && account.moved_to_account_id.nil? end def unconfirmed_or_pending? @@ -192,14 +222,25 @@ class User < ApplicationRecord prepare_new_user! end - def update_tracked_fields!(request) - super - prepare_returning_user! + def otp_enabled? + otp_required_for_login + end + + def webauthn_enabled? + webauthn_credentials.any? + end + + def two_factor_enabled? + otp_required_for_login? || webauthn_credentials.any? end def disable_two_factor! self.otp_required_for_login = false + self.otp_secret = nil otp_backup_codes&.clear + + webauthn_credentials.destroy_all if webauthn_enabled? + save! end @@ -235,16 +276,16 @@ class User < ApplicationRecord @shows_application ||= settings.show_application end + # rubocop:disable Naming/MethodParameterName def token_for_app(a) return nil if a.nil? || a.owner != self - Doorkeeper::AccessToken - .find_or_create_by(application_id: a.id, resource_owner_id: id) do |t| - + Doorkeeper::AccessToken.find_or_create_by(application_id: a.id, resource_owner_id: id) do |t| t.scopes = a.scopes t.expires_in = Doorkeeper.configuration.access_token_expires_in t.use_refresh_token = Doorkeeper.configuration.refresh_token_enabled? end end + # rubocop:enable Naming/MethodParameterName def activate_session(request) session_activations.activate(session_id: SecureRandom.hex, @@ -312,6 +353,7 @@ class User < ApplicationRecord arr << [current_sign_in_at, current_sign_in_ip] if current_sign_in_ip.present? arr << [last_sign_in_at, last_sign_in_ip] if last_sign_in_ip.present? + arr << [created_at, sign_up_ip] if sign_up_ip.present? arr.sort_by { |pair| pair.first || Time.now.utc }.uniq(&:last).reverse! end @@ -366,7 +408,17 @@ class User < ApplicationRecord end def set_approved - self.approved = open_registrations? || valid_invitation? || external? + self.approved = begin + if sign_up_from_ip_requires_approval? + false + else + open_registrations? || valid_invitation? || external? + end + end + end + + def sign_up_from_ip_requires_approval? + !sign_up_ip.nil? && IpBlock.where(severity: :sign_up_requires_approval).where('ip >>= ?', sign_up_ip.to_s).exists? end def open_registrations? @@ -377,6 +429,10 @@ class User < ApplicationRecord !!@external end + def bypass_invite_request_check? + @bypass_invite_request_check + end + def sanitize_languages return if chosen_languages.nil? chosen_languages.reject!(&:blank?) @@ -395,7 +451,7 @@ class User < ApplicationRecord end def notify_staff_about_pending_account! - User.staff.includes(:account).each do |u| + User.staff.includes(:account).find_each do |u| next unless u.allows_pending_account_emails? AdminMailer.new_pending_account(u.account, self).deliver_later end @@ -414,4 +470,8 @@ class User < ApplicationRecord def validate_email_dns? email_changed? && !(Rails.env.test? || Rails.env.development?) end + + def invite_text_required? + Setting.require_invite_text && !invited? && !external? && !bypass_invite_request_check? + end end diff --git a/app/models/webauthn_credential.rb b/app/models/webauthn_credential.rb new file mode 100644 index 0000000000000000000000000000000000000000..7d423e38d71f59949ea8f959db36a71dd44fa571 --- /dev/null +++ b/app/models/webauthn_credential.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: webauthn_credentials +# +# id :bigint(8) not null, primary key +# external_id :string not null +# public_key :string not null +# nickname :string not null +# sign_count :bigint(8) default(0), not null +# user_id :bigint(8) +# created_at :datetime not null +# updated_at :datetime not null +# + +class WebauthnCredential < ApplicationRecord + validates :external_id, :public_key, :nickname, :sign_count, presence: true + validates :external_id, uniqueness: true + validates :nickname, uniqueness: { scope: :user_id } + validates :sign_count, + numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 2**63 - 1 } +end diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb index 9c145979d6c2c076577a2359139e457d1164e8e5..672e1786bfd7bb0cdc512b705b9fd7dcd3c45faa 100644 --- a/app/policies/account_policy.rb +++ b/app/policies/account_policy.rb @@ -14,10 +14,22 @@ class AccountPolicy < ApplicationPolicy end def suspend? - staff? && !record.user&.staff? + staff? && !record.user&.staff? && !record.instance_actor? + end + + def destroy? + record.suspended_temporarily? && admin? end def unsuspend? + staff? && record.suspension_origin_local? + end + + def sensitive? + staff? && !record.user&.staff? + end + + def unsensitive? staff? end @@ -50,6 +62,6 @@ class AccountPolicy < ApplicationPolicy end def memorialize? - admin? && !record.user&.admin? + admin? && !record.user&.admin? && !record.instance_actor? end end diff --git a/app/policies/domain_block_policy.rb b/app/policies/domain_block_policy.rb index 47c0a81af44f923bff704873ca9964755d614154..543259ccef8681e2bd6bf0b4c0596119adf8ba6d 100644 --- a/app/policies/domain_block_policy.rb +++ b/app/policies/domain_block_policy.rb @@ -13,6 +13,10 @@ class DomainBlockPolicy < ApplicationPolicy admin? end + def update? + admin? + end + def destroy? admin? end diff --git a/app/policies/ip_block_policy.rb b/app/policies/ip_block_policy.rb new file mode 100644 index 0000000000000000000000000000000000000000..34dbd746a33f35fde066738f03b9e76748c468a9 --- /dev/null +++ b/app/policies/ip_block_policy.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class IpBlockPolicy < ApplicationPolicy + def index? + admin? + end + + def create? + admin? + end + + def destroy? + admin? + end +end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 3d4e50d3719730cc65540f58180a103fc3a284f9..bcf9c3395ca974291ad738c45fcae14f05702bce 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -12,6 +12,8 @@ class StatusPolicy < ApplicationPolicy end def show? + return false if author.suspended? + if requires_mention? owned? || mention_exists? elsif private? diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb index c150bf742be5799816de757aa6d0795326dddaff..1bfdd40ac9d3c1b712e0b2e8f9fa31f7f0014ca4 100644 --- a/app/presenters/instance_presenter.rb +++ b/app/presenters/instance_presenter.rb @@ -29,7 +29,7 @@ class InstancePresenter end def domain_count - Rails.cache.fetch('distinct_domain_count') { Account.distinct.count(:domain) } + Rails.cache.fetch('distinct_domain_count') { Instance.count } end def sample_accounts diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 627d4446b9919d45ae6379153a2e2458724e2901..759ef30f91bb5dbe94dfb672a6c99a95882c6ce0 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -7,10 +7,10 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer context_extensions :manually_approves_followers, :featured, :also_known_as, :moved_to, :property_value, :identity_proof, - :discoverable, :olm + :discoverable, :olm, :suspended attributes :id, :type, :following, :followers, - :inbox, :outbox, :featured, + :inbox, :outbox, :featured, :featured_tags, :preferred_username, :name, :summary, :url, :manually_approves_followers, :discoverable @@ -23,6 +23,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer attribute :devices, unless: :instance_actor? attribute :moved_to, if: :moved? attribute :also_known_as, if: :also_known_as? + attribute :suspended, if: :suspended? class EndpointsSerializer < ActivityPub::Serializer include RoutingHelper @@ -39,7 +40,7 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer has_one :icon, serializer: ActivityPub::ImageSerializer, if: :avatar_exists? has_one :image, serializer: ActivityPub::ImageSerializer, if: :header_exists? - delegate :moved?, :instance_actor?, to: :object + delegate :suspended?, :instance_actor?, to: :object def id object.instance_actor? ? instance_actor_url : account_url(object) @@ -74,13 +75,17 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer end def outbox - account_outbox_url(object) + object.instance_actor? ? instance_actor_outbox_url : account_outbox_url(object) end def featured account_collection_url(object, :featured) end + def featured_tags + account_collection_url(object, :tags) + end + def endpoints object end @@ -89,12 +94,16 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer object.username end + def discoverable + object.suspended? ? false : (object.discoverable || false) + end + def name - object.display_name + object.suspended? ? '' : object.display_name end def summary - Formatter.instance.simplified_format(object) + object.suspended? ? '' : Formatter.instance.simplified_format(object) end def icon @@ -109,36 +118,44 @@ class ActivityPub::ActorSerializer < ActivityPub::Serializer object end + def suspended + object.suspended? + end + def url object.instance_actor? ? about_more_url(instance_actor: true) : short_account_url(object) end def avatar_exists? - object.avatar? + !object.suspended? && object.avatar? end def header_exists? - object.header? + !object.suspended? && object.header? end def manually_approves_followers - object.locked + object.suspended? ? false : object.locked end def virtual_tags - object.emojis + object.tags + object.suspended? ? [] : (object.emojis + object.tags) end def virtual_attachments - object.fields + object.identity_proofs.active + object.suspended? ? [] : (object.fields + object.identity_proofs.active) end def moved_to ActivityPub::TagManager.instance.uri_for(object.moved_to_account) end + def moved? + !object.suspended? && object.moved? + end + def also_known_as? - !object.also_known_as.empty? + !object.suspended? && !object.also_known_as.empty? end class CustomEmojiSerializer < ActivityPub::EmojiSerializer diff --git a/app/serializers/activitypub/collection_serializer.rb b/app/serializers/activitypub/collection_serializer.rb index ea7af543320dca3b74b0e38185e35e534dfa4d27..34026a6b5be01d6475c490b541ea3e54c5a858d9 100644 --- a/app/serializers/activitypub/collection_serializer.rb +++ b/app/serializers/activitypub/collection_serializer.rb @@ -16,6 +16,8 @@ class ActivityPub::CollectionSerializer < ActivityPub::Serializer ActivityPub::NoteSerializer when 'Device' ActivityPub::DeviceSerializer + when 'FeaturedTag' + ActivityPub::HashtagSerializer when 'ActivityPub::CollectionPresenter' ActivityPub::CollectionSerializer when 'String' diff --git a/app/serializers/activitypub/hashtag_serializer.rb b/app/serializers/activitypub/hashtag_serializer.rb new file mode 100644 index 0000000000000000000000000000000000000000..1a56e4dfe4c745f375bacb3b6001d7b6d8d95291 --- /dev/null +++ b/app/serializers/activitypub/hashtag_serializer.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ActivityPub::HashtagSerializer < ActivityPub::Serializer + include RoutingHelper + + attributes :type, :href, :name + + def type + 'Hashtag' + end + + def name + "##{object.name}" + end + + def href + if object.class.name == 'FeaturedTag' + short_account_tag_url(object.account, object.tag) + else + tag_url(object) + end + end +end diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index f26fd93a424f1ecb30f10f0e11ebbe880080b528..6f9e1ca639183282d9bfb0daa5a3365da1b339f7 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -95,6 +95,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer ActivityPub::TagManager.instance.cc(object) end + def sensitive + object.account.sensitized? || object.sensitive + end + def virtual_tags object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis end diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 2939004efeb7484a3b322d88d29e1263a82ea022..70263e0c5768c257912c28da71f21e43b6a1441e 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -33,6 +33,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:display_media] = object.current_account.user.setting_display_media store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers store[:reduce_motion] = object.current_account.user.setting_reduce_motion + store[:disable_swiping] = object.current_account.user.setting_disable_swiping store[:advanced_layout] = object.current_account.user.setting_advanced_layout store[:use_blurhash] = object.current_account.user.setting_use_blurhash store[:use_pending_items] = object.current_account.user.setting_use_pending_items diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb index 21ec0d4bed2f96f38b9ec58f1f6dc4950a6413fc..dafe8f55b9e8e42f32e07bc92f421f44370832f6 100644 --- a/app/serializers/manifest_serializer.rb +++ b/app/serializers/manifest_serializer.rb @@ -7,7 +7,7 @@ class ManifestSerializer < ActiveModel::Serializer attributes :name, :short_name, :description, :icons, :theme_color, :background_color, :display, :start_url, :scope, - :share_target + :share_target, :shortcuts def name object.site_title @@ -64,4 +64,42 @@ class ManifestSerializer < ActiveModel::Serializer }, } end + + def shortcuts + [ + { + name: 'New toot', + url: '/web/statuses/new', + icons: [ + { + src: '/shortcuts/new-status.png', + type: 'image/png', + sizes: '192x192', + }, + ], + }, + { + name: 'Notifications', + url: '/web/notifications', + icons: [ + { + src: '/shortcuts/notifications.png', + type: 'image/png', + sizes: '192x192', + }, + ], + }, + { + name: 'Direct messages', + url: '/web/timelines/direct', + icons: [ + { + src: '/shortcuts/direct.png', + type: 'image/png', + sizes: '192x192', + }, + ], + }, + ] + end end diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 0db1916b0740640cf0ef64eb155da9ab2d5579e6..189a62d0eec82b5395687117f5501cde8a085fd6 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -8,8 +8,11 @@ class REST::AccountSerializer < ActiveModel::Serializer :followers_count, :following_count, :statuses_count, :last_status_at has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested? + has_many :emojis, serializer: REST::CustomEmojiSerializer + attribute :suspended, if: :suspended? + class FieldSerializer < ActiveModel::Serializer attributes :name, :value, :verified_at @@ -29,7 +32,7 @@ class REST::AccountSerializer < ActiveModel::Serializer end def note - Formatter.instance.simplified_format(object) + object.suspended? ? '' : Formatter.instance.simplified_format(object) end def url @@ -37,26 +40,60 @@ class REST::AccountSerializer < ActiveModel::Serializer end def avatar - full_asset_url(object.avatar_original_url) + full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_original_url) end def avatar_static - full_asset_url(object.avatar_static_url) + full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_static_url) end def header - full_asset_url(object.header_original_url) + full_asset_url(object.suspended? ? object.header.default_url : object.header_original_url) end def header_static - full_asset_url(object.header_static_url) - end - - def moved_and_not_nested? - object.moved? && object.moved_to_account.moved_to_account_id.nil? + full_asset_url(object.suspended? ? object.header.default_url : object.header_static_url) end def last_status_at object.last_status_at&.to_date&.iso8601 end + + def display_name + object.suspended? ? '' : object.display_name + end + + def locked + object.suspended? ? false : object.locked + end + + def bot + object.suspended? ? false : object.bot + end + + def discoverable + object.suspended? ? false : object.discoverable + end + + def moved_to_account + object.suspended? ? nil : object.moved_to_account + end + + def emojis + object.suspended? ? [] : object.emojis + end + + def fields + object.suspended? ? [] : object.fields + end + + def suspended + object.suspended? + end + + delegate :suspended?, to: :object + + def moved_and_not_nested? + object.moved? && object.moved_to_account.moved_to_account_id.nil? + end end diff --git a/app/serializers/rest/featured_tag_serializer.rb b/app/serializers/rest/featured_tag_serializer.rb index 08121ff16db2be23bcb352b5a4f4cfc129eb74a0..96adcc7d09345a0405adf9eaf5b795f3e858aea7 100644 --- a/app/serializers/rest/featured_tag_serializer.rb +++ b/app/serializers/rest/featured_tag_serializer.rb @@ -1,9 +1,15 @@ # frozen_string_literal: true class REST::FeaturedTagSerializer < ActiveModel::Serializer - attributes :id, :name, :statuses_count, :last_status_at + include RoutingHelper + + attributes :id, :name, :url, :statuses_count, :last_status_at def id object.id.to_s end + + def url + short_account_tag_url(object.account, object.tag) + end end diff --git a/app/serializers/rest/list_serializer.rb b/app/serializers/rest/list_serializer.rb index 977da7439acb9f54844dacc90a1572451afc3bb3..3e87f711961279f4fe2f8ebc49631b49d290699c 100644 --- a/app/serializers/rest/list_serializer.rb +++ b/app/serializers/rest/list_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::ListSerializer < ActiveModel::Serializer - attributes :id, :title + attributes :id, :title, :replies_policy def id object.id.to_s diff --git a/app/serializers/rest/media_attachment_serializer.rb b/app/serializers/rest/media_attachment_serializer.rb index e65f7acf1a9e607d5aeba71379616b7845befdc2..a24f953152f4a811b47e400341a6f37c9f33c4ea 100644 --- a/app/serializers/rest/media_attachment_serializer.rb +++ b/app/serializers/rest/media_attachment_serializer.rb @@ -4,7 +4,7 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer include RoutingHelper attributes :id, :type, :url, :preview_url, - :remote_url, :text_url, :meta, + :remote_url, :preview_remote_url, :text_url, :meta, :description, :blurhash def id @@ -35,6 +35,10 @@ class REST::MediaAttachmentSerializer < ActiveModel::Serializer end end + def preview_remote_url + object.thumbnail_remote_url.presence + end + def text_url object.local? ? medium_url(object) : nil end diff --git a/app/serializers/rest/muted_account_serializer.rb b/app/serializers/rest/muted_account_serializer.rb new file mode 100644 index 0000000000000000000000000000000000000000..3ddd706dcd327b0f28c81f878e052745c442ecb8 --- /dev/null +++ b/app/serializers/rest/muted_account_serializer.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class REST::MutedAccountSerializer < REST::AccountSerializer + attribute :mute_expires_at + + def mute_expires_at + mute = current_user.account.mute_relationships.find_by(target_account_id: object.id) + mute && !mute.expired? ? mute.expires_at : nil + end +end diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 80812ad0df9cd5d8f740ff78d8d28287b84c10c8..27b031fcc77a1603b617faca6745550b43216129 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -11,6 +11,6 @@ class REST::NotificationSerializer < ActiveModel::Serializer end def status_type? - [:favourite, :reblog, :mention, :poll].include?(object.type) + [:favourite, :reblog, :status, :mention, :poll].include?(object.type) end end diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb index c2f3c9a112642113eed01025d5b08caf01792dbf..afd4cddf9b5718aba504ed5dbdb18cdbf5b32bb1 100644 --- a/app/serializers/rest/relationship_serializer.rb +++ b/app/serializers/rest/relationship_serializer.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true class REST::RelationshipSerializer < ActiveModel::Serializer - attributes :id, :following, :showing_reblogs, :followed_by, :blocking, :blocked_by, - :muting, :muting_notifications, :requested, :domain_blocking, - :endorsed, :note + attributes :id, :following, :showing_reblogs, :notifying, :followed_by, + :blocking, :blocked_by, :muting, :muting_notifications, :requested, + :domain_blocking, :endorsed, :note def id object.id.to_s @@ -19,6 +19,12 @@ class REST::RelationshipSerializer < ActiveModel::Serializer false end + def notifying + (instance_options[:relationships].following[object.id] || {})[:notify] || + (instance_options[:relationships].requested[object.id] || {})[:notify] || + false + end + def followed_by instance_options[:relationships].followed_by[object.id] || false end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 0109de882bdc0021fdbeb9b9c86bd3b41981d602..bb6df90b7a61f53342506f92b7dd945177e940e2 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -58,6 +58,14 @@ class REST::StatusSerializer < ActiveModel::Serializer end end + def sensitive + if current_user? && current_user.account_id == object.account_id + object.sensitive + else + object.account.sensitized? || object.sensitive + end + end + def uri ActivityPub::TagManager.instance.uri_for(object) end diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index 493813aab4e1c6b465da3a344a6fd17aee169636..43e59604055342a684d908b3810dd229a912a99c 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -27,7 +27,7 @@ class AccountSearchService < BaseService return @exact_match if defined?(@exact_match) - @exact_match = begin + match = begin if options[:resolve] ResolveAccountService.new.call(query) elsif domain_is_local? @@ -36,6 +36,10 @@ class AccountSearchService < BaseService Account.find_remote(query_username, query_domain) end end + + match = nil if !match.nil? && !account.nil? && options[:following] && !account.following?(match) + + @exact_match = match end def search_results diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb index 83fbf6d07d32bd155883406d69e886792499e0c3..9d01f538687ed2d6d20d1c8b1c3f0a35771802e4 100644 --- a/app/services/activitypub/fetch_remote_account_service.rb +++ b/app/services/activitypub/fetch_remote_account_service.rb @@ -28,7 +28,7 @@ class ActivityPub::FetchRemoteAccountService < BaseService return unless only_key || verified_webfinger? - ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key) + ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key) rescue Oj::ParseError nil end @@ -39,17 +39,16 @@ class ActivityPub::FetchRemoteAccountService < BaseService webfinger = webfinger!("acct:#{@username}@#{@domain}") confirmed_username, confirmed_domain = split_acct(webfinger.subject) - return webfinger.link('self')&.href == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? + return webfinger.link('self', 'href') == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") @username, @domain = split_acct(webfinger.subject) - self_reference = webfinger.link('self') return false unless @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? - return false if self_reference&.href != @uri + return false if webfinger.link('self', 'href') != @uri true - rescue Goldfinger::Error + rescue Webfinger::Error false end diff --git a/app/services/activitypub/prepare_followers_synchronization_service.rb b/app/services/activitypub/prepare_followers_synchronization_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..2d22ed701e8722f8beef2f407d8e8d9b6661d517 --- /dev/null +++ b/app/services/activitypub/prepare_followers_synchronization_service.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ActivityPub::PrepareFollowersSynchronizationService < BaseService + include JsonLdHelper + + def call(account, params) + @account = account + + return if params['collectionId'] != @account.followers_url || invalid_origin?(params['url']) || @account.local_followers_hash == params['digest'] + + ActivityPub::FollowersSynchronizationWorker.perform_async(@account.id, params['url']) + end +end diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 85b915ec6752f4a5e298bf3ff1b4589e232f88fd..6afeb92d62612c393152ee59ac3ad66f79295fa8 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -18,15 +18,18 @@ class ActivityPub::ProcessAccountService < BaseService RedisLock.acquire(lock_options) do |lock| if lock.acquired? - @account = Account.remote.find_by(uri: @uri) if @options[:only_key] - @account ||= Account.find_remote(@username, @domain) - @old_public_key = @account&.public_key - @old_protocol = @account&.protocol + @account = Account.remote.find_by(uri: @uri) if @options[:only_key] + @account ||= Account.find_remote(@username, @domain) + @old_public_key = @account&.public_key + @old_protocol = @account&.protocol + @suspension_changed = false create_account if @account.nil? update_account process_tags process_attachments + + process_duplicate_accounts! if @options[:verified_webfinger] else raise Mastodon::RaceConditionError end @@ -37,8 +40,9 @@ class ActivityPub::ProcessAccountService < BaseService after_protocol_change! if protocol_changed? after_key_change! if key_changed? && !@options[:signed_with_known_key] clear_tombstones! if key_changed? + after_suspension_change! if suspension_changed? - unless @options[:only_key] + unless @options[:only_key] || @account.suspended? check_featured_collection! if @account.featured_collection_url.present? check_links! unless @account.fields.empty? end @@ -52,46 +56,57 @@ class ActivityPub::ProcessAccountService < BaseService def create_account @account = Account.new - @account.protocol = :activitypub - @account.username = @username - @account.domain = @domain - @account.private_key = nil - @account.suspended_at = domain_block.created_at if auto_suspend? - @account.silenced_at = domain_block.created_at if auto_silence? + @account.protocol = :activitypub + @account.username = @username + @account.domain = @domain + @account.private_key = nil + @account.suspended_at = domain_block.created_at if auto_suspend? + @account.suspension_origin = :local if auto_suspend? + @account.silenced_at = domain_block.created_at if auto_silence? + @account.save end def update_account @account.last_webfingered_at = Time.now.utc unless @options[:only_key] @account.protocol = :activitypub - set_immediate_attributes! - set_fetchable_attributes! unless @options[:only_keys] + set_suspension! + set_immediate_protocol_attributes! + set_fetchable_key! unless @account.suspended? && @account.suspension_origin_local? + set_immediate_attributes! unless @account.suspended? + set_fetchable_attributes! unless @options[:only_key] || @account.suspended? @account.save_with_optional_media! end - def set_immediate_attributes! + def set_immediate_protocol_attributes! @account.inbox_url = @json['inbox'] || '' @account.outbox_url = @json['outbox'] || '' @account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || '' @account.followers_url = @json['followers'] || '' - @account.featured_collection_url = @json['featured'] || '' - @account.devices_url = @json['devices'] || '' @account.url = url || @uri @account.uri = @uri + @account.actor_type = actor_type + end + + def set_immediate_attributes! + @account.featured_collection_url = @json['featured'] || '' + @account.devices_url = @json['devices'] || '' @account.display_name = @json['name'] || '' @account.note = @json['summary'] || '' @account.locked = @json['manuallyApprovesFollowers'] || false @account.fields = property_values || {} @account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) } - @account.actor_type = actor_type @account.discoverable = @json['discoverable'] || false end + def set_fetchable_key! + @account.public_key = public_key || '' + end + def set_fetchable_attributes! @account.avatar_remote_url = image_url('icon') || '' unless skip_download? @account.header_remote_url = image_url('image') || '' unless skip_download? - @account.public_key = public_key || '' @account.statuses_count = outbox_total_items if outbox_total_items.present? @account.following_count = following_total_items if following_total_items.present? @account.followers_count = followers_total_items if followers_total_items.present? @@ -99,6 +114,18 @@ class ActivityPub::ProcessAccountService < BaseService @account.moved_to_account = @json['movedTo'].present? ? moved_account : nil end + def set_suspension! + return if @account.suspended? && @account.suspension_origin_local? + + if @account.suspended? && !@json['suspended'] + @account.unsuspend! + @suspension_changed = true + elsif !@account.suspended? && @json['suspended'] + @account.suspend!(origin: :remote) + @suspension_changed = true + end + end + def after_protocol_change! ActivityPub::PostUpgradeWorker.perform_async(@account.domain) end @@ -107,6 +134,14 @@ class ActivityPub::ProcessAccountService < BaseService RefollowWorker.perform_async(@account.id) end + def after_suspension_change! + if @account.suspended? + Admin::SuspensionWorker.perform_async(@account.id) + else + Admin::UnsuspensionWorker.perform_async(@account.id) + end + end + def check_featured_collection! ActivityPub::SynchronizeFeaturedCollectionWorker.perform_async(@account.id) end @@ -115,6 +150,12 @@ class ActivityPub::ProcessAccountService < BaseService VerifyAccountLinksWorker.perform_async(@account.id) end + def process_duplicate_accounts! + return unless Account.where(uri: @account.uri).where.not(id: @account.id).exists? + + AccountMergingWorker.perform_async(@account.id) + end + def actor_type if @json['type'].is_a?(Array) @json['type'].find { |type| ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(type) } @@ -196,7 +237,7 @@ class ActivityPub::ProcessAccountService < BaseService total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil has_first_page = collection.is_a?(Hash) && collection['first'].present? @collections[type] = [total_items, has_first_page] - rescue HTTP::Error, OpenSSL::SSL::SSLError + rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::LengthValidationError @collections[type] = [nil, nil] end @@ -227,6 +268,10 @@ class ActivityPub::ProcessAccountService < BaseService !@old_public_key.nil? && @old_public_key != @account.public_key end + def suspension_changed? + @suspension_changed + end + def clear_tombstones! Tombstone.where(account_id: @account.id).delete_all end diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index e6ccaccc90f3e61cbdf27ab095c59e82330e7213..f1d175dacc1996043ba0513dc97f2161c545e2c8 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -8,7 +8,7 @@ class ActivityPub::ProcessCollectionService < BaseService @json = Oj.load(body, mode: :strict) @options = options - return if !supported_context? || (different_actor? && verify_account!.nil?) || @account.suspended? || @account.local? + return if !supported_context? || (different_actor? && verify_account!.nil?) || suspended_actor? || @account.local? case @json['type'] when 'Collection', 'CollectionPage' @@ -28,6 +28,14 @@ class ActivityPub::ProcessCollectionService < BaseService @json['actor'].present? && value_or_id(@json['actor']) != @account.uri end + def suspended_actor? + @account.suspended? && !activity_allowed_while_suspended? + end + + def activity_allowed_while_suspended? + %w(Delete Reject Undo Update).include?(@json['type']) + end + def process_items(items) items.reverse_each.map { |item| process_item(item) }.compact end diff --git a/app/services/activitypub/synchronize_followers_service.rb b/app/services/activitypub/synchronize_followers_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..d83fcf55e665c9a6b9ccb3a937dfc12ccd17b529 --- /dev/null +++ b/app/services/activitypub/synchronize_followers_service.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +class ActivityPub::SynchronizeFollowersService < BaseService + include JsonLdHelper + include Payloadable + + def call(account, partial_collection_url) + @account = account + + items = collection_items(partial_collection_url) + return if items.nil? + + # There could be unresolved accounts (hence the call to .compact) but this + # should never happen in practice, since in almost all cases we keep an + # Account record, and should we not do that, we should have sent a Delete. + # In any case there is not much we can do if that occurs. + @expected_followers = items.map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }.compact + + remove_unexpected_local_followers! + handle_unexpected_outgoing_follows! + end + + private + + def remove_unexpected_local_followers! + @account.followers.local.where.not(id: @expected_followers.map(&:id)).each do |unexpected_follower| + UnfollowService.new.call(unexpected_follower, @account) + end + end + + def handle_unexpected_outgoing_follows! + @expected_followers.each do |expected_follower| + next if expected_follower.following?(@account) + + if expected_follower.requested?(@account) + # For some reason the follow request went through but we missed it + expected_follower.follow_requests.find_by(target_account: @account)&.authorize! + else + # Since we were not aware of the follow from our side, we do not have an + # ID for it that we can include in the Undo activity. For this reason, + # the Undo may not work with software that relies exclusively on + # matching activity IDs and not the actor and target + follow = Follow.new(account: expected_follower, target_account: @account) + ActivityPub::DeliveryWorker.perform_async(build_undo_follow_json(follow), follow.account_id, follow.target_account.inbox_url) + end + end + end + + def build_undo_follow_json(follow) + Oj.dump(serialize_payload(follow, ActivityPub::UndoFollowSerializer)) + end + + def collection_items(collection_or_uri) + collection = fetch_collection(collection_or_uri) + return unless collection.is_a?(Hash) + + collection = fetch_collection(collection['first']) if collection['first'].present? + return unless collection.is_a?(Hash) + + case collection['type'] + when 'Collection', 'CollectionPage' + collection['items'] + when 'OrderedCollection', 'OrderedCollectionPage' + collection['orderedItems'] + end + end + + def fetch_collection(collection_or_uri) + return collection_or_uri if collection_or_uri.is_a?(Hash) + return if invalid_origin?(collection_or_uri) + + fetch_resource_without_id_validation(collection_or_uri, nil, true) + end +end diff --git a/app/services/after_block_service.rb b/app/services/after_block_service.rb index 2a0e10a79a60e294edb490ed928b58e6541e3908..314919df8851145341e42e8225d1362500859b1a 100644 --- a/app/services/after_block_service.rb +++ b/app/services/after_block_service.rb @@ -13,7 +13,7 @@ class AfterBlockService < BaseService private def clear_home_feed! - FeedManager.instance.clear_from_timeline(@account, @target_account) + FeedManager.instance.clear_from_home(@account, @target_account) end def clear_conversations! diff --git a/app/services/after_unallow_domain_service.rb b/app/services/after_unallow_domain_service.rb index ccd0b8ae919f653ce0c8f51d0721f3b6cd8af756..d3008a1052f0186f3821c89fc11036bb43437657 100644 --- a/app/services/after_unallow_domain_service.rb +++ b/app/services/after_unallow_domain_service.rb @@ -3,7 +3,7 @@ class AfterUnallowDomainService < BaseService def call(domain) Account.where(domain: domain).find_each do |account| - SuspendAccountService.new.call(account, reserve_username: false) + DeleteAccountService.new.call(account, reserve_username: false) end end end diff --git a/app/services/app_sign_up_service.rb b/app/services/app_sign_up_service.rb index c9739c77d194796e738057d8856fc4421f2c01af..e006941577228e4ff1fe8979e5e8d24f15217b00 100644 --- a/app/services/app_sign_up_service.rb +++ b/app/services/app_sign_up_service.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true class AppSignUpService < BaseService - def call(app, params) + def call(app, remote_ip, params) return unless allowed_registrations? user_params = params.slice(:email, :password, :agreement, :locale) account_params = params.slice(:username) invite_request_params = { text: params[:reason] } - user = User.create!(user_params.merge(created_by_application: app, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params)) + user = User.create!(user_params.merge(created_by_application: app, sign_up_ip: remote_ip, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params)) Doorkeeper::AccessToken.create!(application: app, resource_owner_id: user.id, diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index 2295a01dc3d613bf2499af71d6672c8b64bbfa1d..b54bcae3504d8f976e279d3e747db6725045151c 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -3,32 +3,40 @@ class BatchedRemoveStatusService < BaseService include Redisable - # Delete given statuses and reblogs of them - # Dispatch PuSH updates of the deleted statuses, but only local ones - # Dispatch Salmon deletes, unique per domain, of the deleted statuses, but only local ones - # Remove statuses from home feeds - # Push delete events to streaming API for home feeds and public feeds - # @param [Enumerable<Status>] statuses A preferably batched array of statuses + # Delete multiple statuses and reblogs of them as efficiently as possible + # @param [Enumerable<Status>] statuses An array of statuses # @param [Hash] options - # @option [Boolean] :skip_side_effects + # @option [Boolean] :skip_side_effects Do not modify feeds and send updates to streaming API def call(statuses, **options) - statuses = Status.where(id: statuses.map(&:id)).includes(:account).flat_map { |status| [status] + status.reblogs.includes(:account).to_a } + ActiveRecord::Associations::Preloader.new.preload(statuses, options[:skip_side_effects] ? :reblogs : [:account, :tags, reblogs: :account]) - @mentions = statuses.each_with_object({}) { |s, h| h[s.id] = s.active_mentions.includes(:account).to_a } - @tags = statuses.each_with_object({}) { |s, h| h[s.id] = s.tags.pluck(:name) } + statuses_and_reblogs = statuses.flat_map { |status| [status] + status.reblogs } - @json_payloads = statuses.each_with_object({}) { |s, h| h[s.id] = Oj.dump(event: :delete, payload: s.id.to_s) } + # The conversations for direct visibility statuses also need + # to be manually updated. This part is not efficient but we + # rely on direct visibility statuses being relatively rare. + statuses_with_account_conversations = statuses.select(&:direct_visibility?) - # Ensure that rendered XML reflects destroyed state - statuses.each do |status| - status.mark_for_mass_destruction! - status.destroy + ActiveRecord::Associations::Preloader.new.preload(statuses_with_account_conversations, [mentions: :account]) + + statuses_with_account_conversations.each do |status| + status.send(:unlink_from_conversations) end + # We do not batch all deletes into one to avoid having a long-running + # transaction lock the database, but we use the delete method instead + # of destroy to avoid all callbacks. We rely on foreign keys to + # cascade the delete faster without loading the associations. + statuses_and_reblogs.each_slice(50) { |slice| Status.where(id: slice.map(&:id)).delete_all } + + # Since we skipped all callbacks, we also need to manually + # deindex the statuses + Chewy.strategy.current.update(StatusesIndex::Status, statuses_and_reblogs) if Chewy.enabled? + return if options[:skip_side_effects] # Batch by source account - statuses.group_by(&:account_id).each_value do |account_statuses| + statuses_and_reblogs.group_by(&:account_id).each_value do |account_statuses| account = account_statuses.first.account next unless account @@ -38,19 +46,18 @@ class BatchedRemoveStatusService < BaseService end # Cannot be batched - statuses.each do |status| - unpush_from_public_timelines(status) + @status_id_cutoff = Mastodon::Snowflake.id_at(2.weeks.ago) + redis.pipelined do + statuses.each do |status| + unpush_from_public_timelines(status) + end end end private def unpush_from_home_timelines(account, statuses) - recipients = account.followers_for_local_distribution.to_a - - recipients << account if account.local? - - recipients.each do |follower| + account.followers_for_local_distribution.includes(:user).reorder(nil).find_each do |follower| statuses.each do |status| FeedManager.instance.unpush_from_home(follower, status) end @@ -58,7 +65,7 @@ class BatchedRemoveStatusService < BaseService end def unpush_from_list_timelines(account, statuses) - account.lists_for_local_distribution.select(:id, :account_id).each do |list| + account.lists_for_local_distribution.select(:id, :account_id).includes(account: :user).reorder(nil).find_each do |list| statuses.each do |status| FeedManager.instance.unpush_from_list(list, status) end @@ -66,30 +73,21 @@ class BatchedRemoveStatusService < BaseService end def unpush_from_public_timelines(status) - return unless status.public_visibility? + return unless status.public_visibility? && status.id > @status_id_cutoff - payload = @json_payloads[status.id] + payload = Oj.dump(event: :delete, payload: status.id.to_s) - redis.pipelined do - redis.publish('timeline:public', payload) - if status.local? - redis.publish('timeline:public:local', payload) - else - redis.publish('timeline:public:remote', payload) - end - if status.media_attachments.any? - redis.publish('timeline:public:media', payload) - if status.local? - redis.publish('timeline:public:local:media', payload) - else - redis.publish('timeline:public:remote:media', payload) - end - end + redis.publish('timeline:public', payload) + redis.publish(status.local? ? 'timeline:public:local' : 'timeline:public:remote', payload) - @tags[status.id].each do |hashtag| - redis.publish("timeline:hashtag:#{hashtag.mb_chars.downcase}", payload) - redis.publish("timeline:hashtag:#{hashtag.mb_chars.downcase}:local", payload) if status.local? - end + if status.media_attachments.any? + redis.publish('timeline:public:media', payload) + redis.publish(status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', payload) + end + + status.tags.map { |tag| tag.name.mb_chars.downcase }.each do |hashtag| + redis.publish("timeline:hashtag:#{hashtag}", payload) + redis.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local? end end end diff --git a/app/services/block_domain_service.rb b/app/services/block_domain_service.rb index dc23ef8d8a8e5019e44b783190ad44eebd901ba7..76cc36ff6b0d005adede48ca8be89cf0027bebf6 100644 --- a/app/services/block_domain_service.rb +++ b/app/services/block_domain_service.rb @@ -16,7 +16,7 @@ class BlockDomainService < BaseService scope = Account.by_domain_and_subdomains(domain_block.domain) scope.where(silenced_at: domain_block.created_at).in_batches.update_all(silenced_at: nil) unless domain_block.silence? - scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil) unless domain_block.suspend? + scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil, suspension_origin: nil) unless domain_block.suspend? end def process_domain_block! @@ -34,9 +34,10 @@ class BlockDomainService < BaseService end def suspend_accounts! - blocked_domain_accounts.without_suspended.in_batches.update_all(suspended_at: @domain_block.created_at) + blocked_domain_accounts.without_suspended.in_batches.update_all(suspended_at: @domain_block.created_at, suspension_origin: :local) + blocked_domain_accounts.where(suspended_at: @domain_block.created_at).reorder(nil).find_each do |account| - SuspendAccountService.new.call(account, reserve_username: true, suspended_at: @domain_block.created_at) + DeleteAccountService.new.call(account, reserve_username: true, suspended_at: @domain_block.created_at) end end diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..802799ccd9b96389fc644202f3a9e4395acb841f --- /dev/null +++ b/app/services/delete_account_service.rb @@ -0,0 +1,307 @@ +# frozen_string_literal: true + +class DeleteAccountService < BaseService + include Payloadable + + ASSOCIATIONS_ON_SUSPEND = %w( + account_pins + active_relationships + aliases + block_relationships + blocked_by_relationships + conversation_mutes + conversations + custom_filters + devices + domain_blocks + featured_tags + follow_requests + identity_proofs + list_accounts + migrations + mute_relationships + muted_by_relationships + notifications + owned_lists + passive_relationships + report_notes + scheduled_statuses + status_pins + ).freeze + + # The following associations have no important side-effects + # in callbacks and all of their own associations are secured + # by foreign keys, making them safe to delete without loading + # into memory + ASSOCIATIONS_WITHOUT_SIDE_EFFECTS = %w( + account_pins + aliases + conversation_mutes + conversations + custom_filters + devices + domain_blocks + featured_tags + follow_requests + identity_proofs + list_accounts + migrations + mute_relationships + muted_by_relationships + notifications + owned_lists + scheduled_statuses + status_pins + ) + + ASSOCIATIONS_ON_DESTROY = %w( + reports + targeted_moderation_notes + targeted_reports + ).freeze + + # Suspend or remove an account and remove as much of its data + # as possible. If it's a local account and it has not been confirmed + # or never been approved, then side effects are skipped and both + # the user and account records are removed fully. Otherwise, + # it is controlled by options. + # @param [Account] + # @param [Hash] options + # @option [Boolean] :reserve_email Keep user record. Only applicable for local accounts + # @option [Boolean] :reserve_username Keep account record + # @option [Boolean] :skip_side_effects Side effects are ActivityPub and streaming API payloads + # @option [Boolean] :skip_activitypub Skip sending ActivityPub payloads. Implied by :skip_side_effects + # @option [Time] :suspended_at Only applicable when :reserve_username is true + def call(account, **options) + @account = account + @options = { reserve_username: true, reserve_email: true }.merge(options) + + if @account.local? && @account.user_unconfirmed_or_pending? + @options[:reserve_email] = false + @options[:reserve_username] = false + @options[:skip_side_effects] = true + end + + @options[:skip_activitypub] = true if @options[:skip_side_effects] + + distribute_activities! + purge_content! + fulfill_deletion_request! + end + + private + + def distribute_activities! + return if skip_activitypub? + + if @account.local? + delete_actor! + elsif @account.activitypub? + reject_follows! + undo_follows! + end + end + + def reject_follows! + # When deleting a remote account, the account obviously doesn't + # actually become deleted on its origin server, i.e. unlike a + # locally deleted account it continues to have access to its home + # feed and other content. To prevent it from being able to continue + # to access toots it would receive because it follows local accounts, + # we have to force it to unfollow them. + + ActivityPub::DeliveryWorker.push_bulk(Follow.where(account: @account)) do |follow| + [Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)), follow.target_account_id, @account.inbox_url] + end + end + + def undo_follows! + # When deleting a remote account, the account obviously doesn't + # actually become deleted on its origin server, but following relationships + # are severed on our end. Therefore, make the remote server aware that the + # follow relationships are severed to avoid confusion and potential issues + # if the remote account gets un-suspended. + + ActivityPub::DeliveryWorker.push_bulk(Follow.where(target_account: @account)) do |follow| + [Oj.dump(serialize_payload(follow, ActivityPub::UndoFollowSerializer)), follow.account_id, @account.inbox_url] + end + end + + def purge_user! + return if !@account.local? || @account.user.nil? + + if keep_user_record? + @account.user.disable! + @account.user.invites.where(uses: 0).destroy_all + else + @account.user.destroy + end + end + + def purge_content! + purge_user! + purge_profile! + purge_statuses! + purge_mentions! + purge_media_attachments! + purge_polls! + purge_generated_notifications! + purge_favourites! + purge_bookmarks! + purge_feeds! + purge_other_associations! + + @account.destroy unless keep_account_record? + end + + def purge_statuses! + @account.statuses.reorder(nil).where.not(id: reported_status_ids).in_batches do |statuses| + BatchedRemoveStatusService.new.call(statuses, skip_side_effects: skip_side_effects?) + end + end + + def purge_mentions! + @account.mentions.reorder(nil).where.not(status_id: reported_status_ids).in_batches.delete_all + end + + def purge_media_attachments! + @account.media_attachments.reorder(nil).find_each do |media_attachment| + next if keep_account_record? && reported_status_ids.include?(media_attachment.status_id) + + media_attachment.destroy + end + end + + def purge_polls! + @account.polls.reorder(nil).where.not(status_id: reported_status_ids).in_batches.delete_all + end + + def purge_generated_notifications! + # By deleting polls and statuses without callbacks, we've left behind + # polymorphically associated notifications generated by this account + + Notification.where(from_account: @account).in_batches.delete_all + end + + def purge_favourites! + @account.favourites.in_batches do |favourites| + ids = favourites.pluck(:status_id) + StatusStat.where(status_id: ids).update_all('favourites_count = GREATEST(0, favourites_count - 1)') + Chewy.strategy.current.update(StatusesIndex::Status, ids) if Chewy.enabled? + # Rails.cache.delete_multi would be better, but we don't have it yet + ids.each { |id| Rails.cache.delete("statuses/#{id}") } + favourites.delete_all + end + end + + def purge_bookmarks! + @account.bookmarks.in_batches do |bookmarks| + Chewy.strategy.current.update(StatusesIndex::Status, bookmarks.pluck(:status_id)) if Chewy.enabled? + bookmarks.delete_all + end + end + + def purge_other_associations! + associations_for_destruction.each do |association_name| + purge_association(association_name) + end + end + + def purge_feeds! + return unless @account.local? + + FeedManager.instance.clean_feeds!(:home, [@account.id]) + FeedManager.instance.clean_feeds!(:list, @account.owned_lists.pluck(:id)) + end + + def purge_profile! + # If the account is going to be destroyed + # there is no point wasting time updating + # its values first + + return unless keep_account_record? + + @account.silenced_at = nil + @account.suspended_at = @options[:suspended_at] || Time.now.utc + @account.suspension_origin = :local + @account.locked = false + @account.memorial = false + @account.discoverable = false + @account.display_name = '' + @account.note = '' + @account.fields = [] + @account.statuses_count = 0 + @account.followers_count = 0 + @account.following_count = 0 + @account.moved_to_account = nil + @account.also_known_as = [] + @account.trust_level = :untrusted + @account.avatar.destroy + @account.header.destroy + @account.save! + end + + def fulfill_deletion_request! + @account.deletion_request&.destroy + end + + def purge_association(association_name) + association = @account.public_send(association_name) + + if ASSOCIATIONS_WITHOUT_SIDE_EFFECTS.include?(association_name) + association.in_batches.delete_all + else + association.in_batches.destroy_all + end + end + + def delete_actor! + ActivityPub::DeliveryWorker.push_bulk(delivery_inboxes) do |inbox_url| + [delete_actor_json, @account.id, inbox_url] + end + + ActivityPub::LowPriorityDeliveryWorker.push_bulk(low_priority_delivery_inboxes) do |inbox_url| + [delete_actor_json, @account.id, inbox_url] + end + end + + def delete_actor_json + @delete_actor_json ||= Oj.dump(serialize_payload(@account, ActivityPub::DeleteActorSerializer, signer: @account)) + end + + def delivery_inboxes + @delivery_inboxes ||= @account.followers.inboxes + Relay.enabled.pluck(:inbox_url) + end + + def low_priority_delivery_inboxes + Account.inboxes - delivery_inboxes + end + + def reported_status_ids + @reported_status_ids ||= Report.where(target_account: @account).unresolved.pluck(:status_ids).flatten.uniq + end + + def associations_for_destruction + if keep_account_record? + ASSOCIATIONS_ON_SUSPEND + else + ASSOCIATIONS_ON_SUSPEND + ASSOCIATIONS_ON_DESTROY + end + end + + def keep_user_record? + @options[:reserve_email] + end + + def keep_account_record? + @options[:reserve_username] + end + + def skip_side_effects? + @options[:skip_side_effects] + end + + def skip_activitypub? + @options[:skip_activitypub] + end +end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 276eac0c18c93224192596a2cf3e99abd81c3d6b..b72bb82d3faea4f9e9bf0b776f21eaba809012a2 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -6,20 +6,22 @@ class FanOutOnWriteService < BaseService def call(status) raise Mastodon::RaceConditionError if status.visibility.nil? - render_anonymous_payload(status) + deliver_to_self(status) if status.account.local? if status.direct_visibility? + deliver_to_mentioned_followers(status) deliver_to_own_conversation(status) elsif status.limited_visibility? deliver_to_mentioned_followers(status) else - deliver_to_self(status) if status.account.local? deliver_to_followers(status) deliver_to_lists(status) end return if status.account.silenced? || !status.public_visibility? || status.reblog? + render_anonymous_payload(status) + deliver_to_hashtags(status) return if status.reply? && status.in_reply_to_account_id != status.account_id @@ -58,8 +60,10 @@ class FanOutOnWriteService < BaseService def deliver_to_mentioned_followers(status) Rails.logger.debug "Delivering status #{status.id} to limited followers" - FeedInsertWorker.push_bulk(status.mentions.includes(:account).map(&:account).select { |mentioned_account| mentioned_account.local? && mentioned_account.following?(status.account) }) do |follower| - [status.id, follower.id, :home] + status.mentions.joins(:account).merge(status.account.followers_for_local_distribution).select(:id, :account_id).reorder(nil).find_in_batches do |mentions| + FeedInsertWorker.push_bulk(mentions) do |mention| + [status.id, mention.account_id, :home] + end end end diff --git a/app/services/favourite_service.rb b/app/services/favourite_service.rb index 02b26458a6fa09e7934354c22443ec1768d55d1b..a0ab3b4b755603c046034df4dc6859442bec51f5 100644 --- a/app/services/favourite_service.rb +++ b/app/services/favourite_service.rb @@ -29,7 +29,7 @@ class FavouriteService < BaseService status = favourite.status if status.account.local? - NotifyService.new.call(status.account, favourite) + NotifyService.new.call(status.account, :favourite, favourite) elsif status.account.activitypub? ActivityPub::DeliveryWorker.perform_async(build_json(favourite), favourite.account_id, status.account.inbox_url) end diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index beab449b27389d576a9965f1d3dd9fdb6ba6f598..7efa310547efcdff47144fae63ffd6420207ca1f 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -78,6 +78,7 @@ class FetchLinkCardService < BaseService uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) end + # rubocop:disable Naming/MethodParameterName def mention_link?(a) @status.mentions.any? do |mention| a['href'] == ActivityPub::TagManager.instance.url_for(mention.account) @@ -88,6 +89,7 @@ class FetchLinkCardService < BaseService # Avoid links for hashtags and mentions (microformats) a['rel']&.include?('tag') || a['class']&.match?(/u-url|h-card/) || mention_link?(a) end + # rubocop:enable Naming/MethodParameterName def attempt_oembed service = FetchOEmbedService.new diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index 311ae7fa688dd65c14ae1869bcd556e66b9e3f60..b98f7011d1887e55460ef042f2c99127293bed75 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -9,12 +9,14 @@ class FollowService < BaseService # @param [String, Account] uri User URI to follow in the form of username@domain (or account record) # @param [Hash] options # @option [Boolean] :reblogs Whether or not to show reblogs, defaults to true + # @option [Boolean] :notify Whether to create notifications about new posts, defaults to false # @option [Boolean] :bypass_locked + # @option [Boolean] :bypass_limit Allow following past the total follow number # @option [Boolean] :with_rate_limit def call(source_account, target_account, options = {}) @source_account = source_account @target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true) - @options = { reblogs: true, bypass_locked: false, with_rate_limit: false }.merge(options) + @options = { bypass_locked: false, bypass_limit: false, with_rate_limit: false }.merge(options) raise ActiveRecord::RecordNotFound if following_not_possible? raise Mastodon::NotPermittedError if following_not_allowed? @@ -45,18 +47,18 @@ class FollowService < BaseService end def change_follow_options! - @source_account.follow!(@target_account, reblogs: @options[:reblogs]) + @source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify]) end def change_follow_request_options! - @source_account.request_follow!(@target_account, reblogs: @options[:reblogs]) + @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify]) end def request_follow! - follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit]) + follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit]) if @target_account.local? - LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name) + LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name, :follow_request) elsif @target_account.activitypub? ActivityPub::DeliveryWorker.perform_async(build_json(follow_request), @source_account.id, @target_account.inbox_url) end @@ -65,9 +67,9 @@ class FollowService < BaseService end def direct_follow! - follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit]) + follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], notify: @options[:notify], rate_limit: @options[:with_rate_limit], bypass_limit: @options[:bypass_limit]) - LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name) + LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name, :follow) MergeWorker.perform_async(@target_account.id, @source_account.id) follow diff --git a/app/services/hashtag_query_service.rb b/app/services/hashtag_query_service.rb deleted file mode 100644 index 196de0639205b20596ea5968210234ab390c5b08..0000000000000000000000000000000000000000 --- a/app/services/hashtag_query_service.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -class HashtagQueryService < BaseService - LIMIT_PER_MODE = 4 - - def call(tag, params, account = nil, local = false) - tags = tags_for(Array(tag.name) | Array(params[:any])).pluck(:id) - all = tags_for(params[:all]) - none = tags_for(params[:none]) - - Status.distinct - .as_tag_timeline(tags, account, local) - .tagged_with_all(all) - .tagged_with_none(none) - end - - private - - def tags_for(names) - Tag.matching_name(Array(names).take(LIMIT_PER_MODE)) if names.present? - end -end diff --git a/app/services/import_service.rb b/app/services/import_service.rb index 4cad93767a4268acc75dc3008afc684329ac3392..0c6ef2238e94afc430ee7bc1821b07e5e0cc7317 100644 --- a/app/services/import_service.rb +++ b/app/services/import_service.rb @@ -18,6 +18,8 @@ class ImportService < BaseService import_mutes! when 'domain_blocking' import_domain_blocks! + when 'bookmarks' + import_bookmarks! end end @@ -25,7 +27,7 @@ class ImportService < BaseService def import_follows! parse_import_data!(['Account address']) - import_relationships!('follow', 'unfollow', @account.following, follow_limit, reblogs: 'Show boosts') + import_relationships!('follow', 'unfollow', @account.following, ROWS_PROCESSING_LIMIT, reblogs: { header: 'Show boosts', default: true }) end def import_blocks! @@ -35,7 +37,7 @@ class ImportService < BaseService def import_mutes! parse_import_data!(['Account address']) - import_relationships!('mute', 'unmute', @account.muting, ROWS_PROCESSING_LIMIT, notifications: 'Hide notifications') + import_relationships!('mute', 'unmute', @account.muting, ROWS_PROCESSING_LIMIT, notifications: { header: 'Hide notifications', default: true }) end def import_domain_blocks! @@ -65,7 +67,7 @@ class ImportService < BaseService def import_relationships!(action, undo_action, overwrite_scope, limit, extra_fields = {}) local_domain_suffix = "@#{Rails.configuration.x.local_domain}" - items = @data.take(limit).map { |row| [row['Account address']&.strip&.delete_suffix(local_domain_suffix), Hash[extra_fields.map { |key, header| [key, row[header]&.strip] }]] }.reject { |(id, _)| id.blank? } + items = @data.take(limit).map { |row| [row['Account address']&.strip&.delete_suffix(local_domain_suffix), Hash[extra_fields.map { |key, field_settings| [key, row[field_settings[:header]]&.strip || field_settings[:default]] }]] }.reject { |(id, _)| id.blank? } if @import.overwrite? presence_hash = items.each_with_object({}) { |(id, extra), mapping| mapping[id] = [true, extra] } @@ -83,11 +85,45 @@ class ImportService < BaseService head_items = items.uniq { |acct, _| acct.split('@')[1] } tail_items = items - head_items + Import::RelationshipWorker.push_bulk(head_items + tail_items) do |acct, extra| [@account.id, acct, action, extra] end end + def import_bookmarks! + parse_import_data!(['#uri']) + items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip } + + if @import.overwrite? + presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true } + + @account.bookmarks.find_each do |bookmark| + if presence_hash[bookmark.status.uri] + items.delete(bookmark.status.uri) + else + bookmark.destroy! + end + end + end + + statuses = items.map do |uri| + status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status) + next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri) + + status || ActivityPub::FetchRemoteStatusService.new.call(uri) + end.compact + + account_ids = statuses.map(&:account_id) + preloaded_relations = relations_map_for_account(@account, account_ids) + + statuses.keep_if { |status| StatusPolicy.new(@account, status, preloaded_relations).show? } + + statuses.each do |status| + @account.bookmarks.find_or_create_by!(account: @account, status: status) + end + end + def parse_import_data!(default_headers) data = CSV.parse(import_data, headers: true) data = CSV.parse(import_data, headers: default_headers) unless data.headers&.first&.strip&.include?(' ') @@ -98,7 +134,13 @@ class ImportService < BaseService Paperclip.io_adapters.for(@import.data).read end - def follow_limit - FollowLimitValidator.limit_for_account(@account) + def relations_map_for_account(account, account_ids) + { + blocking: {}, + blocked_by: Account.blocked_by_map(account_ids, account.id), + muting: {}, + following: Account.following_map(account_ids, account.id), + domain_blocking_by_domain: {}, + } end end diff --git a/app/services/mute_service.rb b/app/services/mute_service.rb index 676804cb991d97fa718f9b5554c47ea339daf4da..9ae9afd623498d3a6b0baaa7d6cb7d91a88fea6f 100644 --- a/app/services/mute_service.rb +++ b/app/services/mute_service.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true class MuteService < BaseService - def call(account, target_account, notifications: nil) + def call(account, target_account, notifications: nil, duration: 0) return if account.id == target_account.id - mute = account.mute!(target_account, notifications: notifications) + mute = account.mute!(target_account, notifications: notifications, duration: duration) if mute.hide_notifications? BlockWorker.perform_async(account.id, target_account.id) @@ -12,6 +12,8 @@ class MuteService < BaseService MuteWorker.perform_async(account.id, target_account.id) end + DeleteMuteWorker.perform_at(duration.seconds, mute.id) if duration != 0 + mute end end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 9364a6ae87933f3c4caae2421c3f596d9c2a8ef2..fc187db4030673ac4d4093b2fbcd40c5e71d50ea 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true class NotifyService < BaseService - def call(recipient, activity) + def call(recipient, type, activity) @recipient = recipient @activity = activity - @notification = Notification.new(account: @recipient, activity: @activity) + @notification = Notification.new(account: @recipient, type: type, activity: @activity) return if recipient.user.nil? || blocked? @@ -13,13 +13,17 @@ class NotifyService < BaseService push_to_conversation! if direct_message? send_email! if email_enabled? rescue ActiveRecord::RecordInvalid - return + nil end private def blocked_mention? - FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient.id) + FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient) + end + + def blocked_status? + false end def blocked_favourite? diff --git a/app/services/precompute_feed_service.rb b/app/services/precompute_feed_service.rb index 076dedacab97dfed799c5c417b4ada969e0555e4..61f573534dda18ca4267e73b1da1a4f98dcc0c32 100644 --- a/app/services/precompute_feed_service.rb +++ b/app/services/precompute_feed_service.rb @@ -2,7 +2,7 @@ class PrecomputeFeedService < BaseService def call(account) - FeedManager.instance.populate_feed(account) + FeedManager.instance.populate_home(account) ensure Redis.current.del("account:#{account.id}:regeneration") end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 33243c0ba70d6dd6f4bf885bdc306f34b7900e63..d8d24e8e0bdab2ebe811a5b077f2864e56f9813f 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -30,14 +30,15 @@ class ProcessMentionsService < BaseService if mention_undeliverable?(mentioned_account) begin mentioned_account = resolve_account_service.call(Regexp.last_match(1)) - rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError + rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError mentioned_account = nil end end next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended? - mentions << mentioned_account.mentions.where(status: status).first_or_create(status: status) + mention = mentioned_account.mentions.new(status: status) + mentions << mention if mention.save "@#{mentioned_account.acct}" end @@ -64,9 +65,9 @@ class ProcessMentionsService < BaseService mentioned_account = mention.account if mentioned_account.local? - LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name) + LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name, :mention) elsif mentioned_account.activitypub? - ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url) + ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url, { synchronize_followers: !mention.status.distributable? }) end end diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb index 6866d2face796633465531e1d03cb4682599a820..5032397b34f8d8e83292b9ac05b0d7be013bb91c 100644 --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@ -45,7 +45,7 @@ class ReblogService < BaseService reblogged_status = reblog.reblog if reblogged_status.account.local? - LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name) + LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, :reblog) elsif reblogged_status.account.activitypub? && !reblogged_status.account.following?(reblog.account) ActivityPub::DeliveryWorker.perform_async(build_json(reblog), reblog.account_id, reblogged_status.account.inbox_url) end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 4f0edc3cfbaaa2ff346eca7942179380cc52ddc1..d6043fb5d8099cc318286c2b49fbe851b11bd6db 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -9,44 +9,47 @@ class RemoveStatusService < BaseService # @param [Hash] options # @option [Boolean] :redraft # @option [Boolean] :immediate - # @option [Boolean] :original_removed + # @option [Boolean] :original_removed def call(status, **options) @payload = Oj.dump(event: :delete, payload: status.id.to_s) @status = status @account = status.account - @tags = status.tags.pluck(:name).to_a - @mentions = status.active_mentions.includes(:account).to_a - @reblogs = status.reblogs.includes(:account).to_a @options = options RedisLock.acquire(lock_options) do |lock| if lock.acquired? - remove_from_self if status.account.local? + remove_from_self if @account.local? remove_from_followers remove_from_lists - remove_from_affected - remove_reblogs - remove_from_hashtags - remove_from_public - remove_from_media if status.media_attachments.any? - remove_from_spam_check - remove_media + + # There is no reason to send out Undo activities when the + # cause is that the original object has been removed, since + # original object being removed implicitly removes reblogs + # of it. The Delete activity of the original is forwarded + # separately. + if @account.local? && !@options[:original_removed] + remove_from_remote_followers + remove_from_remote_reach + end + + # Since reblogs don't mention anyone, don't get reblogged, + # favourited and don't contain their own media attachments + # or hashtags, this can be skipped + unless @status.reblog? + remove_from_mentions + remove_reblogs + remove_from_hashtags + remove_from_public + remove_from_media if @status.media_attachments.any? + remove_from_spam_check + remove_media + end @status.destroy! if @options[:immediate] || !@status.reported? else raise Mastodon::RaceConditionError end end - - # There is no reason to send out Undo activities when the - # cause is that the original object has been removed, since - # original object being removed implicitly removes reblogs - # of it. The Delete activity of the original is forwarded - # separately. - return if !@account.local? || @options[:original_removed] - - remove_from_remote_followers - remove_from_remote_affected end private @@ -67,31 +70,35 @@ class RemoveStatusService < BaseService end end - def remove_from_affected - @mentions.map(&:account).select(&:local?).each do |account| - redis.publish("timeline:#{account.id}", @payload) + def remove_from_mentions + # For limited visibility statuses, the mentions that determine + # who receives them in their home feed are a subset of followers + # and therefore the delete is already handled by sending it to all + # followers. Here we send a delete to actively mentioned accounts + # that may not follow the account + + @status.active_mentions.find_each do |mention| + redis.publish("timeline:#{mention.account_id}", @payload) end end - def remove_from_remote_affected + def remove_from_remote_reach + return if @status.reblog? + # People who got mentioned in the status, or who # reblogged it from someone else might not follow # the author and wouldn't normally receive the # delete notification - so here, we explicitly # send it to them - target_accounts = (@mentions.map(&:account).reject(&:local?) + @reblogs.map(&:account).reject(&:local?)) - target_accounts << @status.reblog.account if @status.reblog? && !@status.reblog.account.local? - target_accounts.uniq!(&:id) + status_reach_finder = StatusReachFinder.new(@status) - # ActivityPub - ActivityPub::DeliveryWorker.push_bulk(target_accounts.select(&:activitypub?).uniq(&:preferred_inbox_url)) do |target_account| - [signed_activity_json, @account.id, target_account.preferred_inbox_url] + ActivityPub::DeliveryWorker.push_bulk(status_reach_finder.inboxes) do |inbox_url| + [signed_activity_json, @account.id, inbox_url] end end def remove_from_remote_followers - # ActivityPub ActivityPub::DeliveryWorker.push_bulk(@account.followers.inboxes) do |inbox_url| [signed_activity_json, @account.id, inbox_url] end @@ -118,19 +125,19 @@ class RemoveStatusService < BaseService # because once original status is gone, reblogs will disappear # without us being able to do all the fancy stuff - @reblogs.each do |reblog| + @status.reblogs.includes(:account).find_each do |reblog| RemoveStatusService.new.call(reblog, original_removed: true) end end def remove_from_hashtags - @account.featured_tags.where(tag_id: @status.tags.pluck(:id)).each do |featured_tag| + @account.featured_tags.where(tag_id: @status.tags.map(&:id)).each do |featured_tag| featured_tag.decrement(@status.id) end return unless @status.public_visibility? - @tags.each do |hashtag| + @status.tags.map(&:name).each do |hashtag| redis.publish("timeline:hashtag:#{hashtag.mb_chars.downcase}", @payload) redis.publish("timeline:hashtag:#{hashtag.mb_chars.downcase}:local", @payload) if @status.local? end @@ -140,22 +147,14 @@ class RemoveStatusService < BaseService return unless @status.public_visibility? redis.publish('timeline:public', @payload) - if @status.local? - redis.publish('timeline:public:local', @payload) - else - redis.publish('timeline:public:remote', @payload) - end + redis.publish(@status.local? ? 'timeline:public:local' : 'timeline:public:remote', @payload) end def remove_from_media return unless @status.public_visibility? redis.publish('timeline:public:media', @payload) - if @status.local? - redis.publish('timeline:public:local:media', @payload) - else - redis.publish('timeline:public:remote:media', @payload) - end + redis.publish(@status.local? ? 'timeline:public:local:media' : 'timeline:public:remote:media', @payload) end def remove_media diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 1e955c1e704b70574511426e1e7f25097889d257..9d9c7d6c9fc1da60126dcce7e5964ac8ff211b34 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -24,7 +24,8 @@ class ReportService < BaseService target_account: @target_account, status_ids: @status_ids, comment: @comment, - uri: @options[:uri] + uri: @options[:uri], + forwarded: ActiveModel::Type::Boolean.new.cast(@options[:forward]) ) end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index ba77552c6c02796170cc55d04f80317bbeec4642..3301aaf51b1311c2f19d5db6f7839aaffe7dd9e8 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -5,8 +5,6 @@ class ResolveAccountService < BaseService include DomainControlHelper include WebfingerHelper - class WebfingerRedirectError < StandardError; end - # Find or create an account record for a remote user. When creating, # look up the user's webfinger and fetch ActivityPub data # @param [String, Account] uri URI in the username@domain format or account record @@ -26,12 +24,12 @@ class ResolveAccountService < BaseService @account ||= Account.find_remote(@username, @domain) - return @account if @account&.local? || !webfinger_update_due? + return @account if @account&.local? || @domain.nil? || !webfinger_update_due? # At this point we are in need of a Webfinger query, which may # yield us a different username/domain through a redirect - process_webfinger!(@uri) + @domain = nil if TagManager.instance.local_domain?(@domain) # Because the username/domain pair may be different than what # we already checked, we need to check if we've already got @@ -41,13 +39,18 @@ class ResolveAccountService < BaseService @account ||= Account.find_remote(@username, @domain) - return @account if @account&.local? || !webfinger_update_due? + if gone_from_origin? && not_yet_deleted? + queue_deletion! + return + end + + return @account if @account&.local? || gone_from_origin? || !webfinger_update_due? # Now it is certain, it is definitely a remote account, and it # either needs to be created, or updated from fresh data - process_account! - rescue Goldfinger::Error, WebfingerRedirectError, Oj::ParseError => e + fetch_account! + rescue Webfinger::Error, Oj::ParseError => e Rails.logger.debug "Webfinger query for #{@uri} failed: #{e}" nil end @@ -76,33 +79,37 @@ class ResolveAccountService < BaseService @uri = [@username, @domain].compact.join('@') end - def process_webfinger!(uri, redirected = false) + def process_webfinger!(uri) @webfinger = webfinger!("acct:#{uri}") - confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@') + confirmed_username, confirmed_domain = split_acct(@webfinger.subject) if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? @username = confirmed_username @domain = confirmed_domain - @uri = uri - elsif !redirected - return process_webfinger!("#{confirmed_username}@#{confirmed_domain}", true) - else - raise WebfingerRedirectError, "The URI #{uri} tries to hijack #{@username}@#{@domain}" + return end - @domain = nil if TagManager.instance.local_domain?(@domain) + # Account doesn't match, so it may have been redirected + @webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") + @username, @domain = split_acct(@webfinger.subject) + + unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? + raise Webfinger::RedirectError, "The URI #{uri} tries to hijack #{@username}@#{@domain}" + end + rescue Webfinger::GoneError + @gone = true + end + + def split_acct(acct) + acct.gsub(/\Aacct:/, '').split('@') end - def process_account! + def fetch_account! return unless activitypub_ready? RedisLock.acquire(lock_options) do |lock| if lock.acquired? - @account = Account.find_remote(@username, @domain) - - next if actor_json.nil? - - @account = ActivityPub::ProcessAccountService.new.call(@username, @domain, actor_json) + @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url) else raise Mastodon::RaceConditionError end @@ -118,18 +125,23 @@ class ResolveAccountService < BaseService end def activitypub_ready? - !@webfinger.link('self').nil? && ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self').type) + ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self', 'type')) end def actor_url - @actor_url ||= @webfinger.link('self').href + @actor_url ||= @webfinger.link('self', 'href') + end + + def gone_from_origin? + @gone end - def actor_json - return @actor_json if defined?(@actor_json) + def not_yet_deleted? + @account.present? && !@account.local? + end - json = fetch_resource(actor_url, false) - @actor_json = supported_context?(json) && equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) ? json : nil + def queue_deletion! + AccountDeletionWorker.perform_async(@account.id, reserve_username: false, skip_activitypub: true) end def lock_options diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb index 78080d878f9dba5f238ceb0044331952c9305ec9..5981e4d98a00fc4e2a958972bbfd84894a65e6ee 100644 --- a/app/services/resolve_url_service.rb +++ b/app/services/resolve_url_service.rb @@ -34,7 +34,17 @@ class ResolveURLService < BaseService # It may happen that the resource is a private toot, and thus not fetchable, # but we can return the toot if we already know about it. - status = Status.find_by(uri: @url) || Status.find_by(url: @url) + scope = Status.where(uri: @url) + + # We don't have an index on `url`, so try guessing the `uri` from `url` + parsed_url = Addressable::URI.parse(@url) + parsed_url.path.match(%r{/@(?<username>#{Account::USERNAME_RE})/(?<status_id>[0-9]+)\Z}) do |matched| + parsed_url.path = "/users/#{matched[:username]}/statuses/#{matched[:status_id]}" + scope = scope.or(Status.where(uri: parsed_url.to_s, url: @url)) + end + + status = scope.first + authorize_with @on_behalf_of, status, :show? unless status.nil? status rescue Mastodon::NotPermittedError diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index ecc893931d596d9fd00a8a0911ce910be7bf9f95..9f4da91d4c005986f23c672d3ef636359277fe96 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -3,173 +3,91 @@ class SuspendAccountService < BaseService include Payloadable - ASSOCIATIONS_ON_SUSPEND = %w( - account_pins - active_relationships - block_relationships - blocked_by_relationships - conversation_mutes - conversations - custom_filters - domain_blocks - favourites - follow_requests - list_accounts - mute_relationships - muted_by_relationships - notifications - owned_lists - passive_relationships - report_notes - scheduled_statuses - status_pins - ).freeze - - ASSOCIATIONS_ON_DESTROY = %w( - reports - targeted_moderation_notes - targeted_reports - ).freeze - - # Suspend or remove an account and remove as much of its data - # as possible. If it's a local account and it has not been confirmed - # or never been approved, then side effects are skipped and both - # the user and account records are removed fully. Otherwise, - # it is controlled by options. - # @param [Account] - # @param [Hash] options - # @option [Boolean] :reserve_email Keep user record. Only applicable for local accounts - # @option [Boolean] :reserve_username Keep account record - # @option [Boolean] :skip_side_effects Side effects are ActivityPub and streaming API payloads - # @option [Time] :suspended_at Only applicable when :reserve_username is true - def call(account, **options) + def call(account) @account = account - @options = { reserve_username: true, reserve_email: true }.merge(options) - if @account.local? && @account.user_unconfirmed_or_pending? - @options[:reserve_email] = false - @options[:reserve_username] = false - @options[:skip_side_effects] = true - end - - reject_follows! - purge_user! - purge_profile! - purge_content! + suspend! + reject_remote_follows! + distribute_update_actor! + unmerge_from_home_timelines! + unmerge_from_list_timelines! + privatize_media_attachments! end private - def reject_follows! - return if @account.local? || !@account.activitypub? - - ActivityPub::DeliveryWorker.push_bulk(Follow.where(account: @account)) do |follow| - [build_reject_json(follow), follow.target_account_id, follow.account.inbox_url] - end + def suspend! + @account.suspend! unless @account.suspended? end - def purge_user! - return if !@account.local? || @account.user.nil? - - if @options[:reserve_email] - @account.user.disable! - @account.user.invites.where(uses: 0).destroy_all - else - @account.user.destroy - end - end - - def purge_content! - distribute_delete_actor! if @account.local? && !@options[:skip_side_effects] - - @account.statuses.reorder(nil).find_in_batches do |statuses| - statuses.reject! { |status| reported_status_ids.include?(status.id) } if @options[:reserve_username] - BatchedRemoveStatusService.new.call(statuses, skip_side_effects: @options[:skip_side_effects]) - end - - @account.media_attachments.reorder(nil).find_each do |media_attachment| - next if @options[:reserve_username] && reported_status_ids.include?(media_attachment.status_id) + def reject_remote_follows! + return if @account.local? || !@account.activitypub? - media_attachment.destroy - end + # When suspending a remote account, the account obviously doesn't + # actually become suspended on its origin server, i.e. unlike a + # locally suspended account it continues to have access to its home + # feed and other content. To prevent it from being able to continue + # to access toots it would receive because it follows local accounts, + # we have to force it to unfollow them. Unfortunately, there is no + # counterpart to this operation, i.e. you can't then force a remote + # account to re-follow you, so this part is not reversible. - @account.polls.reorder(nil).find_each do |poll| - next if @options[:reserve_username] && reported_status_ids.include?(poll.status_id) + follows = Follow.where(account: @account).to_a - poll.destroy + ActivityPub::DeliveryWorker.push_bulk(follows) do |follow| + [Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)), follow.target_account_id, @account.inbox_url] end - associations_for_destruction.each do |association_name| - destroy_all(@account.public_send(association_name)) - end - - @account.destroy unless @options[:reserve_username] - end - - def purge_profile! - # If the account is going to be destroyed - # there is no point wasting time updating - # its values first - - return unless @options[:reserve_username] - - @account.silenced_at = nil - @account.suspended_at = @options[:suspended_at] || Time.now.utc - @account.locked = false - @account.memorial = false - @account.discoverable = false - @account.display_name = '' - @account.note = '' - @account.fields = [] - @account.statuses_count = 0 - @account.followers_count = 0 - @account.following_count = 0 - @account.moved_to_account = nil - @account.trust_level = :untrusted - @account.avatar.destroy - @account.header.destroy - @account.save! + follows.each(&:destroy) end - def destroy_all(association) - association.in_batches.destroy_all + def distribute_update_actor! + ActivityPub::UpdateDistributionWorker.perform_async(@account.id) if @account.local? end - def distribute_delete_actor! - ActivityPub::DeliveryWorker.push_bulk(delivery_inboxes) do |inbox_url| - [delete_actor_json, @account.id, inbox_url] + def unmerge_from_home_timelines! + @account.followers_for_local_distribution.find_each do |follower| + FeedManager.instance.unmerge_from_home(@account, follower) end - - ActivityPub::LowPriorityDeliveryWorker.push_bulk(low_priority_delivery_inboxes) do |inbox_url| - [delete_actor_json, @account.id, inbox_url] - end - end - - def delete_actor_json - @delete_actor_json ||= Oj.dump(serialize_payload(@account, ActivityPub::DeleteActorSerializer, signer: @account)) end - def build_reject_json(follow) - Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)) - end - - def delivery_inboxes - @delivery_inboxes ||= @account.followers.inboxes + Relay.enabled.pluck(:inbox_url) - end - - def low_priority_delivery_inboxes - Account.inboxes - delivery_inboxes - end - - def reported_status_ids - @reported_status_ids ||= Report.where(target_account: @account).unresolved.pluck(:status_ids).flatten.uniq + def unmerge_from_list_timelines! + @account.lists_for_local_distribution.find_each do |list| + FeedManager.instance.unmerge_from_list(@account, list) + end end - def associations_for_destruction - if @options[:reserve_username] - ASSOCIATIONS_ON_SUSPEND - else - ASSOCIATIONS_ON_SUSPEND + ASSOCIATIONS_ON_DESTROY + def privatize_media_attachments! + attachment_names = MediaAttachment.attachment_definitions.keys + + @account.media_attachments.find_each do |media_attachment| + attachment_names.each do |attachment_name| + attachment = media_attachment.public_send(attachment_name) + styles = [:original] | attachment.styles.keys + + next if attachment.blank? + + styles.each do |style| + case Paperclip::Attachment.default_options[:storage] + when :s3 + begin + attachment.s3_object(style).acl.put(acl: 'private') + rescue Aws::S3::Errors::NoSuchKey + Rails.logger.warn "Tried to change acl on non-existent key #{attachment.s3_object(style).key}" + end + when :fog + # Not supported + when :filesystem + begin + FileUtils.chmod(0o600 & ~File.umask, attachment.path(style)) unless attachment.path(style).nil? + rescue Errno::ENOENT + Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}" + end + end + + CacheBusterWorker.perform_async(attachment.path(style)) if Rails.configuration.x.cache_buster_enabled + end + end end end end diff --git a/app/services/unblock_domain_service.rb b/app/services/unblock_domain_service.rb index d502d9e4925cf1227cb7bbbf0454e2938e2bcb98..e765fb7a86f91fc31385c99de471266ae321662e 100644 --- a/app/services/unblock_domain_service.rb +++ b/app/services/unblock_domain_service.rb @@ -13,6 +13,6 @@ class UnblockDomainService < BaseService scope = Account.by_domain_and_subdomains(domain_block.domain) scope.where(silenced_at: domain_block.created_at).in_batches.update_all(silenced_at: nil) unless domain_block.noop? - scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil) if domain_block.suspend? + scope.where(suspended_at: domain_block.created_at).in_batches.update_all(suspended_at: nil, suspension_origin: nil) if domain_block.suspend? end end diff --git a/app/services/unsuspend_account_service.rb b/app/services/unsuspend_account_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..ce9ee48ed11ec5771ea4f4376f09560d9dc6531c --- /dev/null +++ b/app/services/unsuspend_account_service.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +class UnsuspendAccountService < BaseService + def call(account) + @account = account + + unsuspend! + refresh_remote_account! + + return if @account.nil? + + merge_into_home_timelines! + merge_into_list_timelines! + publish_media_attachments! + end + + private + + def unsuspend! + @account.unsuspend! if @account.suspended? + end + + def refresh_remote_account! + return if @account.local? + + # While we had the remote account suspended, it could be that + # it got suspended on its origin, too. So, we need to refresh + # it straight away so it gets marked as remotely suspended in + # that case. + + @account.update!(last_webfingered_at: nil) + @account = ResolveAccountService.new.call(@account) + + # Worth noting that it is possible that the remote has not only + # been suspended, but deleted permanently, in which case + # @account would now be nil. + end + + def merge_into_home_timelines! + @account.followers_for_local_distribution.find_each do |follower| + FeedManager.instance.merge_into_home(@account, follower) + end + end + + def merge_into_list_timelines! + @account.lists_for_local_distribution.find_each do |list| + FeedManager.instance.merge_into_list(@account, list) + end + end + + def publish_media_attachments! + attachment_names = MediaAttachment.attachment_definitions.keys + + @account.media_attachments.find_each do |media_attachment| + attachment_names.each do |attachment_name| + attachment = media_attachment.public_send(attachment_name) + styles = [:original] | attachment.styles.keys + + next if attachment.blank? + + styles.each do |style| + case Paperclip::Attachment.default_options[:storage] + when :s3 + begin + attachment.s3_object(style).acl.put(acl: Paperclip::Attachment.default_options[:s3_permissions]) + rescue Aws::S3::Errors::NoSuchKey + Rails.logger.warn "Tried to change acl on non-existent key #{attachment.s3_object(style).key}" + end + when :fog + # Not supported + when :filesystem + begin + FileUtils.chmod(0o666 & ~File.umask, attachment.path(style)) unless attachment.path(style).nil? + rescue Errno::ENOENT + Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}" + end + end + + CacheBusterWorker.perform_async(attachment.path(style)) if Rails.configuration.x.cache_buster_enabled + end + end + end + end +end diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 4172d577408f4ae88aaeb91ab2fc8b64548f7313..77f794e1787dca244f09d211cab4809c062c8554 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -12,8 +12,8 @@ class UpdateAccountService < BaseService check_links(account) process_hashtags(account) end - rescue Mastodon::DimensionsValidationError => de - account.errors.add(:avatar, de.message) + rescue Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e + account.errors.add(:avatar, e.message) false end diff --git a/app/validators/blacklisted_email_validator.rb b/app/validators/blacklisted_email_validator.rb index 0d01a1c47fb7fb842542a5d0981fcb547dd1d06b..16e3abf1298ed080f586e486524a7f89673a68d3 100644 --- a/app/validators/blacklisted_email_validator.rb +++ b/app/validators/blacklisted_email_validator.rb @@ -6,7 +6,7 @@ class BlacklistedEmailValidator < ActiveModel::Validator @email = user.email - user.errors.add(:email, I18n.t('users.invalid_email')) if blocked_email? + user.errors.add(:email, I18n.t('users.blocked_email_provider')) if blocked_email? end private diff --git a/app/validators/email_mx_validator.rb b/app/validators/email_mx_validator.rb index 9b5009966833ac391ce42e631e836aefd7e43525..ef1554494cccbe535e2b69496d509bdb395adc90 100644 --- a/app/validators/email_mx_validator.rb +++ b/app/validators/email_mx_validator.rb @@ -4,22 +4,38 @@ require 'resolv' class EmailMxValidator < ActiveModel::Validator def validate(user) - user.errors.add(:email, I18n.t('users.invalid_email')) if invalid_mx?(user.email) + domain = get_domain(user.email) + + if domain.nil? + user.errors.add(:email, I18n.t('users.invalid_email')) + else + ips, hostnames = resolve_mx(domain) + if ips.empty? + user.errors.add(:email, I18n.t('users.invalid_email_mx')) + elsif on_blacklist?(hostnames + ips) + user.errors.add(:email, I18n.t('users.blocked_email_provider')) + end + end end private - def invalid_mx?(value) + def get_domain(value) _, domain = value.split('@', 2) - return true if domain.nil? + return nil if domain.nil? + + TagManager.instance.normalize_domain(domain) + rescue Addressable::URI::InvalidURIError + nil + end - domain = TagManager.instance.normalize_domain(domain) + def resolve_mx(domain) hostnames = [] ips = [] Resolv::DNS.open do |dns| - dns.timeouts = 1 + dns.timeouts = 5 hostnames = dns.getresources(domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } @@ -29,9 +45,7 @@ class EmailMxValidator < ActiveModel::Validator end end - ips.empty? || on_blacklist?(hostnames + ips) - rescue Addressable::URI::InvalidURIError - true + [ips, hostnames] end def on_blacklist?(values) diff --git a/app/validators/import_validator.rb b/app/validators/import_validator.rb new file mode 100644 index 0000000000000000000000000000000000000000..a182abfa5066ee85e4b4beda94d70de1dba0604d --- /dev/null +++ b/app/validators/import_validator.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class ImportValidator < ActiveModel::Validator + KNOWN_HEADERS = [ + 'Account address', + '#domain', + '#uri', + ].freeze + + def validate(import) + return if import.type.blank? || import.data.blank? + + # We parse because newlines could be part of individual rows. This + # runs on create so we should be reading the local file here before + # it is uploaded to object storage or moved anywhere... + csv_data = CSV.parse(import.data.queued_for_write[:original].read) + + row_count = csv_data.size + row_count -= 1 if KNOWN_HEADERS.include?(csv_data.first&.first) + + import.errors.add(:data, I18n.t('imports.errors.over_rows_processing_limit', count: ImportService::ROWS_PROCESSING_LIMIT)) if row_count > ImportService::ROWS_PROCESSING_LIMIT + + case import.type + when 'following' + validate_following_import(import, row_count) + end + end + + private + + def validate_following_import(import, row_count) + base_limit = FollowLimitValidator.limit_for_account(import.account) + + limit = begin + if import.overwrite? + base_limit + else + base_limit - import.account.following_count + end + end + + import.errors.add(:data, I18n.t('users.follow_limit_reached', limit: base_limit)) if row_count > limit + end +end diff --git a/app/validators/registration_form_time_validator.rb b/app/validators/registration_form_time_validator.rb new file mode 100644 index 0000000000000000000000000000000000000000..ba7c7e6c6462ecb837e85af2189ab0fa10fc2c7b --- /dev/null +++ b/app/validators/registration_form_time_validator.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class RegistrationFormTimeValidator < ActiveModel::Validator + REGISTRATION_FORM_MIN_TIME = 3.seconds.freeze + + def validate(user) + user.errors.add(:base, I18n.t('auth.too_fast')) if user.registration_form_time.present? && user.registration_form_time > REGISTRATION_FORM_MIN_TIME.ago + end +end diff --git a/app/views/about/_domain_blocks.html.haml b/app/views/about/_domain_blocks.html.haml index e0c5df41d632aa82219911c14db70af38e5be4f3..35a30f16eefd830b3f2cc8dd4154d508d0417609 100644 --- a/app/views/about/_domain_blocks.html.haml +++ b/app/views/about/_domain_blocks.html.haml @@ -7,6 +7,6 @@ - domain_blocks.each do |domain_block| %tr %td.nowrap - %span{ title: domain_block.domain }= domain_block.domain + %span{ title: "SHA-256: #{domain_block.domain_digest}" }= domain_block.public_domain %td = domain_block.public_comment if display_blocks_rationale? diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml index af28e21749133aec80e1826bf9f38d84ddadd60c..e4d614d71e7a7c17770d3b559c41cdff27bd8227 100644 --- a/app/views/about/_registration.html.haml +++ b/app/views/about/_registration.html.haml @@ -1,22 +1,25 @@ .simple_form__overlay-area{ class: (closed_registrations? && @instance_presenter.closed_registrations_message.present?) ? 'simple_form__overlay-area__blurred' : '' } - = simple_form_for(new_user, url: user_registration_path, namespace: 'registration') do |f| + = simple_form_for(new_user, url: user_registration_path, namespace: 'registration', html: { novalidate: false }) do |f| %p.lead= t('about.federation_hint_html', instance: content_tag(:strong, site_hostname)) .fields-group = f.simple_fields_for :account do |account_fields| - = account_fields.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, append: "@#{site_hostname}", hint: false, disabled: closed_registrations? + = account_fields.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, append: "@#{site_hostname}", hint: false, disabled: closed_registrations? = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? - = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off', :minlength => User.password_length.first, :maxlength => User.password_length.last }, hint: false, disabled: closed_registrations? = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + = f.input :website, as: :url, placeholder: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: 'Website'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations? + - if approved_registrations? .fields-group = f.simple_fields_for :invite_request do |invite_request_fields| - = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false + = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text .fields-group - = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), disabled: closed_registrations? + = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), required: true, disabled: closed_registrations? .actions = f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations? diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index 4152a360170dc77efafc64ebccf9b8a1037d6186..109b5fa863fb548739eea79459a09e4716b4a82a 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -2,7 +2,7 @@ = site_hostname - content_for :header_tags do - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' = render partial: 'shared/og' .grid-4 @@ -17,11 +17,11 @@ .row__information-board .information-board__section %span= t 'about.user_count_before' - %strong= number_with_delimiter @instance_presenter.user_count + %strong= number_to_human @instance_presenter.user_count, strip_insignificant_zeros: true %span= t 'about.user_count_after', count: @instance_presenter.user_count .information-board__section %span= t 'about.status_count_before' - %strong= number_with_delimiter @instance_presenter.status_count + %strong= number_to_human @instance_presenter.status_count, strip_insignificant_zeros: true %span= t 'about.status_count_after', count: @instance_presenter.status_count .row__mascot .landing-page__mascot diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index c9688ea88d55b6cbf783a7ee9b3ddd1b5bc03fa4..1a81b96f6c90fc420abccdc2c5fd0419ca3a4f1e 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -39,12 +39,12 @@ = render partial: 'statuses/status', collection: @pinned_statuses, as: :status, locals: { pinned: true } - if @newer_url - .entry= link_to_more @newer_url + .entry= link_to_newer @newer_url = render partial: 'statuses/status', collection: @statuses, as: :status - if @older_url - .entry= link_to_more @older_url + .entry= link_to_older @older_url .column-1 - if @account.memorial? diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index e6461aad04de5c7b03b8dd9e3e9274bb8776deba..27e1f80a722fe8b4a82433af4f4afc5f159a05c7 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -1,6 +1,10 @@ - content_for :page_title do = @account.acct +- if @account.instance_actor? + .flash-message.notice + %strong= t('accounts.instance_actor_flash') + = render 'application/card', account: @account - account = @account @@ -56,19 +60,23 @@ = link_to admin_action_logs_path(target_account_id: @account.id) do .dashboard__counters__text - if @account.local? && @account.user.nil? - %span.neutral= t('admin.accounts.deleted') + = t('admin.accounts.deleted') + - elsif @account.memorial? + = t('admin.accounts.memorialized') - elsif @account.suspended? - %span.red= t('admin.accounts.suspended') + = t('admin.accounts.suspended') - elsif @account.silenced? - %span.red= t('admin.accounts.silenced') + = t('admin.accounts.silenced') - elsif @account.local? && @account.user&.disabled? - %span.red= t('admin.accounts.disabled') + = t('admin.accounts.disabled') - elsif @account.local? && !@account.user&.confirmed? - %span.neutral= t('admin.accounts.confirming') + = t('admin.accounts.confirming') - elsif @account.local? && !@account.user_approved? - %span.neutral= t('admin.accounts.pending') + = t('admin.accounts.pending') + - elsif @account.sensitized? + = t('admin.accounts.sensitive') - else - %span.neutral= t('admin.accounts.no_limits_imposed') + = t('admin.accounts.no_limits_imposed') .dashboard__counters__label= t 'admin.accounts.login_status' - unless @account.local? && @account.user.nil? @@ -122,19 +130,6 @@ = t('admin.accounts.confirming') %td= table_link_to 'refresh', t('admin.accounts.resend_confirmation.send'), resend_admin_account_confirmation_path(@account.id), method: :post if can?(:confirm, @account.user) - %tr - %th= t('admin.accounts.login_status') - %td - - if @account.user&.disabled? - = t('admin.accounts.disabled') - - else - = t('admin.accounts.enabled') - %td - - if @account.user&.disabled? - = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user) - - elsif @account.user_approved? - = table_link_to 'lock', t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable') if can?(:disable, @account.user) - %tr %th= t('simple_form.labels.defaults.locale') %td= @account.user_locale @@ -172,49 +167,67 @@ %td = @account.inbox_url = fa_icon DeliveryFailureTracker.available?(@account.inbox_url) ? 'check' : 'times' + %td + = table_link_to 'search', @domain_block.present? ? t('admin.domain_blocks.view') : t('admin.accounts.view_domain'), admin_instance_path(@account.domain) %tr %th= t('admin.accounts.shared_inbox_url') %td = @account.shared_inbox_url = fa_icon DeliveryFailureTracker.available?(@account.shared_inbox_url) ? 'check': 'times' + %td + - if @domain_block.nil? + = table_link_to 'ban', t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @account.domain) + + - if @account.suspended? + %hr.spacer/ + + %p.muted-hint= @deletion_request.present? ? t('admin.accounts.suspension_reversible_hint_html', date: content_tag(:strong, l(@deletion_request.due_at.to_date))) : t('admin.accounts.suspension_irreversible') + + = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsuspend, @account) + + - if @deletion_request.present? + = link_to t('admin.accounts.delete'), admin_account_path(@account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, @account) + - else + %div.action-buttons + %div + - if @account.local? && @account.user_approved? + = link_to t('admin.accounts.warn'), new_admin_account_action_path(@account.id, type: 'none'), class: 'button' if can?(:warn, @account) + + - if @account.user_disabled? + = link_to t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post, class: 'button' if can?(:enable, @account.user) + - else + = link_to t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable'), class: 'button' if can?(:disable, @account.user) + + - if @account.sensitized? + = link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsensitive, @account) + - elsif !@account.local? || @account.user_approved? + = link_to t('admin.accounts.sensitive'), new_admin_account_action_path(@account.id, type: 'sensitive'), class: 'button' if can?(:sensitive, @account) + + - if @account.silenced? + = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account) + - elsif !@account.local? || @account.user_approved? + = link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button' if can?(:silence, @account) + + - if @account.local? + - if @account.user_pending? + = link_to t('admin.accounts.approve'), approve_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, @account.user) + = link_to t('admin.accounts.reject'), reject_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, @account.user) + + - unless @account.user_confirmed? + = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user) - %div.action-buttons - %div - - if @account.local? && @account.user_approved? - = link_to t('admin.accounts.warn'), new_admin_account_action_path(@account.id, type: 'none'), class: 'button' if can?(:warn, @account) - - if @account.silenced? - = link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account) - - elsif !@account.local? || @account.user_approved? - = link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button button--destructive' if can?(:silence, @account) - - - if @account.local? - - if @account.user_pending? - = link_to t('admin.accounts.approve'), approve_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, @account.user) - = link_to t('admin.accounts.reject'), reject_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, @account.user) - - - unless @account.user_confirmed? - = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user) - - - if @account.suspended? - = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsuspend, @account) - - elsif !@account.local? || @account.user_approved? - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button button--destructive' if can?(:suspend, @account) - - - unless @account.local? - - if DomainBlock.rule_for(@account.domain) - = link_to t('admin.domain_blocks.view'), admin_instance_path(@account.domain), class: 'button' + - if !@account.local? || @account.user_approved? + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button' if can?(:suspend, @account) + + %div + - if @account.local? + = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' if can?(:reset_password, @account.user) + - if @account.user&.otp_required_for_login? + = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) + - if !@account.memorial? && @account.user_approved? + = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) - else - = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @account.domain), class: 'button button--destructive' - - %div - - if @account.local? - = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' if can?(:reset_password, @account.user) - - if @account.user&.otp_required_for_login? - = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) - - if !@account.memorial? && @account.user_approved? - = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) - - else - = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' if can?(:redownload, @account) + = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button' if can?(:redownload, @account) %hr.spacer/ @@ -233,3 +246,13 @@ .actions = f.button :button, t('admin.account_moderation_notes.create'), type: :submit + + %hr.spacer/ + + - if @account.user&.invite_request&.text&.present? + %div.speech-bubble + %div.speech-bubble__bubble + = @account.user&.invite_request&.text + %div.speech-bubble__owner + = admin_account_link_to @account + = t('admin.accounts.invite_request_text') diff --git a/app/views/admin/action_logs/index.html.haml b/app/views/admin/action_logs/index.html.haml index 99f756762958b96b2745d350eb9f8ba6c3e24cf9..e7d9054d9f8beb1d4c9ffcdd70106e528e08303d 100644 --- a/app/views/admin/action_logs/index.html.haml +++ b/app/views/admin/action_logs/index.html.haml @@ -2,7 +2,7 @@ = t('admin.action_logs.title') - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' = form_tag admin_action_logs_url, method: 'GET', class: 'simple_form' do = hidden_field_tag :target_account_id, params[:target_account_id] if params[:target_account_id].present? diff --git a/app/views/admin/custom_emojis/index.html.haml b/app/views/admin/custom_emojis/index.html.haml index 1cbc36f97ec4650632210e4527c820ee51ea94cf..bfec0407ef2aa4e3a060a1826a6ca1e1e560d522 100644 --- a/app/views/admin/custom_emojis/index.html.haml +++ b/app/views/admin/custom_emojis/index.html.haml @@ -2,7 +2,7 @@ = t('admin.custom_emojis.title') - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - if can?(:create, :custom_emoji) - content_for :heading_actions do diff --git a/app/views/admin/domain_allows/new.html.haml b/app/views/admin/domain_allows/new.html.haml index 52599857aabc43b8a55733c84e6c0200a272059c..249a961cee85bb0ec58bbb618a69044f247e1192 100644 --- a/app/views/admin/domain_allows/new.html.haml +++ b/app/views/admin/domain_allows/new.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('admin.domain_allows.add_new') diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml index 29e47ef3bdd78af7919145bd00f498f13449752b..6fe2edc8218914c7297a1c188b65bbbb7221210a 100644 --- a/app/views/admin/domain_blocks/edit.html.haml +++ b/app/views/admin/domain_blocks/edit.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('admin.domain_blocks.edit') @@ -20,6 +20,9 @@ .fields-group = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint') + .fields-group + = f.input :obfuscate, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.obfuscate'), hint: I18n.t('admin.domain_blocks.obfuscate_hint') + .field-group = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6 diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml index ed1581936a8fac4e9b60df1c57a13e337e3f9592..8b78f71f2d24e2dfad26c2e49ba4d7e61559bf09 100644 --- a/app/views/admin/domain_blocks/new.html.haml +++ b/app/views/admin/domain_blocks/new.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('.title') @@ -20,6 +20,9 @@ .fields-group = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint') + .fields-group + = f.input :obfuscate, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.obfuscate'), hint: I18n.t('admin.domain_blocks.obfuscate_hint') + .field-group = f.input :private_comment, wrapper: :with_label, label: I18n.t('admin.domain_blocks.private_comment'), hint: t('admin.domain_blocks.private_comment_hint'), rows: 6 diff --git a/app/views/admin/instances/_instance.html.haml b/app/views/admin/instances/_instance.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..188d0d9841df229ae6e22f07db5681ffea1fdaa6 --- /dev/null +++ b/app/views/admin/instances/_instance.html.haml @@ -0,0 +1,25 @@ +.directory__tag + = link_to admin_instance_path(instance) do + %h4 + = instance.domain + %small + - if instance.domain_block + - first_item = true + - if !instance.domain_block.noop? + = t("admin.domain_blocks.severity.#{instance.domain_block.severity}") + - first_item = false + - unless instance.domain_block.suspend? + - if instance.domain_block.reject_media? + - unless first_item + • + = t('admin.domain_blocks.rejecting_media') + - first_item = false + - if instance.domain_block.reject_reports? + - unless first_item + • + = t('admin.domain_blocks.rejecting_reports') + - elsif whitelist_mode? + = t('admin.accounts.whitelisted') + - else + = t('admin.accounts.no_limits_imposed') + .trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= number_to_human instance.accounts_count, strip_insignificant_zeros: true diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml index 696ba3c7febf72d19c72522b17b462fd4ea5902c..5f20e7ec04559d47ff381fbe2123369039aa1f84 100644 --- a/app/views/admin/instances/index.html.haml +++ b/app/views/admin/instances/index.html.haml @@ -32,32 +32,10 @@ %hr.spacer/ -- @instances.each do |instance| - .directory__tag - = link_to admin_instance_path(instance) do - %h4 - = instance.domain - %small - - if instance.domain_block - - first_item = true - - if !instance.domain_block.noop? - = t("admin.domain_blocks.severity.#{instance.domain_block.severity}") - - first_item = false - - unless instance.domain_block.suspend? - - if instance.domain_block.reject_media? - - unless first_item - • - = t('admin.domain_blocks.rejecting_media') - - first_item = false - - if instance.domain_block.reject_reports? - - unless first_item - • - = t('admin.domain_blocks.rejecting_reports') - - elsif whitelist_mode? - = t('admin.accounts.whitelisted') - - else - = t('admin.accounts.no_limits_imposed') - - if instance.countable? - .trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= number_to_human instance.accounts_count, strip_insignificant_zeros: true - -= paginate paginated_instances +- if @instances.empty? + %div.muted-hint.center-text + = t 'admin.instances.empty' +- else + = render @instances + += paginate @instances diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml index 92e14c0df06b16efee5d1130b3b8e3eed370a5c6..0b9382771bb50d370746755698b1ea28930cb087 100644 --- a/app/views/admin/instances/show.html.haml +++ b/app/views/admin/instances/show.html.haml @@ -2,58 +2,60 @@ = @instance.domain .dashboard__counters + %div + = link_to admin_accounts_path(remote: '1', by_domain: @instance.domain) do + .dashboard__counters__num= number_with_delimiter @instance.accounts_count + .dashboard__counters__label= t 'admin.accounts.title' + %div + = link_to admin_reports_path(by_target_domain: @instance.domain) do + .dashboard__counters__num= number_with_delimiter @instance.reports_count + .dashboard__counters__label= t 'admin.instances.total_reported' %div %div - .dashboard__counters__num= number_with_delimiter @following_count - .dashboard__counters__label= t 'admin.instances.total_followed_by_them' + .dashboard__counters__num= number_to_human_size @instance.media_storage + .dashboard__counters__label= t 'admin.instances.total_storage' %div %div - .dashboard__counters__num= number_with_delimiter @followers_count - .dashboard__counters__label= t 'admin.instances.total_followed_by_us' + .dashboard__counters__num= number_with_delimiter @instance.following_count + .dashboard__counters__label= t 'admin.instances.total_followed_by_them' %div %div - .dashboard__counters__num= number_to_human_size @media_storage - .dashboard__counters__label= t 'admin.instances.total_storage' + .dashboard__counters__num= number_with_delimiter @instance.followers_count + .dashboard__counters__label= t 'admin.instances.total_followed_by_us' %div %div - .dashboard__counters__num= number_with_delimiter @blocks_count + .dashboard__counters__num= number_with_delimiter @instance.blocks_count .dashboard__counters__label= t 'admin.instances.total_blocked_by_us' - %div - = link_to admin_reports_path(by_target_domain: @instance.domain) do - .dashboard__counters__num= number_with_delimiter @reports_count - .dashboard__counters__label= t 'admin.instances.total_reported' + %div %div .dashboard__counters__num - - if @available + - if @instance.delivery_failure_tracker.available? = fa_icon 'check' - else = fa_icon 'times' .dashboard__counters__label= t 'admin.instances.delivery_available' -- if @private_comment.present? +- if @instance.private_comment.present? .speech-bubble .speech-bubble__bubble - = simple_format(h(@private_comment)) + = simple_format(h(@instance.private_comment)) .speech-bubble__owner= t 'admin.instances.private_comment' -- if @public_comment.present? +- if @instance.public_comment.present? .speech-bubble .speech-bubble__bubble - = simple_format(h(@public_comment)) + = simple_format(h(@instance.public_comment)) .speech-bubble__owner= t 'admin.instances.public_comment' %hr.spacer/ %div.action-buttons %div - = link_to t('admin.accounts.title'), admin_accounts_path(remote: '1', by_domain: @instance.domain), class: 'button' - - %div - - if @domain_allow - = link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete } - - elsif @domain_block - = link_to t('admin.domain_blocks.edit'), edit_admin_domain_block_path(@domain_block), class: 'button' - = link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@domain_block), class: 'button' + - if @instance.domain_allow + = link_to t('admin.domain_allows.undo'), admin_domain_allow_path(@instance.domain_allow), class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure'), method: :delete } + - elsif @instance.domain_block + = link_to t('admin.domain_blocks.edit'), edit_admin_domain_block_path(@instance.domain_block), class: 'button' + = link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@instance.domain_block), class: 'button' - else = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button' diff --git a/app/views/admin/ip_blocks/_ip_block.html.haml b/app/views/admin/ip_blocks/_ip_block.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..e07e2b4448b726928acbc7c9f6ec51d5372fad6c --- /dev/null +++ b/app/views/admin/ip_blocks/_ip_block.html.haml @@ -0,0 +1,11 @@ +.batch-table__row + %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox + = f.check_box :ip_block_ids, { multiple: true, include_hidden: false }, ip_block.id + .batch-table__row__content + .batch-table__row__content__text + %samp= "#{ip_block.ip}/#{ip_block.ip.prefix}" + - if ip_block.comment.present? + • + = ip_block.comment + %br/ + = t("simple_form.labels.ip_block.severities.#{ip_block.severity}") diff --git a/app/views/admin/ip_blocks/index.html.haml b/app/views/admin/ip_blocks/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..d5b983de9ec079750a67fcfe381cfd2e9cfd3209 --- /dev/null +++ b/app/views/admin/ip_blocks/index.html.haml @@ -0,0 +1,28 @@ +- content_for :page_title do + = t('admin.ip_blocks.title') + +- content_for :header_tags do + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' + +- if can?(:create, :ip_block) + - content_for :heading_actions do + = link_to t('admin.ip_blocks.add_new'), new_admin_ip_block_path, class: 'button' + += form_for(@form, url: batch_admin_ip_blocks_path) do |f| + = hidden_field_tag :page, params[:page] || 1 + + .batch-table + .batch-table__toolbar + %label.batch-table__toolbar__select.batch-checkbox-all + = check_box_tag :batch_checkbox_all, nil, false + .batch-table__toolbar__actions + - if can?(:destroy, :ip_block) + = f.button safe_join([fa_icon('times'), t('admin.ip_blocks.delete')]), name: :delete, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } + .batch-table__body + - if @ip_blocks.empty? + = nothing_here 'nothing-here--under-tabs' + - else + = render partial: 'ip_block', collection: @ip_blocks, locals: { f: f } + += paginate @ip_blocks + diff --git a/app/views/admin/ip_blocks/new.html.haml b/app/views/admin/ip_blocks/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..69f6b98b9b676f2f38262ef8479db29e93d7bf77 --- /dev/null +++ b/app/views/admin/ip_blocks/new.html.haml @@ -0,0 +1,20 @@ +- content_for :page_title do + = t('.title') + += simple_form_for @ip_block, url: admin_ip_blocks_path do |f| + = render 'shared/error_messages', object: @ip_block + + .fields-group + = f.input :ip, as: :string, wrapper: :with_block_label, input_html: { placeholder: '192.0.2.0/24' } + + .fields-group + = f.input :expires_in, wrapper: :with_block_label, collection: [1.day, 2.weeks, 1.month, 6.months, 1.year, 3.years].map(&:to_i), label_method: lambda { |i| I18n.t("admin.ip_blocks.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt') + + .fields-group + = f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: lambda { |severity| safe_join([I18n.t("simple_form.labels.ip_block.severities.#{severity}"), content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint')]) } + + .fields-group + = f.input :comment, as: :string, wrapper: :with_block_label + + .actions + = f.button :button, t('admin.ip_blocks.add_new'), type: :submit diff --git a/app/views/admin/pending_accounts/_account.html.haml b/app/views/admin/pending_accounts/_account.html.haml index 7a9796a6741b96c2019ab7d4439810ebb5ff602e..5b475b59a90107ab95d2a57c9f7e13f33ad463ca 100644 --- a/app/views/admin/pending_accounts/_account.html.haml +++ b/app/views/admin/pending_accounts/_account.html.haml @@ -7,7 +7,7 @@ %strong= account.user_email = "(@#{account.username})" %br/ - = account.user_current_sign_in_ip + %samp= account.user_current_sign_in_ip • = t 'admin.accounts.time_in_queue', time: time_ago_in_words(account.user&.created_at) diff --git a/app/views/admin/pending_accounts/index.html.haml b/app/views/admin/pending_accounts/index.html.haml index 79ae4a320fccc4639045b60c8a31d59e6230f36d..8384a1c9f012f5c233712ab91bb97ef97ef9fe4c 100644 --- a/app/views/admin/pending_accounts/index.html.haml +++ b/app/views/admin/pending_accounts/index.html.haml @@ -2,7 +2,7 @@ = t('admin.pending_accounts.title', count: User.pending.count) - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' = form_for(@form, url: batch_admin_pending_accounts_path) do |f| = hidden_field_tag :page, params[:page] || 1 diff --git a/app/views/admin/reports/_status.html.haml b/app/views/admin/reports/_status.html.haml index fa15796d280b9aad6303d351cd4459ec30132ba4..ada6dd2bc549f9b3ab43ae7e1369b7a4826ee0ff 100644 --- a/app/views/admin/reports/_status.html.haml +++ b/app/views/admin/reports/_status.html.haml @@ -14,7 +14,7 @@ - unless status.proper.media_attachments.empty? - if status.proper.media_attachments.first.video? - video = status.proper.media_attachments.first - = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: status.proper.sensitive?, visible: false, width: 610, height: 343, inline: true, alt: video.description + = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: status.proper.sensitive?, visible: false, width: 610, height: 343, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json - elsif status.proper.media_attachments.first.audio? - audio = status.proper.media_attachments.first = react_component :audio, src: audio.file.url(:original), height: 110, alt: audio.description, duration: audio.file.meta.dig(:original, :duration) diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml index bb441380ec76870f4df401e6043ebe95baf1d0d0..721c55f71a6c4f86e6f06c03f92d5c39cbfe8769 100644 --- a/app/views/admin/reports/index.html.haml +++ b/app/views/admin/reports/index.html.haml @@ -59,6 +59,10 @@ = fa_icon('camera') = report.media_attachments.count + - if report.forwarded? + · + = t('admin.reports.forwarded_to', domain: target_account.domain) + .report-card__summary__item__assigned - if report.assigned_account.present? = admin_account_link_to report.assigned_account diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index 0d563eea77749548a8751ae79d5560bafb4715cb..b060c553f09df03ee32f470074ba10c768a516b4 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('admin.reports.report', id: @report.id) @@ -46,6 +46,16 @@ %td{ colspan: 2 } - if @report.action_taken? = table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put + - unless @report.target_account.local? + %tr + %th= t('admin.reports.forwarded') + %td{ colspan: 3 } + - if @report.forwarded.nil? + \- + - elsif @report.forwarded? + = t('simple_form.yes') + - else + = t('simple_form.no') - if !@report.action_taken_by_account.nil? %tr %th= t('admin.reports.action_taken_by') diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index f37775aa985a7bca1866fce95b936dc51d3c9591..159bd4b0a0d011aba7ea90b5637e99d20aafa3b5 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('admin.settings.title') @@ -44,7 +44,14 @@ %hr.spacer/ .fields-group - = f.input :enable_bootstrap_timeline_accounts, as: :boolean, wrapper: :with_label, label: t('admin.settings.enable_bootstrap_timeline_accounts.title') + = f.input :require_invite_text, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.require_invite_text.title'), hint: t('admin.settings.registrations.require_invite_text.desc_html'), disabled: !approved_registrations? + .fields-group + + %hr.spacer/ + + .fields-group + = f.input :enable_bootstrap_timeline_accounts, as: :boolean, wrapper: :with_label, label: t('admin.settings.enable_bootstrap_timeline_accounts.title'), hint: t('admin.settings.enable_bootstrap_timeline_accounts.desc_html') + .fields-group = f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html'), disabled: !Setting.enable_bootstrap_timeline_accounts diff --git a/app/views/admin/statuses/index.html.haml b/app/views/admin/statuses/index.html.haml index f1169a2fdecca46d5da81fc9ab6be1f63b916b17..c39ba9071fce14f297c87150e0f089ba1eb27404 100644 --- a/app/views/admin/statuses/index.html.haml +++ b/app/views/admin/statuses/index.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' - content_for :page_title do = t('admin.statuses.title') diff --git a/app/views/admin/tags/index.html.haml b/app/views/admin/tags/index.html.haml index f888a311dbf8c5f9b6e3c3e30f957ccf63e5d726..d7719d45d62d1ad65a3eff56f5cc37823f7ed2e7 100644 --- a/app/views/admin/tags/index.html.haml +++ b/app/views/admin/tags/index.html.haml @@ -2,7 +2,7 @@ = t('admin.tags.title') - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' .filters .filter-subset diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml index 383d44f00fa3f9ae49109f2c7e9b2ddf40d09bbe..114a74454223dc283a6d24ce67e7f9ac6a8f66e4 100644 --- a/app/views/auth/passwords/edit.html.haml +++ b/app/views/auth/passwords/edit.html.haml @@ -1,14 +1,14 @@ - content_for :page_title do = t('auth.set_new_password') -= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| += simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, novalidate: false }) do |f| = render 'shared/error_messages', object: resource - if !use_seamless_external_login? || resource.encrypted_password.present? = f.input :reset_password_token, as: :hidden .fields-group - = f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }, required: true + = f.input :password, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off', :minlength => User.password_length.first, :maxlength => User.password_length.last }, required: true .fields-group = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }, required: true diff --git a/app/views/auth/registrations/_sessions.html.haml b/app/views/auth/registrations/_sessions.html.haml index 395e36a9fd6d07373a3e4ca01bad451bab6b31d5..d3a04c00e7eceb98a6e30e0ec792066cce51e289 100644 --- a/app/views/auth/registrations/_sessions.html.haml +++ b/app/views/auth/registrations/_sessions.html.haml @@ -27,5 +27,5 @@ - else %time.time-ago{ datetime: session.updated_at.iso8601, title: l(session.updated_at) }= l(session.updated_at) %td - - if current_session.session_id != session.session_id + - if current_session.session_id != session.session_id && !current_account.suspended? = table_link_to 'times', t('sessions.revoke'), settings_session_path(session), method: :delete diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml index a155c75c987e9c69d220e905a66c3d0093f97543..a3445b421aa1f0bb039e19af422c1ce548316763 100644 --- a/app/views/auth/registrations/edit.html.haml +++ b/app/views/auth/registrations/edit.html.haml @@ -5,7 +5,7 @@ %h3= t('auth.security') -= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit' }) do |f| += simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit', novalidate: false }) do |f| = render 'shared/error_messages', object: resource - if !use_seamless_external_login? || resource.encrypted_password.present? @@ -17,7 +17,7 @@ .fields-row .fields-row__column.fields-group.fields-row__column-6 - = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }, hint: t('simple_form.hints.defaults.password'), disabled: current_account.suspended? + = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off', :minlength => User.password_length.first, :maxlength => User.password_length.last }, hint: t('simple_form.hints.defaults.password'), disabled: current_account.suspended? .fields-row__column.fields-group.fields-row__column-6 = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }, disabled: current_account.suspended? @@ -30,18 +30,19 @@ = render 'sessions' -%hr.spacer/ +- unless current_account.suspended? + %hr.spacer/ -%h3= t('auth.migrate_account') -%p.muted-hint= t('auth.migrate_account_html', path: settings_migration_path) + %h3= t('auth.migrate_account') + %p.muted-hint= t('auth.migrate_account_html', path: settings_migration_path) -%hr.spacer/ + %hr.spacer/ -%h3= t('migrations.incoming_migrations') -%p.muted-hint= t('migrations.incoming_migrations_html', path: settings_aliases_path) + %h3= t('migrations.incoming_migrations') + %p.muted-hint= t('migrations.incoming_migrations_html', path: settings_aliases_path) -- if open_deletion? && !current_account.suspended? - %hr.spacer/ + - if open_deletion? + %hr.spacer/ - %h3= t('auth.delete_account') - %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path) + %h3= t('auth.delete_account') + %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path) diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml index 457bc1d2314129b145de64504a158b8650f3b5cf..6981195ed90f212e29e54efb411f4632197abcbb 100644 --- a/app/views/auth/registrations/new.html.haml +++ b/app/views/auth/registrations/new.html.haml @@ -4,7 +4,7 @@ - content_for :header_tags do = render partial: 'shared/og', locals: { description: description_for_sign_up } -= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| += simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { novalidate: false }) do |f| = render 'shared/error_messages', object: resource - if @invite.present? && @invite.autofollow? @@ -14,26 +14,29 @@ = f.simple_fields_for :account do |ff| .fields-group - = ff.input :username, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' }, append: "@#{site_hostname}", hint: t('simple_form.hints.defaults.username', domain: site_hostname) + = ff.input :username, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, append: "@#{site_hostname}", hint: t('simple_form.hints.defaults.username', domain: site_hostname) .fields-group = f.input :email, wrapper: :with_label, label: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' } .fields-group - = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' } + = f.input :password, wrapper: :with_label, label: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off', :minlength => User.password_length.first, :maxlength => User.password_length.last } .fields-group = f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' } + = f.input :confirm_password, as: :string, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), :autocomplete => 'off' } + + = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label' => t('simple_form.labels.defaults.honeypot', label: 'Website'), :autocomplete => 'off' } - if approved_registrations? && !@invite.present? .fields-group = f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields| - = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false + = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: Setting.require_invite_text = f.input :invite_code, as: :hidden .fields-group - = f.input :agreement, as: :boolean, wrapper: :with_label, label: whitelist_mode? ? t('auth.checkbox_agreement_without_rules_html', terms_path: terms_path) : t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path) + = f.input :agreement, as: :boolean, wrapper: :with_label, label: whitelist_mode? ? t('auth.checkbox_agreement_without_rules_html', terms_path: terms_path) : t('auth.checkbox_agreement_html', rules_path: about_more_path, terms_path: terms_path), required: true .actions = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml index ceb1694084bee70ebe50a7cfdb41623d6282465f..9713bdaebfd41de17302b32c9383e6382af7ec64 100644 --- a/app/views/auth/sessions/new.html.haml +++ b/app/views/auth/sessions/new.html.haml @@ -22,7 +22,6 @@ .actions - resource_class.omniauth_providers.each do |provider| - = link_to omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}" do - = t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize) + = link_to t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize), omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}", method: :post .form-footer= render 'auth/shared/links' diff --git a/app/views/auth/sessions/two_factor.html.haml b/app/views/auth/sessions/two_factor.html.haml index b2e36f6bca4e5e011a1f935afaa468cb16feeef6..b897a0422e23c1ca5ab1b472b84478656a9ea53b 100644 --- a/app/views/auth/sessions/two_factor.html.haml +++ b/app/views/auth/sessions/two_factor.html.haml @@ -1,14 +1,9 @@ - content_for :page_title do = t('auth.login') -= simple_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f| - %p.hint.otp-hint= t('simple_form.hints.sessions.otp') +=javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous' - .fields-group - = f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt'), :autocomplete => 'off' }, autofocus: true +- if @webauthn_enabled + = render partial: 'auth/sessions/two_factor/webauthn_form', locals: { hidden: @scheme_type != 'webauthn' } - .actions - = f.button :button, t('auth.login'), type: :submit - - - if Setting.site_contact_email.present? - %p.hint.subtle-hint= t('users.otp_lost_help_html', email: mail_to(Setting.site_contact_email, nil)) += render partial: 'auth/sessions/two_factor/otp_authentication_form', locals: { hidden: @scheme_type != 'totp' } diff --git a/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..ab2d48c0a3ebce1ca84b4a33fa8139a49661025c --- /dev/null +++ b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml @@ -0,0 +1,18 @@ += simple_form_for(resource, + as: resource_name, + url: session_path(resource_name), + html: { method: :post, id: 'otp-authentication-form' }.merge(hidden ? { class: 'hidden' } : {})) do |f| + %p.hint.authentication-hint= t('simple_form.hints.sessions.otp') + + .fields-group + = f.input :otp_attempt, type: :number, wrapper: :with_label, label: t('simple_form.labels.defaults.otp_attempt'), input_html: { 'aria-label' => t('simple_form.labels.defaults.otp_attempt'), :autocomplete => 'off' }, autofocus: true + + .actions + = f.button :button, t('auth.login'), type: :submit + + - if Setting.site_contact_email.present? + %p.hint.subtle-hint= t('users.otp_lost_help_html', email: mail_to(Setting.site_contact_email, nil)) + + - if @webauthn_enabled + .form-footer + = link_to(t('auth.link_to_webauth'), '#', id: 'link-to-webauthn') diff --git a/app/views/auth/sessions/two_factor/_webauthn_form.html.haml b/app/views/auth/sessions/two_factor/_webauthn_form.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..32ed1294aa424f3cf30cd5c817a1e7a88039cc91 --- /dev/null +++ b/app/views/auth/sessions/two_factor/_webauthn_form.html.haml @@ -0,0 +1,17 @@ +%p.flash-message.hidden#unsupported-browser-message= t 'webauthn_credentials.not_supported' +%p.flash-message.alert.hidden#security-key-error-message= t 'webauthn_credentials.invalid_credential' + + += simple_form_for(resource, + as: resource_name, + url: session_path(resource_name), + html: { method: :post, id: 'webauthn-form' }.merge(hidden ? { class: 'hidden' } : {})) do |f| + %h3.title= t('simple_form.title.sessions.webauthn') + %p.hint= t('simple_form.hints.sessions.webauthn') + + .actions + = f.button :button, t('auth.use_security_key'), class: 'js-webauthn', type: :submit + + .form-footer + %p= t('auth.dont_have_your_security_key') + = link_to(t('auth.link_to_otp'), '#', id: 'link-to-otp') diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 30c7aab194f3aa6365f1839ebe5634cfbc184051..94cc782b2b7fe06518e075d99d13be4fe696594f 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1,12 +1,12 @@ - content_for :header_tags do - = preload_link_tag asset_pack_path('features/getting_started.js'), crossorigin: 'anonymous' - = preload_link_tag asset_pack_path('features/compose.js'), crossorigin: 'anonymous' - = preload_link_tag asset_pack_path('features/home_timeline.js'), crossorigin: 'anonymous' - = preload_link_tag asset_pack_path('features/notifications.js'), crossorigin: 'anonymous' + = preload_pack_asset 'features/getting_started.js', crossorigin: 'anonymous' + = preload_pack_asset 'features/compose.js', crossorigin: 'anonymous' + = preload_pack_asset 'features/home_timeline.js', crossorigin: 'anonymous' + = preload_pack_asset 'features/notifications.js', crossorigin: 'anonymous' %meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key} = render_initial_state - = javascript_pack_tag 'application', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'application', crossorigin: 'anonymous' .app-holder#mastodon{ data: { props: Oj.dump(default_props) } } %noscript diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index b1a2d0617ff23e1b401a344e9a158f7a34aa19ec..62716ab1ee01b403d8c1d51b48f70d8ee850588d 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -1,6 +1,6 @@ - content_for :header_tags do = render_initial_state - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' - content_for :content do .admin-wrapper diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e32cdcabb3f6017d6b499c14924a21ddaa8084fb..9501207e0818b373e699ec1e588b3a67ff27ae3d 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -6,6 +6,7 @@ - if cdn_host? %link{ rel: 'dns-prefetch', href: cdn_host }/ + %meta{ name: 'cdn-host', content: cdn_host }/ - if storage_host? %link{ rel: 'dns-prefetch', href: storage_host }/ @@ -20,10 +21,10 @@ %title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title - = stylesheet_pack_tag 'common', media: 'all' - = stylesheet_pack_tag current_theme, media: 'all' - = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous' - = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous' + = stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous' + = stylesheet_pack_tag current_theme, media: 'all', crossorigin: 'anonymous' + = javascript_pack_tag 'common', crossorigin: 'anonymous' + = javascript_pack_tag "locale_#{I18n.locale}", crossorigin: 'anonymous' = csrf_meta_tags %meta{ name: 'style-nonce', content: request.content_security_policy_nonce } diff --git a/app/views/layouts/auth.html.haml b/app/views/layouts/auth.html.haml index 585e246557a4de1dcef951c5a4e275a781facc72..0ea3bbe3b07069112a502e7e66a58f9d873cc6cd 100644 --- a/app/views/layouts/auth.html.haml +++ b/app/views/layouts/auth.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' - content_for :content do .container-alt diff --git a/app/views/layouts/embedded.html.haml b/app/views/layouts/embedded.html.haml index 4a40b8584b407d9815b3da2674ce1421ed670d45..e4311d342c82ab999922489e6b439f20feb1e404 100644 --- a/app/views/layouts/embedded.html.haml +++ b/app/views/layouts/embedded.html.haml @@ -6,12 +6,13 @@ - if cdn_host? %link{ rel: 'dns-prefetch', href: cdn_host }/ + %meta{ name: 'cdn-host', content: cdn_host }/ - if storage_host? %link{ rel: 'dns-prefetch', href: storage_host }/ - = stylesheet_pack_tag 'common', media: 'all' - = stylesheet_pack_tag Setting.default_settings['theme'], media: 'all' + = stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous' + = stylesheet_pack_tag Setting.default_settings['theme'], media: 'all', crossorigin: 'anonymous' = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous' = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous' = render_initial_state diff --git a/app/views/layouts/error.html.haml b/app/views/layouts/error.html.haml index 25c85abf9e7964611d339bc9177af4eeac4c89fd..852a0c69b6069f0224567ae750692d0b3da070d7 100644 --- a/app/views/layouts/error.html.haml +++ b/app/views/layouts/error.html.haml @@ -5,10 +5,10 @@ %meta{ charset: 'utf-8' }/ %title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ') %meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/ - = stylesheet_pack_tag 'common', media: 'all' - = stylesheet_pack_tag Setting.default_settings['theme'], media: 'all' - = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous' - = javascript_pack_tag 'error', integrity: true, crossorigin: 'anonymous' + = stylesheet_pack_tag 'common', media: 'all', crossorigin: 'anonymous' + = stylesheet_pack_tag Setting.default_settings['theme'], media: 'all', crossorigin: 'anonymous' + = javascript_pack_tag 'common', crossorigin: 'anonymous' + = javascript_pack_tag 'error', crossorigin: 'anonymous' %body.error .dialog .dialog__illustration diff --git a/app/views/layouts/modal.html.haml b/app/views/layouts/modal.html.haml index 2ef49e413208ad2e9fa717f4a53d8675a0884e0a..e74e2c0e35644e7d7d38b66e55586819cc4b34bc 100644 --- a/app/views/layouts/modal.html.haml +++ b/app/views/layouts/modal.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' - content_for :content do - if user_signed_in? && !@hide_header diff --git a/app/views/layouts/public.html.haml b/app/views/layouts/public.html.haml index a2c4e5deb2d4078eeb3f642f47759c1a60a263d3..e63cf0848f0dc4f7c23bfd99911823c9f262e34c 100644 --- a/app/views/layouts/public.html.haml +++ b/app/views/layouts/public.html.haml @@ -1,6 +1,6 @@ - content_for :header_tags do = render_initial_state - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' - content_for :content do .public-layout diff --git a/app/views/media/player.html.haml b/app/views/media/player.html.haml index ae47750e9ab0e61900b8f0b260b8d5ae0b769582..95e37bb22a8b276a70aecff5a0febeb4ad1a5a00 100644 --- a/app/views/media/player.html.haml +++ b/app/views/media/player.html.haml @@ -1,9 +1,9 @@ - content_for :header_tags do = render_initial_state - = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'public', crossorigin: 'anonymous' - if @media_attachment.video? - = react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description do + = react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), frameRate: @media_attachment.file.meta.dig('original', 'frame_rate'), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description, media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer)].as_json do %video{ controls: 'controls' } %source{ src: @media_attachment.file.url(:original) } - elsif @media_attachment.gifv? diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index e992e5563dc82a51a6ccddf6811fbee4fa143c8e..9b7e1b65c63937b9dc10920b221603df1c65ab8a 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -26,11 +26,11 @@ = "@#{status.account.acct}" - if status.spoiler_text? - %div{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + %div.auto-dir %p = Formatter.instance.format_spoiler(status) - %div{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + %div.auto-dir = Formatter.instance.format(status) - if status.media_attachments.size > 0 diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml index 7b77108a93c959295405638bacef7126c43a641b..fbb733db49f3cd95a70a450e0ad74a2b277a0a0d 100644 --- a/app/views/oauth/authorized_applications/index.html.haml +++ b/app/views/oauth/authorized_applications/index.html.haml @@ -20,5 +20,5 @@ %th!= application.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.join(', ') %td= l application.created_at %td - - unless application.superapp? + - unless application.superapp? || current_account.suspended? = table_link_to 'times', t('doorkeeper.authorized_applications.buttons.revoke'), oauth_authorized_application_path(application), method: :delete, data: { confirm: t('doorkeeper.authorized_applications.confirmations.revoke') } diff --git a/app/views/public_timelines/show.html.haml b/app/views/public_timelines/show.html.haml index 5e536a2356180270bcc02fd6da54877539dca737..3325be5bf1c82d2dc474aa3e16708aa4630b19bb 100644 --- a/app/views/public_timelines/show.html.haml +++ b/app/views/public_timelines/show.html.haml @@ -3,7 +3,7 @@ - content_for :header_tags do %meta{ name: 'robots', content: 'noindex' }/ - = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'about', crossorigin: 'anonymous' .page-header %h1= t('about.see_whats_happening') diff --git a/app/views/relationships/_account.html.haml b/app/views/relationships/_account.html.haml index af5a4aaf7d0fce7a1c897e3c9225ed90b47a2d84..f521aff2258ed2bbe3650adfc54797d3da6c6fe4 100644 --- a/app/views/relationships/_account.html.haml +++ b/app/views/relationships/_account.html.haml @@ -5,6 +5,8 @@ %table.accounts-table %tbody %tr + %td.accounts-table__interrelationships + = interrelationships_icon(@relationships, account.id) %td= account_link_to account %td.accounts-table__count.optional = number_to_human account.statuses_count, strip_insignificant_zeros: true diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index 099bb32024d111701a6bf497a1715f76b9bcb5e3..c82e639e0ed605f4c57aa124cf74d01526341a6a 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -2,7 +2,7 @@ = t('settings.relationships') - content_for :header_tags do - = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous' + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' .filters .filter-subset @@ -42,6 +42,8 @@ %label.batch-table__toolbar__select.batch-checkbox-all = check_box_tag :batch_checkbox_all, nil, false .batch-table__toolbar__actions + = f.button safe_join([fa_icon('user-plus'), t('relationships.follow_selected_followers')]), name: :follow, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship? && !mutual_relationship? + = f.button safe_join([fa_icon('user-times'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless followed_by_relationship? = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless following_relationship? diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml index 0bb80e93726f2ca43eea12c5b0c4149e46ba594e..18b52c0c2c6f8d123295a2ed349cefdb01ea2812 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -36,6 +36,10 @@ %th= t('exports.domain_blocks') %td= number_with_delimiter @export.total_domain_blocks %td= table_link_to 'download', t('exports.csv'), settings_exports_domain_blocks_path(format: :csv) + %tr + %th= t('exports.bookmarks') + %td= number_with_delimiter @export.total_bookmarks + %td= table_link_to 'download', t('bookmarks.csv'), settings_exports_bookmarks_path(format: :csv) %hr.spacer/ diff --git a/app/views/settings/featured_tags/index.html.haml b/app/views/settings/featured_tags/index.html.haml index 6734d027c5409dbb9bdb5e3766680ce527b4dcc6..297379893ab24df83ba7e53fe63ee4e05a542007 100644 --- a/app/views/settings/featured_tags/index.html.haml +++ b/app/views/settings/featured_tags/index.html.haml @@ -9,7 +9,7 @@ = render 'shared/error_messages', object: @featured_tag .fields-group - = f.input :name, wrapper: :with_block_label, hint: safe_join([t('simple_form.hints.featured_tag.name'), safe_join(@most_used_tags.map { |tag| link_to("##{tag.name}", settings_featured_tags_path(featured_tag: { name: tag.name }), method: :post) }, ', ')], ' ') + = f.input :name, wrapper: :with_block_label, hint: safe_join([t('simple_form.hints.featured_tag.name'), safe_join(@recently_used_tags.map { |tag| link_to("##{tag.name}", settings_featured_tags_path(featured_tag: { name: tag.name }), method: :post) }, ', ')], ' ') .actions = f.button :button, t('featured_tags.add_new'), type: :submit diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 10fff406e6dd7f1ce2592e641dfd7cd29bfeff07..14941d5fd3f6edc7ee26630e6406efac8332a3ac 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -30,6 +30,7 @@ .fields-group = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label, recommended: true = f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label + = f.input :setting_disable_swiping, as: :boolean, wrapper: :with_label = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label %h4= t 'appearance.toot_layout' diff --git a/app/views/settings/two_factor_authentication/confirmations/new.html.haml b/app/views/settings/two_factor_authentication/confirmations/new.html.haml index 86cf1f695effc8880200268ec00c8b34a4c2bde2..671237db573f8756db04c0eee026eb00525248e3 100644 --- a/app/views/settings/two_factor_authentication/confirmations/new.html.haml +++ b/app/views/settings/two_factor_authentication/confirmations/new.html.haml @@ -2,17 +2,17 @@ = t('settings.two_factor_authentication') = simple_form_for @confirmation, url: settings_two_factor_authentication_confirmation_path, method: :post do |f| - %p.hint= t('two_factor_authentication.instructions_html') + %p.hint= t('otp_authentication.instructions_html') .qr-wrapper .qr-code!= @qrcode.as_svg(padding: 0, module_size: 4) .qr-alternative - %p.hint= t('two_factor_authentication.manual_instructions') - %samp.qr-alternative__code= current_user.otp_secret.scan(/.{4}/).join(' ') + %p.hint= t('otp_authentication.manual_instructions') + %samp.qr-alternative__code= @new_otp_secret.scan(/.{4}/).join(' ') .fields-group - = f.input :otp_attempt, wrapper: :with_label, hint: t('two_factor_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true + = f.input :otp_attempt, wrapper: :with_label, hint: t('otp_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true .actions - = f.button :button, t('two_factor_authentication.enable'), type: :submit + = f.button :button, t('otp_authentication.enable'), type: :submit diff --git a/app/views/settings/two_factor_authentication/otp_authentication/show.html.haml b/app/views/settings/two_factor_authentication/otp_authentication/show.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..d069ba12a96bc1a61b112c5b8569c9745d6058d7 --- /dev/null +++ b/app/views/settings/two_factor_authentication/otp_authentication/show.html.haml @@ -0,0 +1,9 @@ +- content_for :page_title do + = t('settings.two_factor_authentication') + +.simple_form + %p.hint= t('otp_authentication.description_html') + + %hr.spacer/ + + = link_to t('otp_authentication.setup'), settings_otp_authentication_path, data: { method: :post }, class: 'block-button' diff --git a/app/views/settings/two_factor_authentication/webauthn_credentials/index.html.haml b/app/views/settings/two_factor_authentication/webauthn_credentials/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..0dfd94ab9dcf58e93b50986f7865c2d11b829da9 --- /dev/null +++ b/app/views/settings/two_factor_authentication/webauthn_credentials/index.html.haml @@ -0,0 +1,17 @@ +- content_for :page_title do + = t('settings.webauthn_authentication') + +.table-wrapper + %table.table + %tbody + - current_user.webauthn_credentials.each do |credential| + %tr + %td= credential.nickname + %td= t('webauthn_credentials.registered_on', date: l(credential.created_at.to_date, format: :with_month_name)) + %td + = table_link_to 'trash', t('webauthn_credentials.delete'), settings_webauthn_credential_path(credential.id), method: :delete, data: { confirm: t('webauthn_credentials.delete_confirmation') } + +%hr.spacer/ + +.simple_form + = link_to t('webauthn_credentials.add'), new_settings_webauthn_credential_path, class: 'block-button' diff --git a/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml b/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..1148d5ed7e9f104af4e119055a22441ac7a8da1e --- /dev/null +++ b/app/views/settings/two_factor_authentication/webauthn_credentials/new.html.haml @@ -0,0 +1,16 @@ +- content_for :page_title do + = t('settings.webauthn_authentication') + += simple_form_for(:new_webauthn_credential, url: settings_webauthn_credentials_path, html: { id: :new_webauthn_credential }) do |f| + %p.flash-message.hidden#unsupported-browser-message= t 'webauthn_credentials.not_supported' + %p.flash-message.alert.hidden#security-key-error-message= t 'webauthn_credentials.invalid_credential' + + %p.hint= t('webauthn_credentials.description_html') + + .fields_group + = f.input :nickname, wrapper: :with_block_label, hint: t('webauthn_credentials.nickname_hint'), input_html: { :autocomplete => 'off' }, required: true + + .actions + = f.button :button, t('webauthn_credentials.add'), class: 'js-webauthn', type: :submit + += javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous' diff --git a/app/views/settings/two_factor_authentication_methods/index.html.haml b/app/views/settings/two_factor_authentication_methods/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..315443e6d59508e5f81b19795ccfadffd5853145 --- /dev/null +++ b/app/views/settings/two_factor_authentication_methods/index.html.haml @@ -0,0 +1,41 @@ +- content_for :page_title do + = t('settings.two_factor_authentication') + +- content_for :heading_actions do + = link_to t('two_factor_authentication.disable'), disable_settings_two_factor_authentication_methods_path, class: 'button button--destructive', method: :post + +%p.hint + %span.positive-hint + = fa_icon 'check' + = ' ' + = t 'two_factor_authentication.enabled' + +.table-wrapper + %table.table + %thead + %tr + %th= t('two_factor_authentication.methods') + %th + %tbody + %tr + %td= t('two_factor_authentication.otp') + %td + = table_link_to 'pencil', t('two_factor_authentication.edit'), settings_otp_authentication_path, method: :post + %tr + %td= t('two_factor_authentication.webauthn') + - if current_user.webauthn_enabled? + %td + = table_link_to 'pencil', t('two_factor_authentication.edit'), settings_webauthn_credentials_path, method: :get + - else + %td + = table_link_to 'key', t('two_factor_authentication.add'), new_settings_webauthn_credential_path, method: :get + +%hr.spacer/ + +%h3= t('two_factor_authentication.recovery_codes') +%p.muted-hint= t('two_factor_authentication.lost_recovery_codes') + +%hr.spacer/ + +.simple_form + = link_to t('two_factor_authentication.generate_recovery_codes'), settings_two_factor_authentication_recovery_codes_path, data: { method: :post }, class: 'block-button' diff --git a/app/views/settings/two_factor_authentications/show.html.haml b/app/views/settings/two_factor_authentications/show.html.haml deleted file mode 100644 index f1eecd0002d5ee4216a6884462fc751e643051b0..0000000000000000000000000000000000000000 --- a/app/views/settings/two_factor_authentications/show.html.haml +++ /dev/null @@ -1,36 +0,0 @@ -- content_for :page_title do - = t('settings.two_factor_authentication') - -- if current_user.otp_required_for_login - %p.hint - %span.positive-hint - = fa_icon 'check' - = ' ' - = t 'two_factor_authentication.enabled' - - %hr.spacer/ - - = simple_form_for @confirmation, url: settings_two_factor_authentication_path, method: :delete do |f| - .fields-group - = f.input :otp_attempt, wrapper: :with_block_label, hint: t('two_factor_authentication.code_hint'), label: t('simple_form.labels.defaults.otp_attempt'), input_html: { :autocomplete => 'off' }, required: true - - .actions - = f.button :button, t('two_factor_authentication.disable'), type: :submit, class: 'negative' - - %hr.spacer/ - - %h3= t('two_factor_authentication.recovery_codes') - %p.muted-hint= t('two_factor_authentication.lost_recovery_codes') - - %hr.spacer/ - - .simple_form - = link_to t('two_factor_authentication.generate_recovery_codes'), settings_two_factor_authentication_recovery_codes_path, data: { method: :post }, class: 'block-button' - -- else - .simple_form - %p.hint= t('two_factor_authentication.description_html') - - %hr.spacer/ - - = link_to t('two_factor_authentication.setup'), settings_two_factor_authentication_path, data: { method: :post }, class: 'block-button' diff --git a/app/views/shared/_error_messages.html.haml b/app/views/shared/_error_messages.html.haml index 28becd6c4482da59d232e33a93894b9e4279ed91..4916bd424e8a440ba27f617b6923c26caf3c30c3 100644 --- a/app/views/shared/_error_messages.html.haml +++ b/app/views/shared/_error_messages.html.haml @@ -1,3 +1,6 @@ - if object.errors.any? .flash-message.alert#error_explanation %strong= t('generic.validation_errors', count: object.errors.count) +- object.errors[:base].each do |error| + .flash-message.alert + %strong= error diff --git a/app/views/shares/show.html.haml b/app/views/shares/show.html.haml index f2f5479a79c4a6d9f4331d9f486e37d6ec189e10..1c0bbf6765817d96438687d12f503f653e2513c9 100644 --- a/app/views/shares/show.html.haml +++ b/app/views/shares/show.html.haml @@ -1,5 +1,5 @@ - content_for :header_tags do = render_initial_state - = javascript_pack_tag 'share', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'share', crossorigin: 'anonymous' #mastodon-compose{ data: { props: Oj.dump(default_props) } } diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml index 85b2ceea44e1f6be89b7aa8d836c622dba37bf2f..93af131e5a6afc1999d8413c1f1a9835106073c9 100644 --- a/app/views/statuses/_detailed_status.html.haml +++ b/app/views/statuses/_detailed_status.html.haml @@ -20,7 +20,7 @@ %p< %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)} %button.status__content__spoiler-link= t('statuses.show_more') - .e-content{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + .e-content = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - if status.preloadable_poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do @@ -29,17 +29,17 @@ - if !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first - = react_component :video, src: video.file.url(:original), preview: video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small), blurhash: video.blurhash, sensitive: status.sensitive?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do + = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 670, height: 380, detailed: true, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - elsif status.media_attachments.first.audio? - audio = status.media_attachments.first - = react_component :audio, src: audio.file.url(:original), poster: audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url, backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 670, height: 380, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do + = react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 670, height: 380, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - else - = react_component :media_gallery, height: 380, sensitive: status.sensitive?, standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do + = react_component :media_gallery, height: 380, sensitive: sensitized?(status, current_account), standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - elsif status.preview_card - = react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json + = react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json .detailed-status__meta %data.dt-published{ value: status.created_at.to_time.iso8601 } diff --git a/app/views/statuses/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml index 67c6c0fd090a555ccb1924dccb856f07ac51f53d..7e5f1125984fcff4f4157a2c66def8a21e3ecd40 100644 --- a/app/views/statuses/_simple_status.html.haml +++ b/app/views/statuses/_simple_status.html.haml @@ -1,10 +1,13 @@ +:ruby + hide_show_thread ||= false + .status{ class: "status-#{status.visibility}" } .status__info = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener noreferrer' do + %span.status__visibility-icon>< + = visibility_icon status %time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) %data.dt-published{ value: status.created_at.to_time.iso8601 } - %span.status__visibility-icon - = visibility_icon status .p-author.h-card = link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener noreferrer' do @@ -17,7 +20,7 @@ %span.display-name %bdi %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) - + = ' ' %span.display-name__account = acct(status.account) = fa_icon('lock') if status.account.locked? @@ -26,7 +29,7 @@ %p< %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)} %button.status__content__spoiler-link= t('statuses.show_more') - .e-content{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + .e-content = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - if status.preloadable_poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do @@ -35,30 +38,29 @@ - if !status.media_attachments.empty? - if status.media_attachments.first.video? - video = status.media_attachments.first - = react_component :video, src: video.file.url(:original), preview: video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small), blurhash: video.blurhash, sensitive: status.sensitive?, width: 610, height: 343, inline: true, alt: video.description do + = react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 610, height: 343, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - elsif status.media_attachments.first.audio? - audio = status.media_attachments.first - = react_component :audio, src: audio.file.url(:original), poster: audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url, backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 610, height: 343, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do + = react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 610, height: 343, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - else - = react_component :media_gallery, height: 343, sensitive: status.sensitive?, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do + = react_component :media_gallery, height: 343, sensitive: sensitized?(status, current_account), autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do = render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments } - elsif status.preview_card - = react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json + = react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json - - if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id + - if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id && !hide_show_thread = link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__content__read-more-button', target: stream_link_target, rel: 'noopener noreferrer' do = t 'statuses.show_thread' .status__action-bar - .status__action-bar__counter - = link_to remote_interaction_path(status, type: :reply), class: 'status__action-bar-button icon-button modal-button' do - - if status.in_reply_to_id.nil? - = fa_icon 'reply fw' - - else - = fa_icon 'reply-all fw' - .status__action-bar__counter__label= obscured_counter status.replies_count + = link_to remote_interaction_path(status, type: :reply), class: 'status__action-bar-button icon-button icon-button--with-counter modal-button' do + - if status.in_reply_to_id.nil? + = fa_icon 'reply fw' + - else + = fa_icon 'reply-all fw' + %span.icon-button__counter= obscured_counter status.replies_count = link_to remote_interaction_path(status, type: :reblog), class: 'status__action-bar-button icon-button modal-button' do - if status.distributable? = fa_icon 'retweet fw' diff --git a/app/views/statuses/_status.html.haml b/app/views/statuses/_status.html.haml index 0e3652503067836203082446e3c3e125ee072f43..13a06519cf434ac55b1d6a2c59dc35e665bec03b 100644 --- a/app/views/statuses/_status.html.haml +++ b/app/views/statuses/_status.html.haml @@ -17,7 +17,7 @@ - if status.reply? && include_threads - if @next_ancestor .entry{ class: entry_classes } - = link_to_more ActivityPub::TagManager.instance.url_for(@next_ancestor) + = link_to_older ActivityPub::TagManager.instance.url_for(@next_ancestor) = render partial: 'statuses/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay @@ -39,21 +39,21 @@ %span = t('stream_entries.pinned') - = render (centered ? 'statuses/detailed_status' : 'statuses/simple_status'), status: status.proper, autoplay: autoplay + = render (centered ? 'statuses/detailed_status' : 'statuses/simple_status'), status: status.proper, autoplay: autoplay, hide_show_thread: is_predecessor || is_successor - if include_threads - if @since_descendant_thread_id .entry{ class: entry_classes } - = link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1) + = link_to_newer short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1) - @descendant_threads.each do |thread| = render partial: 'statuses/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay - if thread[:next_status] .entry{ class: entry_classes } - = link_to_more ActivityPub::TagManager.instance.url_for(thread[:next_status]) + = link_to_newer ActivityPub::TagManager.instance.url_for(thread[:next_status]) - if @next_descendant_thread .entry{ class: entry_classes } - = link_to_more short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1) + = link_to_newer short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1) - if include_threads && !embedded_view? && !user_signed_in? .entry{ class: entry_classes } diff --git a/app/views/statuses/show.html.haml b/app/views/statuses/show.html.haml index 873df7fbd1dbe7d7f8bcafc9b731205a68fc56e4..7ef7b09a2de2d64b6719e1d4457e3d8a3f947ad8 100644 --- a/app/views/statuses/show.html.haml +++ b/app/views/statuses/show.html.haml @@ -12,6 +12,7 @@ = opengraph 'og:type', 'article' = opengraph 'og:title', "#{display_name(@account)} (#{acct(@account)})" = opengraph 'og:url', short_account_status_url(@account, @status) + = opengraph 'og:published_time', @status.created_at.iso8601 = render 'og_description', activity: @status = render 'og_image', activity: @status, account: @account diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml index 19dadd36a552daf6db4d6d2cc889357429ffa7b5..beeeb56f2ddf79da52a0ff1e734b5082d07d8a52 100644 --- a/app/views/tags/show.html.haml +++ b/app/views/tags/show.html.haml @@ -5,7 +5,7 @@ %meta{ name: 'robots', content: 'noindex' }/ %link{ rel: 'alternate', type: 'application/rss+xml', href: tag_url(@tag, format: 'rss') }/ - = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous' + = javascript_pack_tag 'about', crossorigin: 'anonymous' = render 'og' .page-header diff --git a/app/views/user_mailer/webauthn_credential_added.html.haml b/app/views/user_mailer/webauthn_credential_added.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..81de84b564010fc44d9cd7dab70c1c2a3635528b --- /dev/null +++ b/app/views/user_mailer/webauthn_credential_added.html.haml @@ -0,0 +1,44 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' + + %h1= t 'devise.mailer.webauthn_credential.added.title' + %p.lead= "#{t 'devise.mailer.webauthn_credential.added.explanation' }:" + %p.lead= @webauthn_credential.nickname + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to edit_user_registration_url do + %span= t('settings.account_settings') diff --git a/app/views/user_mailer/webauthn_credential_added.text.erb b/app/views/user_mailer/webauthn_credential_added.text.erb new file mode 100644 index 0000000000000000000000000000000000000000..4319dddbfc49559563a2121d021a921e8dd75544 --- /dev/null +++ b/app/views/user_mailer/webauthn_credential_added.text.erb @@ -0,0 +1,7 @@ +<%= t 'devise.mailer.two_factor_enabled.title' %> + +=== + +<%= t 'devise.mailer.two_factor_enabled.explanation' %> + +=> <%= edit_user_registration_url %> diff --git a/app/views/user_mailer/webauthn_credential_deleted.html.haml b/app/views/user_mailer/webauthn_credential_deleted.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..7b47f0c88e6d81fcfab5cbf3053381f9d24996f9 --- /dev/null +++ b/app/views/user_mailer/webauthn_credential_deleted.html.haml @@ -0,0 +1,44 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' + + %h1= t 'devise.mailer.webauthn_credential.deleted.title' + %p.lead= "#{t 'devise.mailer.webauthn_credential.deleted.explanation' }:" + %p.lead= @webauthn_credential.nickname + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to edit_user_registration_url do + %span= t('settings.account_settings') diff --git a/app/views/user_mailer/webauthn_credential_deleted.text.erb b/app/views/user_mailer/webauthn_credential_deleted.text.erb new file mode 100644 index 0000000000000000000000000000000000000000..53e5bc78c7caa1f5eabe227f47ad0b1a9b0eef1d --- /dev/null +++ b/app/views/user_mailer/webauthn_credential_deleted.text.erb @@ -0,0 +1,7 @@ +<%= t 'devise.mailer.webauthn_credential.deleted.title' %> + +=== + +<%= t 'devise.mailer.webauthn_credential.deleted.explanation' %> + +=> <%= edit_user_registration_url %> diff --git a/app/views/user_mailer/webauthn_disabled.html.haml b/app/views/user_mailer/webauthn_disabled.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..81a2a7954c7f2096ffb25003ae49d82de650cde6 --- /dev/null +++ b/app/views/user_mailer/webauthn_disabled.html.haml @@ -0,0 +1,43 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon.alert-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' + + %h1= t 'devise.mailer.webauthn_disabled.title' + %p.lead= t 'devise.mailer.webauthn_disabled.explanation' + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to edit_user_registration_url do + %span= t('settings.account_settings') diff --git a/app/views/user_mailer/webauthn_disabled.text.erb b/app/views/user_mailer/webauthn_disabled.text.erb new file mode 100644 index 0000000000000000000000000000000000000000..962df77caa9cbdcb2a7be52334639021ba3df627 --- /dev/null +++ b/app/views/user_mailer/webauthn_disabled.text.erb @@ -0,0 +1,7 @@ +<%= t 'devise.mailer.webauthn_disabled.title' %> + +=== + +<%= t 'devise.mailer.webauthn_disabled.explanation' %> + +=> <%= edit_user_registration_url %> diff --git a/app/views/user_mailer/webauthn_enabled.html.haml b/app/views/user_mailer/webauthn_enabled.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..f08e764e8df64e793ec1bbd0536ee65f1153d3a7 --- /dev/null +++ b/app/views/user_mailer/webauthn_enabled.html.haml @@ -0,0 +1,43 @@ +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.hero + .email-row + .col-6 + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.text-center.padded + %table.hero-icon{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td + = image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' + + %h1= t 'devise.mailer.webauthn_enabled.title' + %p.lead= t 'devise.mailer.webauthn_enabled.explanation' + +%table.email-table{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.email-body + .email-container + %table.content-section{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.content-cell.content-start + %table.column{ cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.column-cell.button-cell + %table.button{ align: 'center', cellspacing: 0, cellpadding: 0 } + %tbody + %tr + %td.button-primary + = link_to edit_user_registration_url do + %span= t('settings.account_settings') diff --git a/app/views/user_mailer/webauthn_enabled.text.erb b/app/views/user_mailer/webauthn_enabled.text.erb new file mode 100644 index 0000000000000000000000000000000000000000..4c233fefbd980c2797f2f476270df3e47241232f --- /dev/null +++ b/app/views/user_mailer/webauthn_enabled.text.erb @@ -0,0 +1,7 @@ +<%= t 'devise.mailer.webauthn_credentia.added.title' %> + +=== + +<%= t 'devise.mailer.webauthn_credentia.added.explanation' %> + +=> <%= edit_user_registration_url %> diff --git a/app/views/well_known/host_meta/show.xml.ruby b/app/views/well_known/host_meta/show.xml.ruby index 0a6bdc322fb130363c190603be1e6c8e6402cce5..b4e867c5f88a7c53631639890d9cbdbb250c4103 100644 --- a/app/views/well_known/host_meta/show.xml.ruby +++ b/app/views/well_known/host_meta/show.xml.ruby @@ -5,7 +5,6 @@ doc << Ox::Element.new('XRD').tap do |xrd| xrd << Ox::Element.new('Link').tap do |link| link['rel'] = 'lrdd' - link['type'] = 'application/xrd+xml' link['template'] = @webfinger_template end end diff --git a/app/workers/account_deletion_worker.rb b/app/workers/account_deletion_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..fdf013e01043b10fa26025bcfa46cf87565408b0 --- /dev/null +++ b/app/workers/account_deletion_worker.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AccountDeletionWorker + include Sidekiq::Worker + + sidekiq_options queue: 'pull', lock: :until_executed + + def perform(account_id, options = {}) + reserve_username = options.with_indifferent_access.fetch(:reserve_username, true) + skip_activitypub = options.with_indifferent_access.fetch(:skip_activitypub, false) + DeleteAccountService.new.call(Account.find(account_id), reserve_username: reserve_username, skip_activitypub: skip_activitypub, reserve_email: false) + rescue ActiveRecord::RecordNotFound + true + end +end diff --git a/app/workers/account_merging_worker.rb b/app/workers/account_merging_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..8c234e7acf185ab2ea60e2d0ebf08365b43b8163 --- /dev/null +++ b/app/workers/account_merging_worker.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AccountMergingWorker + include Sidekiq::Worker + + sidekiq_options queue: 'pull' + + def perform(account_id) + account = Account.find(account_id) + + return true if account.nil? || account.local? + + Account.where(uri: account.uri).where.not(id: account.id).find_each do |duplicate| + account.merge_with!(duplicate) + duplicate.destroy + end + end +end diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb index 60775787a8a01138a92d6f36e316a79f2bda0279..6c5a576a703c4ea075637d83290e46c07be95499 100644 --- a/app/workers/activitypub/delivery_worker.rb +++ b/app/workers/activitypub/delivery_worker.rb @@ -2,6 +2,7 @@ class ActivityPub::DeliveryWorker include Sidekiq::Worker + include RoutingHelper include JsonLdHelper STOPLIGHT_FAILURE_THRESHOLD = 10 @@ -38,9 +39,18 @@ class ActivityPub::DeliveryWorker Request.new(:post, @inbox_url, body: @json, http_client: http_client).tap do |request| request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with]) request.add_headers(HEADERS) + request.add_headers({ 'Collection-Synchronization' => synchronization_header }) if ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] != 'true' && @options[:synchronize_followers] end end + def synchronization_header + "collectionId=\"#{account_followers_url(@source_account)}\", digest=\"#{@source_account.remote_followers_hash(inbox_url_prefix)}\", url=\"#{account_followers_synchronization_url(@source_account)}\"" + end + + def inbox_url_prefix + @inbox_url[/http(s?):\/\/[^\/]+\//] + end + def perform_request light = Stoplight(@inbox_url) do request_pool.with(@host) do |http_client| diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb index e4997ba0eaf9ce2d788a507732a1138cef19747f..9b4814644f278a829de4430bed00f6f069e1a7db 100644 --- a/app/workers/activitypub/distribution_worker.rb +++ b/app/workers/activitypub/distribution_worker.rb @@ -13,7 +13,7 @@ class ActivityPub::DistributionWorker return if skip_distribution? ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| - [payload, @account.id, inbox_url] + [payload, @account.id, inbox_url, { synchronize_followers: !@status.distributable? }] end relay! if relayable? diff --git a/app/workers/activitypub/followers_synchronization_worker.rb b/app/workers/activitypub/followers_synchronization_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..35a3ef0b9676dc21fa6f497854513b6d74ab8051 --- /dev/null +++ b/app/workers/activitypub/followers_synchronization_worker.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class ActivityPub::FollowersSynchronizationWorker + include Sidekiq::Worker + + sidekiq_options queue: 'push', lock: :until_executed + + def perform(account_id, url) + @account = Account.find_by(id: account_id) + return true if @account.nil? + + ActivityPub::SynchronizeFollowersService.new.call(@account, url) + end +end diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index 05139f616db9688890ffa638eb2faf554fdb16cf..cef5953194993a55d27b15d0773f78976b59c13d 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -3,7 +3,7 @@ class ActivityPub::ProcessingWorker include Sidekiq::Worker - sidekiq_options backtrace: true + sidekiq_options backtrace: true, retry: 8 def perform(account_id, body, delivered_to_account_id = nil) ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) diff --git a/app/workers/admin/account_deletion_worker.rb b/app/workers/admin/account_deletion_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..82f269ad6fb8c8d384fe1d2d3a615fa1c80e66be --- /dev/null +++ b/app/workers/admin/account_deletion_worker.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class Admin::AccountDeletionWorker + include Sidekiq::Worker + + sidekiq_options queue: 'pull' + + def perform(account_id) + DeleteAccountService.new.call(Account.find(account_id), reserve_username: true, reserve_email: true) + rescue ActiveRecord::RecordNotFound + true + end +end diff --git a/app/workers/admin/suspension_worker.rb b/app/workers/admin/suspension_worker.rb index 83c815efd7c1ed624248b0b2213a9688a2aed2aa..35c570336094efff2aabd016e87240754ebd667f 100644 --- a/app/workers/admin/suspension_worker.rb +++ b/app/workers/admin/suspension_worker.rb @@ -5,7 +5,9 @@ class Admin::SuspensionWorker sidekiq_options queue: 'pull' - def perform(account_id, remove_user = false) - SuspendAccountService.new.call(Account.find(account_id), reserve_username: true, reserve_email: !remove_user) + def perform(account_id) + SuspendAccountService.new.call(Account.find(account_id)) + rescue ActiveRecord::RecordNotFound + true end end diff --git a/app/workers/admin/unsuspension_worker.rb b/app/workers/admin/unsuspension_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..7cb2349b16bf5b5e528323ceba18d02bdf7ff525 --- /dev/null +++ b/app/workers/admin/unsuspension_worker.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class Admin::UnsuspensionWorker + include Sidekiq::Worker + + sidekiq_options queue: 'pull' + + def perform(account_id) + UnsuspendAccountService.new.call(Account.find(account_id)) + rescue ActiveRecord::RecordNotFound + true + end +end diff --git a/app/workers/authorize_follow_worker.rb b/app/workers/authorize_follow_worker.rb index 0d50146246301af88653513a6e4200e3eadd7476..f57900fa59a31b902d9f2e6d36c56a95ad5537a5 100644 --- a/app/workers/authorize_follow_worker.rb +++ b/app/workers/authorize_follow_worker.rb @@ -7,7 +7,7 @@ class AuthorizeFollowWorker source_account = Account.find(source_account_id) target_account = Account.find(target_account_id) - AuthorizeFollowService.new.call(source_account, target_account) + AuthorizeFollowService.new.call(source_account, target_account, bypass_limit: true) rescue ActiveRecord::RecordNotFound true end diff --git a/app/workers/cache_buster_worker.rb b/app/workers/cache_buster_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..5ad0a44cb7a9f19de9bc5176020b88d41a96e0e4 --- /dev/null +++ b/app/workers/cache_buster_worker.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class CacheBusterWorker + include Sidekiq::Worker + include RoutingHelper + + sidekiq_options queue: 'pull' + + def perform(path) + cache_buster.bust(full_asset_url(path)) + end + + private + + def cache_buster + CacheBuster.new(Rails.configuration.x.cache_buster) + end +end diff --git a/app/workers/delete_mute_worker.rb b/app/workers/delete_mute_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..eb031020e1b2cfea2cad1b1dcd0d966161a25b4c --- /dev/null +++ b/app/workers/delete_mute_worker.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class DeleteMuteWorker + include Sidekiq::Worker + + def perform(mute_id) + mute = Mute.find_by(id: mute_id) + UnmuteService.new.call(mute.account, mute.target_account) if mute&.expired? + end +end diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb index 1ae3c877b0976abdfc73c622b7ca69c02dc3c128..b70c7e3895cedefafdbed574060236c7488d2ccf 100644 --- a/app/workers/feed_insert_worker.rb +++ b/app/workers/feed_insert_worker.rb @@ -23,13 +23,25 @@ class FeedInsertWorker private def check_and_insert - perform_push unless feed_filtered? + return if feed_filtered? + + perform_push + perform_notify if notify? end def feed_filtered? - # Note: Lists are a variation of home, so the filtering rules - # of home apply to both - FeedManager.instance.filter?(:home, @status, @follower.id) + case @type + when :home + FeedManager.instance.filter?(:home, @status, @follower) + when :list + FeedManager.instance.filter?(:list, @status, @list) + end + end + + def notify? + return false if @type != :home || @status.reblog? || (@status.reply? && @status.in_reply_to_account_id != @status.account_id) + + Follow.find_by(account: @follower, target_account: @status.account)&.notify? end def perform_push @@ -40,4 +52,8 @@ class FeedInsertWorker FeedManager.instance.push_to_list(@list, @status) end end + + def perform_notify + NotifyService.new.call(@follower, :status, @status) + end end diff --git a/app/workers/import/relationship_worker.rb b/app/workers/import/relationship_worker.rb index 4a455f3aebd3003904f2578f0151d288ef83ee75..4a7100435f7dc42a89fd133dc8e7ae6186a3928a 100644 --- a/app/workers/import/relationship_worker.rb +++ b/app/workers/import/relationship_worker.rb @@ -15,7 +15,11 @@ class Import::RelationshipWorker case relationship when 'follow' - FollowService.new.call(from_account, target_account, options) + begin + FollowService.new.call(from_account, target_account, options) + rescue ActiveRecord::RecordInvalid + raise if FollowLimitValidator.limit_for_account(from_account) < from_account.following_count + end when 'unfollow' UnfollowService.new.call(from_account, target_account) when 'block' diff --git a/app/workers/local_notification_worker.rb b/app/workers/local_notification_worker.rb index 48635e498fffd7e09893fd25ec92d509da241f0e..6b08ca6fcf8f9aa3c902768d56fa4f7ce03b8e78 100644 --- a/app/workers/local_notification_worker.rb +++ b/app/workers/local_notification_worker.rb @@ -3,7 +3,7 @@ class LocalNotificationWorker include Sidekiq::Worker - def perform(receiver_account_id, activity_id = nil, activity_class_name = nil) + def perform(receiver_account_id, activity_id = nil, activity_class_name = nil, type = nil) if activity_id.nil? && activity_class_name.nil? activity = Mention.find(receiver_account_id) receiver = activity.account @@ -12,7 +12,7 @@ class LocalNotificationWorker activity = activity_class_name.constantize.find(activity_id) end - NotifyService.new.call(receiver, activity) + NotifyService.new.call(receiver, type || activity_class_name.underscore, activity) rescue ActiveRecord::RecordNotFound true end diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index d745cb99c7b9aada475223d9250a0315dc0c6c5b..74ef7d4daa7a7739e0b8a87afa809a839113702e 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -6,6 +6,8 @@ class MergeWorker sidekiq_options queue: 'pull' def perform(from_account_id, into_account_id) - FeedManager.instance.merge_into_timeline(Account.find(from_account_id), Account.find(into_account_id)) + FeedManager.instance.merge_into_home(Account.find(from_account_id), Account.find(into_account_id)) + rescue ActiveRecord::RecordNotFound + true end end diff --git a/app/workers/mute_worker.rb b/app/workers/mute_worker.rb index 7bf0923a5dbfb32b07dea86b665b2389279dcde3..c74f657cbacad84d1976ea37051c90d82cd7c463 100644 --- a/app/workers/mute_worker.rb +++ b/app/workers/mute_worker.rb @@ -4,9 +4,8 @@ class MuteWorker include Sidekiq::Worker def perform(account_id, target_account_id) - FeedManager.instance.clear_from_timeline( - Account.find(account_id), - Account.find(target_account_id) - ) + FeedManager.instance.clear_from_home(Account.find(account_id), Account.find(target_account_id)) + rescue ActiveRecord::RecordNotFound + true end end diff --git a/app/workers/poll_expiration_notify_worker.rb b/app/workers/poll_expiration_notify_worker.rb index 64b4cbd7e46b01db2f4aea7847b7e6b0c2754cc4..f0191d4799daad1500eac23433f2b92a981b1fde 100644 --- a/app/workers/poll_expiration_notify_worker.rb +++ b/app/workers/poll_expiration_notify_worker.rb @@ -11,12 +11,12 @@ class PollExpirationNotifyWorker # Notify poll owner and remote voters if poll.local? ActivityPub::DistributePollUpdateWorker.perform_async(poll.status.id) - NotifyService.new.call(poll.account, poll) + NotifyService.new.call(poll.account, :poll, poll) end # Notify local voters - poll.votes.includes(:account).map(&:account).select(&:local?).each do |account| - NotifyService.new.call(account, poll) + poll.votes.includes(:account).group(:account_id).select(:account_id).map(&:account).select(&:local?).each do |account| + NotifyService.new.call(account, :poll, poll) end rescue ActiveRecord::RecordNotFound true diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb index 9b07ce1b56a13ea5aa7b7045ab25a58492d914e9..319b001097b4374a1416865122256d39fd117bb3 100644 --- a/app/workers/refollow_worker.rb +++ b/app/workers/refollow_worker.rb @@ -11,6 +11,7 @@ class RefollowWorker target_account.passive_relationships.where(account: Account.where(domain: nil)).includes(:account).reorder(nil).find_each do |follow| reblogs = follow.show_reblogs? + notify = follow.notify? # Locally unfollow remote account follower = follow.account @@ -18,7 +19,7 @@ class RefollowWorker # Schedule re-follow begin - FollowService.new.call(follower, target_account, reblogs: reblogs) + FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, bypass_limit: true) rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError next end diff --git a/app/workers/scheduler/feed_cleanup_scheduler.rb b/app/workers/scheduler/feed_cleanup_scheduler.rb index 458fe6193e53d69877baeb5968bb49c3624a702f..42b29f4eca072681ad9ef71b96615fc51c80a709 100644 --- a/app/workers/scheduler/feed_cleanup_scheduler.rb +++ b/app/workers/scheduler/feed_cleanup_scheduler.rb @@ -14,37 +14,11 @@ class Scheduler::FeedCleanupScheduler private def clean_home_feeds! - clean_feeds!(inactive_account_ids, :home) + feed_manager.clean_feeds!(:home, inactive_account_ids) end def clean_list_feeds! - clean_feeds!(inactive_list_ids, :list) - end - - def clean_feeds!(ids, type) - reblogged_id_sets = {} - - redis.pipelined do - ids.each do |feed_id| - redis.del(feed_manager.key(type, feed_id)) - reblog_key = feed_manager.key(type, feed_id, 'reblogs') - # We collect a future for this: we don't block while getting - # it, but we can iterate over it later. - reblogged_id_sets[feed_id] = redis.zrange(reblog_key, 0, -1) - redis.del(reblog_key) - end - end - - # Remove all of the reblog tracking keys we just removed the - # references to. - redis.pipelined do - reblogged_id_sets.each do |feed_id, future| - future.value.each do |reblogged_id| - reblog_set_key = feed_manager.key(type, feed_id, "reblogs:#{reblogged_id}") - redis.del(reblog_set_key) - end - end - end + feed_manager.clean_feeds!(:list, inactive_list_ids) end def inactive_account_ids diff --git a/app/workers/scheduler/instance_refresh_scheduler.rb b/app/workers/scheduler/instance_refresh_scheduler.rb new file mode 100644 index 0000000000000000000000000000000000000000..917404beccb3addce4315c64740b51a6d8341f1a --- /dev/null +++ b/app/workers/scheduler/instance_refresh_scheduler.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Scheduler::InstanceRefreshScheduler + include Sidekiq::Worker + + sidekiq_options lock: :until_executed, retry: 0 + + def perform + Instance.refresh + end +end diff --git a/app/workers/scheduler/ip_cleanup_scheduler.rb b/app/workers/scheduler/ip_cleanup_scheduler.rb index 6d38b52a2988de2965a53cfbe5dcf819a69b5049..853f20e2515c367b47cc4e1450dff9938b6026c6 100644 --- a/app/workers/scheduler/ip_cleanup_scheduler.rb +++ b/app/workers/scheduler/ip_cleanup_scheduler.rb @@ -3,13 +3,23 @@ class Scheduler::IpCleanupScheduler include Sidekiq::Worker - RETENTION_PERIOD = 1.year + IP_RETENTION_PERIOD = 1.year.freeze sidekiq_options lock: :until_executed, retry: 0 def perform - time_ago = RETENTION_PERIOD.ago - SessionActivation.where('updated_at < ?', time_ago).in_batches.destroy_all - User.where('last_sign_in_at < ?', time_ago).where.not(last_sign_in_ip: nil).in_batches.update_all(last_sign_in_ip: nil) + clean_ip_columns! + clean_expired_ip_blocks! + end + + private + + def clean_ip_columns! + SessionActivation.where('updated_at < ?', IP_RETENTION_PERIOD.ago).in_batches.destroy_all + User.where('current_sign_in_at < ?', IP_RETENTION_PERIOD.ago).in_batches.update_all(last_sign_in_ip: nil, current_sign_in_ip: nil, sign_up_ip: nil) + end + + def clean_expired_ip_blocks! + IpBlock.expired.in_batches.destroy_all end end diff --git a/app/workers/scheduler/user_cleanup_scheduler.rb b/app/workers/scheduler/user_cleanup_scheduler.rb index 6113edde17b301a15f2ea67f846bf7b498b0ff12..8571b59e1408e1e7d455d84b8ecda4c772f01a53 100644 --- a/app/workers/scheduler/user_cleanup_scheduler.rb +++ b/app/workers/scheduler/user_cleanup_scheduler.rb @@ -6,9 +6,22 @@ class Scheduler::UserCleanupScheduler sidekiq_options lock: :until_executed, retry: 0 def perform + clean_unconfirmed_accounts! + clean_suspended_accounts! + end + + private + + def clean_unconfirmed_accounts! User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch| Account.where(id: batch.map(&:account_id)).delete_all User.where(id: batch.map(&:id)).delete_all end end + + def clean_suspended_accounts! + AccountDeletionRequest.where('created_at <= ?', AccountDeletionRequest::DELAY_TO_DELETION.ago).reorder(nil).find_each do |deletion_request| + Admin::AccountDeletionWorker.perform_async(deletion_request.account_id) + end + end end diff --git a/app/workers/unfollow_follow_worker.rb b/app/workers/unfollow_follow_worker.rb index b6e665a41fbd67bceb6ce00b14f3fdfa6cca1a62..0bd5ff472e845d03eb5d5a03fe9b3632bc5e8424 100644 --- a/app/workers/unfollow_follow_worker.rb +++ b/app/workers/unfollow_follow_worker.rb @@ -10,10 +10,11 @@ class UnfollowFollowWorker old_target_account = Account.find(old_target_account_id) new_target_account = Account.find(new_target_account_id) - follow = follower_account.active_relationships.find_by(target_account: old_target_account) + follow = follower_account.active_relationships.find_by(target_account: old_target_account) reblogs = follow&.show_reblogs? + notify = follow&.notify? - FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, bypass_locked: bypass_locked) + FollowService.new.call(follower_account, new_target_account, reblogs: reblogs, notify: notify, bypass_locked: bypass_locked, bypass_limit: true) UnfollowService.new.call(follower_account, old_target_account, skip_unmerge: true) rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError true diff --git a/app/workers/unmerge_worker.rb b/app/workers/unmerge_worker.rb index ea6aacebf6df28fc7bad92bb8fc455661a16155e..1a23faae51f67632e1aac7db8d235bf2c1e5e431 100644 --- a/app/workers/unmerge_worker.rb +++ b/app/workers/unmerge_worker.rb @@ -6,6 +6,8 @@ class UnmergeWorker sidekiq_options queue: 'pull' def perform(from_account_id, into_account_id) - FeedManager.instance.unmerge_from_timeline(Account.find(from_account_id), Account.find(into_account_id)) + FeedManager.instance.unmerge_from_home(Account.find(from_account_id), Account.find(into_account_id)) + rescue ActiveRecord::RecordNotFound + true end end diff --git a/bin/heroku-web b/bin/heroku-web new file mode 100755 index 0000000000000000000000000000000000000000..219ef35b978bc169e7bff1e2b03a07f322e1ba0d --- /dev/null +++ b/bin/heroku-web @@ -0,0 +1,2 @@ +#!/bin/bash +if [ "$RUN_STREAMING" != "true" ]; then BIND=0.0.0.0 bundle exec puma -C config/puma.rb; else BIND=0.0.0.0 node ./streaming; fi \ No newline at end of file diff --git a/boxfile.yml b/boxfile.yml index c4fd19ce6039a2c3264f0ae8d923a70c1826cc46..c1d89bb159febf8b6a75845f70a3e33875f50470 100644 --- a/boxfile.yml +++ b/boxfile.yml @@ -110,6 +110,7 @@ worker.sidekiq: mailers: bundle exec sidekiq -c 5 -q mailers -L /app/log/sidekiq.log pull: bundle exec sidekiq -c 5 -q pull -L /app/log/sidekiq.log push: bundle exec sidekiq -c 5 -q push -L /app/log/sidekiq.log + scheduler: bundle exec sidekiq -c 5 -q scheduler -L /app/log/sidekiq.log writable_dirs: - tmp diff --git a/chart/Chart.yaml b/chart/Chart.yaml index 783569451d37c54f467587d1b7292e199915f200..19f9c64c741becf97874e56d0e86da4603872b52 100644 --- a/chart/Chart.yaml +++ b/chart/Chart.yaml @@ -15,12 +15,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 0.1.2 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 3.1.5 +appVersion: 3.3.0 dependencies: - name: elasticsearch diff --git a/chart/templates/cronjob-media-remove.yaml b/chart/templates/cronjob-media-remove.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8a01a255181bdf7bd59ac9885af04faa0093069b --- /dev/null +++ b/chart/templates/cronjob-media-remove.yaml @@ -0,0 +1,73 @@ +{{ if .Values.cron.removeMedia.enabled }} +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: {{ include "mastodon.fullname" . }}-media-remove + labels: + {{- include "mastodon.labels" . | nindent 4 }} +spec: + schedule: {{ .Values.cron.removeMedia.schedule }} + jobTemplate: + spec: + template: + metadata: + name: {{ include "mastodon.fullname" . }}-media-remove + spec: + restartPolicy: OnFailure + # ensure we run on the same node as the other rails components; only + # required when using PVCs that are ReadWriteOnce + {{- if or (eq "ReadWriteOnce" .Values.persistence.assets.accessMode) (eq "ReadWriteOnce" .Values.persistence.system.accessMode) }} + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: component + operator: In + values: + - rails + topologyKey: kubernetes.io/hostname + {{- end }} + volumes: + - name: assets + persistentVolumeClaim: + claimName: {{ template "mastodon.fullname" . }}-assets + - name: system + persistentVolumeClaim: + claimName: {{ template "mastodon.fullname" . }}-system + containers: + - name: {{ include "mastodon.fullname" . }}-media-remove + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - bin/tootctl + - media + - remove + envFrom: + - configMapRef: + name: {{ include "mastodon.fullname" . }}-env + - secretRef: + name: {{ template "mastodon.fullname" . }} + env: + - name: "DB_PASS" + valueFrom: + secretKeyRef: + {{- if .Values.postgresql.enabled }} + name: {{ .Release.Name }}-postgresql + {{- else }} + name: {{ template "mastodon.fullname" . }}-postgresql + {{- end }} + key: postgresql-password + - name: "REDIS_PASSWORD" + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-redis + key: redis-password + - name: "PORT" + value: {{ .Values.application.web.port | quote }} + volumeMounts: + - name: assets + mountPath: /opt/mastodon/public/assets + - name: system + mountPath: /opt/mastodon/public/system +{{- end }} diff --git a/chart/values.yaml.template b/chart/values.yaml.template index 694bc4d4224bfb8a58261608a1fbfd5e44e9c50f..9e50c6daca054563e6aedb8029dfa35743b750b8 100644 --- a/chart/values.yaml.template +++ b/chart/values.yaml.template @@ -4,7 +4,7 @@ image: repository: tootsuite/mastodon pullPolicy: Always # https://hub.docker.com/r/tootsuite/mastodon/tags - tag: v3.1.5 + tag: v3.3.0 # alternatively, use `latest` for the latest release or `edge` for the image # built from the most recent commit # @@ -39,6 +39,12 @@ createAdmin: # available locales: https://github.com/tootsuite/mastodon/blob/master/config/application.rb#L43 locale: en +cron: + # run `tootctl media remove` every week + removeMedia: + enabled: true + schedule: "0 0 * * 0" + application: web: port: 3000 diff --git a/config/application.rb b/config/application.rb index ad6cf82d70f9710df3196214a06396d4a736dd5b..af77352212ff90f94cc6167db1394f82ceee2a5f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -22,6 +22,8 @@ require_relative '../lib/mastodon/version' require_relative '../lib/devise/two_factor_ldap_authenticatable' require_relative '../lib/devise/two_factor_pam_authenticatable' require_relative '../lib/chewy/strategy/custom_sidekiq' +require_relative '../lib/webpacker/manifest_extensions' +require_relative '../lib/webpacker/helper_extensions' Dotenv::Railtie.load @@ -83,6 +85,7 @@ module Mastodon :kk, :kn, :ko, + :ku, :lt, :lv, :mk, @@ -98,6 +101,8 @@ module Mastodon :'pt-PT', :ro, :ru, + :sa, + :sc, :sk, :sl, :sq, @@ -111,6 +116,7 @@ module Mastodon :uk, :ur, :vi, + :zgh, :'zh-CN', :'zh-HK', :'zh-TW', @@ -134,6 +140,7 @@ module Mastodon Doorkeeper::AuthorizationsController.layout 'modal' Doorkeeper::AuthorizedApplicationsController.layout 'admin' Doorkeeper::Application.send :include, ApplicationExtension + Doorkeeper::AccessToken.send :include, AccessTokenExtension Devise::FailureApp.send :include, AbstractController::Callbacks Devise::FailureApp.send :include, HttpAcceptLanguage::EasyAccess Devise::FailureApp.send :include, Localized diff --git a/config/boot.rb b/config/boot.rb index f3e36203aad90ff0b9874d6def3c6fa842941e0c..6cde5319d48414e15f593bca26637f6a6c124b86 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,8 @@ +unless ENV.key?('RAILS_ENV') + STDERR.puts 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' + exit 1 +end + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/brakeman.ignore b/config/brakeman.ignore index baa993c78ad9161eeb67ba72f2a1a4890413d0a2..dcbfd02b4e8cb17e85595cd3d89f8fe2c3f36726 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -102,6 +102,37 @@ "confidence": "Weak", "note": "" }, + { + "warning_type": "Dynamic Render Path", + "warning_code": 15, + "fingerprint": "4704e8093e3e0561bf705f892e8fc6780419f8255f4440b1c0afd09339bd6446", + "check_name": "Render", + "message": "Render path contains parameter value", + "file": "app/views/admin/instances/index.html.haml", + "line": 39, + "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/", + "code": "render(action => filtered_instances.page(params[:page]), {})", + "render_path": [ + { + "type": "controller", + "class": "Admin::InstancesController", + "method": "index", + "line": 10, + "file": "app/controllers/admin/instances_controller.rb", + "rendered": { + "name": "admin/instances/index", + "file": "app/views/admin/instances/index.html.haml" + } + } + ], + "location": { + "type": "template", + "template": "admin/instances/index" + }, + "user_input": "params[:page]", + "confidence": "Weak", + "note": "" + }, { "warning_type": "Redirect", "warning_code": 18, @@ -122,6 +153,26 @@ "confidence": "High", "note": "" }, + { + "warning_type": "SQL Injection", + "warning_code": 0, + "fingerprint": "6e4051854bb62e2ddbc671f82d6c2328892e1134b8b28105ecba9b0122540714", + "check_name": "SQL", + "message": "Possible SQL injection", + "file": "app/models/account.rb", + "line": 491, + "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", + "code": "find_by_sql([\" WITH first_degree AS (\\n SELECT target_account_id\\n FROM follows\\n WHERE account_id = ?\\n UNION ALL\\n SELECT ?\\n )\\n SELECT\\n accounts.*,\\n (count(f.id) + 1) * ts_rank_cd(#{textsearch}, #{query}, 32) AS rank\\n FROM accounts\\n LEFT OUTER JOIN follows AS f ON (accounts.id = f.account_id AND f.target_account_id = ?)\\n WHERE accounts.id IN (SELECT * FROM first_degree)\\n AND #{query} @@ #{textsearch}\\n AND accounts.suspended_at IS NULL\\n AND accounts.moved_to_account_id IS NULL\\n GROUP BY accounts.id\\n ORDER BY rank DESC\\n LIMIT ? OFFSET ?\\n\".squish, account.id, account.id, account.id, limit, offset])", + "render_path": null, + "location": { + "type": "method", + "class": "Account", + "method": "advanced_search_for" + }, + "user_input": "textsearch", + "confidence": "Medium", + "note": "" + }, { "warning_type": "SQL Injection", "warning_code": 0, @@ -163,23 +214,23 @@ "note": "" }, { - "warning_type": "Mass Assignment", - "warning_code": 105, - "fingerprint": "8f63dec68951d9bcf7eddb15af9392b2e1333003089c41fb76688dfd3579f394", - "check_name": "PermitAttributes", - "message": "Potentially dangerous key allowed for mass assignment", - "file": "app/controllers/api/v1/crypto/deliveries_controller.rb", - "line": 23, - "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", - "code": "params.require(:device).permit(:account_id, :device_id, :type, :body, :hmac)", + "warning_type": "SQL Injection", + "warning_code": 0, + "fingerprint": "9251d682c4e2840e1b2fea91e7d758efe2097ecb7f6255c065e3750d25eb178c", + "check_name": "SQL", + "message": "Possible SQL injection", + "file": "app/models/account.rb", + "line": 460, + "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", + "code": "find_by_sql([\" SELECT\\n accounts.*,\\n ts_rank_cd(#{textsearch}, #{query}, 32) AS rank\\n FROM accounts\\n WHERE #{query} @@ #{textsearch}\\n AND accounts.suspended_at IS NULL\\n AND accounts.moved_to_account_id IS NULL\\n ORDER BY rank DESC\\n LIMIT ? OFFSET ?\\n\".squish, limit, offset])", "render_path": null, "location": { "type": "method", - "class": "Api::V1::Crypto::DeliveriesController", - "method": "resource_params" + "class": "Account", + "method": "search_for" }, - "user_input": ":account_id", - "confidence": "High", + "user_input": "textsearch", + "confidence": "Medium", "note": "" }, { @@ -273,6 +324,26 @@ "confidence": "High", "note": "" }, + { + "warning_type": "SQL Injection", + "warning_code": 0, + "fingerprint": "e21d8fee7a5805761679877ca35ed1029c64c45ef3b4012a30262623e1ba8bb9", + "check_name": "SQL", + "message": "Possible SQL injection", + "file": "app/models/account.rb", + "line": 507, + "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", + "code": "find_by_sql([\" SELECT\\n accounts.*,\\n (count(f.id) + 1) * ts_rank_cd(#{textsearch}, #{query}, 32) AS rank\\n FROM accounts\\n LEFT OUTER JOIN follows AS f ON (accounts.id = f.account_id AND f.target_account_id = ?) OR (accounts.id = f.target_account_id AND f.account_id = ?)\\n WHERE #{query} @@ #{textsearch}\\n AND accounts.suspended_at IS NULL\\n AND accounts.moved_to_account_id IS NULL\\n GROUP BY accounts.id\\n ORDER BY rank DESC\\n LIMIT ? OFFSET ?\\n\".squish, account.id, account.id, limit, offset])", + "render_path": null, + "location": { + "type": "method", + "class": "Account", + "method": "advanced_search_for" + }, + "user_input": "textsearch", + "confidence": "Medium", + "note": "" + }, { "warning_type": "Mass Assignment", "warning_code": 105, @@ -294,6 +365,6 @@ "note": "" } ], - "updated": "2020-06-01 18:18:02 +0200", - "brakeman_version": "4.8.0" + "updated": "2020-12-07 01:17:13 +0100", + "brakeman_version": "4.10.0" } diff --git a/config/initializers/cache_buster.rb b/config/initializers/cache_buster.rb new file mode 100644 index 0000000000000000000000000000000000000000..227e450f35c1e0df953995625f2f88e0ce7b35d5 --- /dev/null +++ b/config/initializers/cache_buster.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +Rails.application.configure do + config.x.cache_buster_enabled = ENV['CACHE_BUSTER_ENABLED'] == 'true' + + config.x.cache_buster = { + secret_header: ENV['CACHE_BUSTER_SECRET_HEADER'], + secret: ENV['CACHE_BUSTER_SECRET'], + } +end diff --git a/config/initializers/chewy.rb b/config/initializers/chewy.rb index 8f54abf77890a533871e961c52ad74bd8851c8ed..9fc9b2f1a59368e8d87322242a46ce2cb57e93b9 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -12,6 +12,10 @@ Chewy.settings = { sidekiq: { queue: 'pull' }, } +# We use our own async strategy even outside the request-response +# cycle, which takes care of checking if ElasticSearch is enabled +# or not. However, mind that for the Rails console, the :urgent +# strategy is set automatically with no way to override it. Chewy.root_strategy = :custom_sidekiq Chewy.request_strategy = :custom_sidekiq Chewy.use_after_commit_callbacks = false @@ -37,6 +41,7 @@ Elasticsearch::Transport::Client.prepend Module.new { super arguments end } + Elasticsearch::API::Indices::IndicesClient.prepend Module.new { def create(arguments = {}) arguments[:include_type_name] = true diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 59e69ad375feeb25d42038eb6b447f0702eb1d33..ef612e177de2fc7557653944f613717064eecc72 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -10,6 +10,7 @@ Warden::Manager.after_set_user except: :fetch do |user, warden| expires: 1.year.from_now, httponly: true, secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'), + same_site: :lax, } end @@ -20,6 +21,7 @@ Warden::Manager.after_fetch do |user, warden| expires: 1.year.from_now, httponly: true, secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'), + same_site: :lax, } else warden.logout diff --git a/config/initializers/makara.rb b/config/initializers/makara.rb new file mode 100644 index 0000000000000000000000000000000000000000..dc88fa63cd09430875d3ab5bd0508e8183f09ecb --- /dev/null +++ b/config/initializers/makara.rb @@ -0,0 +1,2 @@ +Makara::Cookie::DEFAULT_OPTIONS[:same_site] = :lax +Makara::Cookie::DEFAULT_OPTIONS[:secure] = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true' diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index b4849370dbd2bc2d4c7f776979a92f2d592e67c0..9ad7fd814c80dac34d29c05a0269e46731d3f4f3 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -62,7 +62,7 @@ if ENV['S3_ENABLED'] == 'true' s3_options: { signature_version: ENV.fetch('S3_SIGNATURE_VERSION') { 'v4' }, http_open_timeout: ENV.fetch('S3_OPEN_TIMEOUT'){ '5' }.to_i, - http_read_timeout: 5, + http_read_timeout: ENV.fetch('S3_READ_TIMEOUT'){ '5' }.to_i, http_idle_timeout: 5, retry_limit: 0, } @@ -107,10 +107,20 @@ elsif ENV['SWIFT_ENABLED'] == 'true' else Paperclip::Attachment.default_options.merge!( storage: :filesystem, - use_timestamp: true, path: File.join(ENV.fetch('PAPERCLIP_ROOT_PATH', File.join(':rails_root', 'public', 'system')), ':prefix_path:class', ':attachment', ':id_partition', ':style', ':filename'), url: ENV.fetch('PAPERCLIP_ROOT_URL', '/system') + '/:prefix_url:class/:attachment/:id_partition/:style/:filename', ) end Paperclip.options[:content_type_mappings] = { csv: Import::FILE_TYPES } + +# In some places in the code, we rescue this exception, but we don't always +# load the S3 library, so it may be an undefined constant: + +unless defined?(Seahorse) + module Seahorse + module Client + class NetworkingError < StandardError; end + end + end +end diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index cd29afac5258bc6b6485a22550e7bb26c2c88418..6662ef40b035a0a90410af2d672659c9d8ab35f1 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -42,6 +42,10 @@ class Rack::Attack req.remote_ip == '127.0.0.1' || req.remote_ip == '::1' end + Rack::Attack.blocklist('deny from blocklist') do |req| + IpBlock.blocked?(req.remote_ip) + end + throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req| req.authenticated_user_id if req.api_request? end diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 3dc0edd6fd262f70a6c496c922beb97bd096003c..e5d1be4c6c7d53619c7bcd40c1806ef77ca669ce 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,7 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.session_store :cookie_store, key: '_mastodon_session', secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true') +Rails.application.config.session_store :cookie_store, { + key: '_mastodon_session', + secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'), + same_site: :lax, +} diff --git a/config/initializers/twitter_regex.rb b/config/initializers/twitter_regex.rb index f84f7c0cbb62caca001a0d2a34fd992f7ad8e9ad..7f99a0005649e6f9b6c74e2676a1011831c57df4 100644 --- a/config/initializers/twitter_regex.rb +++ b/config/initializers/twitter_regex.rb @@ -29,7 +29,7 @@ module Twitter ( # $1 total match (#{REGEXEN[:valid_url_preceding_chars]}) # $2 Preceding character ( # $3 URL - ((?:https?|dat|dweb|ipfs|ipns|ssb|gopher):\/\/)? # $4 Protocol (optional) + ((?:https?|dat|dweb|ipfs|ipns|ssb|gopher|gemini):\/\/)? # $4 Protocol (optional) (#{REGEXEN[:valid_domain]}) # $5 Domain(s) (?::(#{REGEXEN[:valid_port_number]}))? # $6 Port number (optional) (/#{REGEXEN[:valid_url_path]}*)? # $7 URL Path and anchor diff --git a/config/initializers/webauthn.rb b/config/initializers/webauthn.rb new file mode 100644 index 0000000000000000000000000000000000000000..a0a5b815378a15eca05340e7f0b2b87bd5195c1a --- /dev/null +++ b/config/initializers/webauthn.rb @@ -0,0 +1,24 @@ +WebAuthn.configure do |config| + # This value needs to match `window.location.origin` evaluated by + # the User Agent during registration and authentication ceremonies. + config.origin = "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" + + # Relying Party name for display purposes + config.rp_name = "Mastodon" + + # Optionally configure a client timeout hint, in milliseconds. + # This hint specifies how long the browser should wait for an + # attestation or an assertion response. + # This hint may be overridden by the browser. + # https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout + config.credential_options_timeout = 120_000 + + # You can optionally specify a different Relying Party ID + # (https://www.w3.org/TR/webauthn/#relying-party-identifier) + # if it differs from the default one. + # + # In this case the default would be "auth.example.com", but you can set it to + # the suffix "example.com" + # + # config.rp_id = "example.com" +end diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index f40e6c36132b1e227a261ccb87a6d1a1abdf5e95..2fbf0ffd710189ce2905acb59a57eba453b1b9f9 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -1,17 +1 @@ ---- -es: - activerecord: - attributes: - poll: - expires_at: Vencimiento - options: Opciones - errors: - models: - account: - attributes: - username: - invalid: sólo letras, números y guiones bajos - status: - attributes: - reblog: - taken: del estado ya existe +--- {} diff --git a/config/locales/activerecord.hi.yml b/config/locales/activerecord.hi.yml index d758a5b5357d76effdf363eeb2c8e0dfb231c4aa..b002ab0933bdf81204e2a39b7e56d8f2cf0c5c42 100644 --- a/config/locales/activerecord.hi.yml +++ b/config/locales/activerecord.hi.yml @@ -1 +1,17 @@ +--- hi: + activerecord: + attributes: + poll: + expires_at: समयसीमा + options: विकलà¥à¤ª + errors: + models: + account: + attributes: + username: + invalid: केवल अकà¥à¤·à¤°, संखà¥à¤¯à¤¾ और अंडरसà¥à¤•ोर + status: + attributes: + reblog: + taken: सà¥à¤¥à¤¿à¤¤à¤¿ पहले से मौजूद है diff --git a/config/locales/activerecord.hr.yml b/config/locales/activerecord.hr.yml index f67f33c7e0cfcce80b0d9e2a044068a78a531865..98ca8155fdaa25b5215f9c268341ccc99cdfc244 100644 --- a/config/locales/activerecord.hr.yml +++ b/config/locales/activerecord.hr.yml @@ -1 +1,7 @@ +--- hr: + activerecord: + attributes: + poll: + expires_at: Krajnji rok + options: Opcije diff --git a/config/locales/activerecord.kab.yml b/config/locales/activerecord.kab.yml index 24e2760dac0738652d83dcfe9c3c579573acfaef..d6b3c40e4a23f31710fc9be62c5a87672c8c28f7 100644 --- a/config/locales/activerecord.kab.yml +++ b/config/locales/activerecord.kab.yml @@ -3,7 +3,7 @@ kab: activerecord: attributes: poll: - expires_at: Azemz n tagara + expires_at: Azemz n taggara options: Tifranin errors: models: diff --git a/config/locales/activerecord.ku.yml b/config/locales/activerecord.ku.yml index cc251e86ae3fc9c96ba4a32a86e9e41868ac09d9..3b976de8c4766c48dbb6fc0cfa79a71818afb809 100644 --- a/config/locales/activerecord.ku.yml +++ b/config/locales/activerecord.ku.yml @@ -1 +1,17 @@ -ckb-IR: +--- +ku: + activerecord: + attributes: + poll: + expires_at: وادەی کۆتایی + options: هەڵبژاردنەکان + errors: + models: + account: + attributes: + username: + invalid: تەنها پیت، ژمارە Ùˆ ژێرەوە + status: + attributes: + reblog: + taken: Ù„Û• بار بوونی هەیە diff --git a/config/locales/activerecord.sa.yml b/config/locales/activerecord.sa.yml new file mode 100644 index 0000000000000000000000000000000000000000..07ea4372a3a109674214ba80f2070c9f99fb872d --- /dev/null +++ b/config/locales/activerecord.sa.yml @@ -0,0 +1 @@ +sa: diff --git a/config/locales/activerecord.sc.yml b/config/locales/activerecord.sc.yml index 6467372690a4143ae03c3f28c23bdd1406a2c5d6..cae24d30c1d5925edac4d5d360ffc6cd1f82f351 100644 --- a/config/locales/activerecord.sc.yml +++ b/config/locales/activerecord.sc.yml @@ -4,3 +4,14 @@ sc: attributes: poll: expires_at: Iscadèntzia + options: Seberos + errors: + models: + account: + attributes: + username: + invalid: petzi lìteras, nùmeros e tratigheddos bassos + status: + attributes: + reblog: + taken: de s'istadu esistet giai diff --git a/config/locales/activerecord.sv.yml b/config/locales/activerecord.sv.yml index 8d142e7acd9aa0259e12980952b56e2358f83fe5..67c1608219bc8dd27ca44473f265ceba629f8888 100644 --- a/config/locales/activerecord.sv.yml +++ b/config/locales/activerecord.sv.yml @@ -11,3 +11,7 @@ sv: attributes: username: invalid: endast bokstäver, siffror och understrykning + status: + attributes: + reblog: + taken: av status finns redan diff --git a/config/locales/activerecord.th.yml b/config/locales/activerecord.th.yml index fd71e36d221f5b68bd41109183dbca89f703c9ad..4dea79b882f7bfb9716b31e24180d3edc3e4c81e 100644 --- a/config/locales/activerecord.th.yml +++ b/config/locales/activerecord.th.yml @@ -14,4 +14,4 @@ th: status: attributes: reblog: - taken: มีสถานะà¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ + taken: ขà¸à¸‡à¸ªà¸–านะมีà¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ diff --git a/config/locales/activerecord.tr.yml b/config/locales/activerecord.tr.yml index 8ce55599cb3b96c656effaf35bdf402b3de8fcae..336c83e7b8b6f40e66eccc3fa7769591c2c230bf 100644 --- a/config/locales/activerecord.tr.yml +++ b/config/locales/activerecord.tr.yml @@ -3,7 +3,7 @@ tr: activerecord: attributes: poll: - expires_at: Son Teslim Tarihi + expires_at: BitiÅŸ zamanı options: Seçenekler errors: models: diff --git a/config/locales/activerecord.tt.yml b/config/locales/activerecord.tt.yml new file mode 100644 index 0000000000000000000000000000000000000000..5eab4abff95e2119202e91e8d75bd785c9ccbdc9 --- /dev/null +++ b/config/locales/activerecord.tt.yml @@ -0,0 +1 @@ +tt: diff --git a/config/locales/activerecord.zgh.yml b/config/locales/activerecord.zgh.yml new file mode 100644 index 0000000000000000000000000000000000000000..8271554666df69414a57b28544cac7837eb71268 --- /dev/null +++ b/config/locales/activerecord.zgh.yml @@ -0,0 +1 @@ +zgh: diff --git a/config/locales/activerecord.zh-HK.yml b/config/locales/activerecord.zh-HK.yml index c968e55aa600f5f996656b7658b49231f6344697..89c3fa02d981371d62449d88a7a80f3f24f8e80d 100644 --- a/config/locales/activerecord.zh-HK.yml +++ b/config/locales/activerecord.zh-HK.yml @@ -4,7 +4,7 @@ zh-HK: attributes: poll: expires_at: æˆªæ¢æ™‚é–“ - options: 鏿“‡ + options: é¸é … errors: models: account: diff --git a/config/locales/ar.yml b/config/locales/ar.yml index b82b030a3e6cbf0c5b60662e086751c2a50da983..44ada75d1fe4743c1bd633e45ee9552d12e3f0e6 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -45,6 +45,7 @@ ar: silenced: 'سيتم Ø¥Ø®ÙØ§Ø¡ المنشورات القادمة من هذه الخوادم ÙÙŠ الخيوط الزمنية ÙˆØ§Ù„Ù…ØØ§Ø¯Ø«Ø§Øª العامة، ولن يتم إنشاء أي إخطارات من جراء ØªÙØ§Ø¹Ù„ات مستخدميها، ما لم ØªÙØªÙŽØ§Ø¨Ø¹Ù‡Ù…:' silenced_title: الخوادم المكتومة suspended: 'لن يتم معالجة أي بيانات قادمة من هذه الخوادم أو تخزينها أو تبادلها، مما سيجعل أي ØªÙØ§Ø¹Ù„ أو اتصال مع المستخدمين والمستخدمات المنتمين إلى هذه الخوادم مستØÙŠÙ„Ø©:' + suspended_title: الخوادم المعلَّقة unavailable_content_html: ÙŠØ³Ù…Ø Ù„Ùƒ ماستدون عموماً بعرض Ù…ØØªÙˆÙ‰ المستخدمين القادم من أي خادم آخر ÙÙŠ Ø§Ù„ÙØ¯ÙŠÙرس ÙˆØ§Ù„ØªÙØ§Ø¹Ù„ معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادوم بالذات. user_count_after: few: مستخدمين @@ -441,6 +442,14 @@ ar: expired: المنتهي صلاØÙŠØªÙ‡Ø§ title: التصÙية title: الدعوات + ip_blocks: + expires_in: + '1209600': أسبوعان + '15778476': 6 أشهر + '2629746': شهر ÙˆØ§ØØ¯ + '31556952': سنة ÙˆØ§ØØ¯Ø© + '86400': يوم ÙˆØ§ØØ¯ + '94670856': 3 سنوات pending_accounts: title: Ø§Ù„ØØ³Ø§Ø¨Ø§Øª المعلقة (%{count}) relationships: @@ -613,6 +622,7 @@ ar: tags: accounts_today: استخدامات هذا اليوم accounts_week: استخدامات هذا الأسبوع + breakdown: توزيع استخدام اليوم ØØ³Ø¨ المصدر context: السياق directory: ÙÙŠ دليل ØØ³Ø§Ø¨Ø§Øª المستخدمين in_directory: "%{count} ÙÙŠ سجل ØØ³Ø§Ø¨Ø§Øª المستخدمين" @@ -1212,21 +1222,15 @@ ar: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: قم بإدخال الرمز المÙوَلّد عبر تطبيق المصادقة للتأكيد - description_html: ÙÙŠ ØØ§Ù„ ØªÙØ¹ÙŠÙ„ <strong>المصادقة بخطوتين </strong>ØŒ ÙØªØ³Ø¬ÙŠÙ„ الدخول يتطلب منك أن يكون بØÙˆØ²ØªÙƒ هاتÙÙƒ النقال قصد توليد الرمز الذي سيتم إدخاله. disable: تعطيل - enable: ØªÙØ¹ÙŠÙ„ enabled: نظام المصادقة بخطوتين Ù…ÙÙØ¹Ù‘ÙŽÙ„ enabled_success: تم ØªÙØ¹ÙŠÙ„ المصادقة بخطوتين Ø¨Ù†Ø¬Ø§Ø generate_recovery_codes: توليد رموز الاسترجاع - instructions_html: "<strong>قم Ø¨Ù…Ø³Ø Ø±Ù…Ø² الكيو آر عبر Google Authenticator أو أي تطبيق TOTP على جهازك</strong>. من الآن ÙØµØ§Ø¹Ø¯Ø§ سو٠يقوم ذاك التطبيق بتوليد رموز يجب عليك إدخالها عند تسجيل الدخول." lost_recovery_codes: تÙمكّنك رموز الاسترجاع Ø§Ù„Ø§ØØªÙŠØ§Ø·ÙŠØ© Ù…ÙÙ† استرجاع Ø§Ù„Ù†ÙØ§Ø° إلى ØØ³Ø§Ø¨Ùƒ ÙÙŠ ØØ§Ù„Ø© Ùقدان جهازك المØÙ…ول. إن ضاعت منك هذه الرموز ÙØ¨Ø¥Ù…كانك إعادة توليدها Ù…ÙÙ† هنا Ùˆ إبطال الرموز القديمة. - manual_instructions: 'ÙÙŠ ØØ§Ù„Ø© تعذّر Ù…Ø³Ø Ø±Ù…Ø² الكيو آر أو Ø·Ùلب منك إدخال يدوي، ÙŠÙمْكÙنك إدخال هذا النص السري على التطبيق:' recovery_codes: النسخ Ø§Ù„Ø§ØØªÙŠØ§Ø·ÙŠ Ù„Ø±Ù…ÙˆØ² الاسترجاع recovery_codes_regenerated: تم إعادة توليد رموز الاسترجاع Ø§Ù„Ø§ØØªÙŠØ§Ø·ÙŠØ© Ø¨Ù†Ø¬Ø§Ø recovery_instructions_html: إن Ùقدت الوصول إلى هاتÙك، يمكنك استخدام Ø£ØØ¯ رموز الاسترداد أدناه لاستعادة الوصول إلى ØØ³Ø§Ø¨Ùƒ. <strong>ØØ§Ùظ على رموز الاسترداد بأمان</strong>. يمكنك ØŒ على سبيل المثال ØŒ طباعتها وتخزينها مع مستندات أخرى هامة. - setup: تنشيط - wrong_code: الرمز الذي أدخلته غير صالØ! تØÙ‚Ù‚ من ØµØØ© الوقت على الخادم Ùˆ الجهاز؟ + webauthn: Ù…ÙØ§ØªÙŠØ الأمان user_mailer: backup_ready: explanation: لقد قمت بطلب نسخة كاملة Ù„ØØ³Ø§Ø¨Ùƒ على ماستدون. إنها Ù…ØªÙˆÙØ±Ø© الآن للتنزيل! @@ -1276,9 +1280,11 @@ ar: tips: Ù†ØµØ§Ø¦Ø title: أهلاً بك، %{name}! users: + blocked_email_provider: مزوّد خدمة البريد الإلكتروني هذا غير Ù…Ø³Ù…ÙˆØ Ø¨Ù‡ follow_limit_reached: لا يمكنك متابعة أكثر Ù…ÙÙ† %{limit} أشخاص generic_access_help_html: ØµØ§Ø¯ÙØª مشكلة ÙÙŠ الوصول إلى ØØ³Ø§Ø¨ÙƒØŸ اتصل بـ %{email} Ù„Ù„ØØµÙˆÙ„ على المساعدة invalid_email: عنوان البريد الإلكتروني غير ØµØ§Ù„Ø + invalid_email_mx: لا يبدو أن عنوان البريد الإلكتروني موجود invalid_otp_token: رمز المصادقة بخطوتين غير ØµØ§Ù„Ø invalid_sign_in_token: رمز الآمان غير صØÙŠØ otp_lost_help_html: إن ÙقدتَهÙما ØŒ يمكنك الاتصال بـ %{email} diff --git a/config/locales/ast.yml b/config/locales/ast.yml index d88347f5b9e938d4d1ca596814bb4f5474306700..59dd30bed481959e2b6c43429bff2ce0772d1349 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -199,6 +199,7 @@ ast: description: suffix: "¡Con una cuenta, vas ser a siguir a persones, espublizar anovamientos ya intercambiar mensaxes con usuarios de cualesquier sirvidor de Mastodon y más!" didnt_get_confirmation: "¿Nun recibiesti les instrucciones de confirmación?" + dont_have_your_security_key: "¿Nun tienes una clave de seguranza?" forgot_password: "¿Escaeciesti la contraseña?" login: Aniciar sesión migrate_account: Mudase a otra cuenta @@ -437,6 +438,7 @@ ast: preferences: Preferencies profile: Perfil two_factor_authentication: Autenticación en dos pasos + webauthn_authentication: Claves d'autenticación spam_check: spam_detected: Esto ye un informe automatizáu. Deteutóse spam. statuses: @@ -483,15 +485,14 @@ ast: default: Mastodon mastodon-light: Claridá two_factor_authentication: - code_hint: Introduz el códigu xeneráu pola aplicación autenticadora pa confirmar disable: Desactivar enabled: L'autenticación en dos pasos ta activada enabled_success: L'autenticación en dos pasos activóse con ésitu generate_recovery_codes: Xenerar códigos de recuperación lost_recovery_codes: Los códigos de recuperación permÃtente recuperar l'accesu a la cuenta si pierdes el teléfonu. Si tamién pierdes estos códigos, pues rexeneralos equÃ. Los códigos de recuperación vieyos van invalidase. - manual_instructions: 'Si nun pues escaniar el códigu QR y precises introducilu a mano, equà ta''l secretu en testu planu:' recovery_codes: Códigos de recuperación recovery_codes_regenerated: Los códigos de recuperación rexeneráronse con ésitu + webauthn: Claves d'autenticación user_mailer: warning: explanation: diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 4142d439f7a1ac7658dae239d314c3e5773f6a30..9284f25bf15913cb5d72a85b68379d7bdb84ee5e 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -70,14 +70,6 @@ bg: blocking: СпиÑък на блокираните following: СпиÑък на поÑледователите upload: Качване - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day media_attachments: validations: images_and_video: Ðе мога да прикача видеоклип към публикациÑ, коÑто вече Ñъдържа Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ @@ -138,10 +130,7 @@ bg: formats: default: "%d %b, %Y, %H:%M" two_factor_authentication: - description_html: При Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð½Ð° <strong>двуÑтепенно удоÑтоверÑване</strong>, за да влезеш в приложението, ще трÑбва да използваш телефона Ñи. През него ще Ñе генерира код, който да въвеждаш при влизане. disable: Деактивирай - enable: Ðктивирай - instructions_html: "<strong>Сканирай този QR код Ñ Google Authenticator или подобно приложение от ÑÐ²Ð¾Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½</strong>. OÑ‚Ñега нататък, това приложение ще генерира код, който ще трÑбва да въвеждаш при вÑÑко влизане." users: invalid_email: E-mail адреÑÑŠÑ‚ е невалиден invalid_otp_token: Ðевалиден код diff --git a/config/locales/bn.yml b/config/locales/bn.yml index 3b575100f6735fdce51873b064d6f9e3b464f3d9..0cf936d682d3c757bb9fa7758bdc6506ad6be2c2 100644 --- a/config/locales/bn.yml +++ b/config/locales/bn.yml @@ -21,7 +21,9 @@ bn: federation_hint_html: "%{instance}তে à¦à¦•টা নিবনà§à¦§à¦¨ থাকলে আপনি যেকোনো মাসà§à¦Ÿà¦¾à¦¡à¦¨ বা à¦à¦§à¦°à¦£à§‡à¦° অনà§à¦¯à¦¾à¦¨à§à¦¯ সারà§à¦à¦¾à¦°à§‡à¦° মানà§à¦·à§‡à¦° সাথে যà§à¦•à§à¦¤ হতে পারবেন ।" get_apps: মোবাইল à¦à¦ªà§à¦ª à¦à¦•টা বà§à¦¯à¦¬à¦¹à¦¾à¦° করতে পারেন hosted_on: à¦à¦‡ মাসà§à¦Ÿà¦¾à¦¡à¦¨à¦Ÿà¦¿ আছে %{domain} ঠ- instance_actor_flash: à¦à¦‡ অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦Ÿà¦¿ à¦à¦¾à¦°à§à¦šà§à¦¯à¦¼à¦¾à¦² à¦à¦•à§à¦Ÿà¦° যা নিজে কোনও সারà§à¦à¦¾à¦°à§‡à¦° পà§à¦°à¦¤à¦¿à¦¨à¦¿à¦§à¦¿à¦¤à§à¦¬ করতে বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হয় à¦à¦¬à¦‚ কোনও পৃথক বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী নয়। à¦à¦Ÿà¦¿ ফেডারেশনের উদà§à¦¦à§‡à¦¶à§à¦¯à§‡ বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হয় à¦à¦¬à¦‚ আপনি যদি পà§à¦°à§‹ ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸ বà§à¦²à¦• করতে না চান তবে অবরà§à¦¦à§à¦§ করা উচিত নয়, সেকà§à¦·à§‡à¦¤à§à¦°à§‡ আপনার ডোমেন বà§à¦²à¦• বà§à¦¯à¦¬à¦¹à¦¾à¦° করা উচিত। + instance_actor_flash: 'à¦à¦‡ অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦Ÿà¦¿ à¦à¦¾à¦°à§à¦šà§à¦¯à¦¼à¦¾à¦² à¦à¦•à§à¦Ÿà¦° যা নিজে কোনও সারà§à¦à¦¾à¦°à§‡à¦° পà§à¦°à¦¤à¦¿à¦¨à¦¿à¦§à¦¿à¦¤à§à¦¬ করতে বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হয় à¦à¦¬à¦‚ কোনও পৃথক বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী নয়। à¦à¦Ÿà¦¿ ফেডারেশনের উদà§à¦¦à§‡à¦¶à§à¦¯à§‡ বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হয় à¦à¦¬à¦‚ আপনি যদি পà§à¦°à§‹ ইনসà§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸ বà§à¦²à¦• করতে না চান তবে অবরà§à¦¦à§à¦§ করা উচিত নয়, সেকà§à¦·à§‡à¦¤à§à¦°à§‡ আপনার ডোমেন বà§à¦²à¦• বà§à¦¯à¦¬à¦¹à¦¾à¦° করা উচিত। + +' learn_more: বিসà§à¦¤à¦¾à¦°à¦¿à¦¤ জানà§à¦¨ privacy_policy: গোপনীয়তা নীতি see_whats_happening: কী কী হচà§à¦›à§‡ দেখà§à¦¨ @@ -38,8 +40,11 @@ bn: domain: সারà§à¦à¦¾à¦° reason: কারণ rejecting_media: 'à¦à¦‡ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿ থেকে মিডিয়া ফাইলগà§à¦²à¦¿ পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾ করা বা সংরকà§à¦·à¦£ করা হবে না à¦à¦¬à¦‚ কোনও থামà§à¦¬à¦¨à§‡à¦‡à¦² পà§à¦°à¦¦à¦°à§à¦¶à¦¿à¦¤ হবে না, মূল ফাইলটিতে মà§à¦¯à¦¾à¦¨à§à¦¯à¦¼à¦¾à¦² কà§à¦²à¦¿à¦•-মাধà§à¦¯à¦®à§‡ পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨:' + rejecting_media_title: ফিলà§à¦Ÿà¦¾à¦° করা মিডিয়া silenced: 'à¦à¦‡ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿à¦° পোসà§à¦Ÿà¦—à§à¦²à¦¿ জনসাধারণের টাইমলাইন à¦à¦¬à¦‚ কথোপকথনে লà§à¦•ানো থাকবে à¦à¦¬à¦‚ আপনি যদি তাদের অনà§à¦¸à¦°à¦£ না করেন তবে তাদের বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর ইনà§à¦Ÿà¦¾à¦°à¦…à§à¦¯à¦¾à¦•শন থেকে কোনও বিজà§à¦žà¦ªà§à¦¤à¦¿ উতà§à¦ªà¦¨à§à¦¨ হবে না:' + silenced_title: নীরব করা সারà§à¦à¦¾à¦° suspended: 'à¦à¦‡ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿ থেকে কোনও ডেটা পà§à¦°à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦œà¦¾à¦¤à¦•রণ, সংরকà§à¦·à¦£ বা আদান-পà§à¦°à¦¦à¦¾à¦¨ করা হবে না, à¦à¦‡ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের সাথে কোনও মিথসà§à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾ বা যোগাযোগকে অসমà§à¦à¦¬ করে তà§à¦²à§‡à¦›à§‡:' + suspended_title: সà§à¦¥à¦—িত করা সারà§à¦à¦¾à¦° unavailable_content_html: মà§à¦¯à¦¾à¦¸à§à¦Ÿà§‹à¦¡à¦¨ সাধারণত আপনাকে ফেদিà¦à¦¾à¦°à§à¦¸ ঠঅনà§à¦¯ কোনও সারà§à¦à¦¾à¦°à§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের থেকে সামগà§à¦°à§€ দেখতে à¦à¦¬à¦‚ তাদের সাথে আলাপচারিতা করার অনà§à¦®à¦¤à¦¿ দেয়। à¦à¦‡ বà§à¦¯à¦¤à¦¿à¦•à§à¦°à¦® যে à¦à¦‡ বিশেষ সারà§à¦à¦¾à¦°à§‡ তৈরি করা হয়েছে। user_count_after: one: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী @@ -76,6 +81,7 @@ bn: roles: admin: পরিচালক bot: রোবট + group: গোষà§à¦ à§€ moderator: পরিচালক unavailable: পà§à¦°à§‹à¦«à¦¾à¦‡à¦² অনà§à¦ªà¦²à¦¬à§à¦§ unfollow: অনà§à¦¸à¦°à¦£ বাদ @@ -89,6 +95,7 @@ bn: delete: মà§à¦›à§‡ ফেলা destroyed_msg: পà§à¦°à¦¶à¦¾à¦¸à¦¨à¦¬à¦¸à§à¦¤à§à¦¤ লেখাটি সঠিকà¦à¦¾à¦¬à§‡ মà§à¦›à§‡ ফেলা হয়েছে! accounts: + add_email_domain_block: নিষিদà§à¦§ করা ই-মেইল ডোমেইন approve: অনà§à¦®à§‹à¦¦à¦¨ দিন approve_all: পà§à¦°à¦¤à§à¦¯à§‡à¦• কে অনà§à¦®à¦¤à¦¿ দিন are_you_sure: আপনি কি নিশà§à¦šà¦¿à¦¤ ? @@ -169,6 +176,7 @@ bn: staff: করà§à¦®à§€ user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী search: অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ + search_same_email_domain: à¦à¦•ই ইমেল ডোমেন সহ অনà§à¦¯à¦¾à¦¨à§à¦¯ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীরা search_same_ip: à¦à¦•ই IP সহ অনà§à¦¯à¦¾à¦¨à§à¦¯ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীরা shared_inbox_url: à¦à¦¾à¦— করা ইনবকà§à¦¸ URL show: @@ -190,8 +198,149 @@ bn: web: ওয়েব whitelisted: সাদাতালিকাযà§à¦•à§à¦¤ action_logs: + action_types: + assigned_to_self_report: রিপোরà§à¦Ÿ বরাদà§à¦¦ করà§à¦¨ + change_email_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী জনà§à¦¯ ইমেইল পরিবরà§à¦¤à¦¨ করà§à¦¨ + confirm_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী নিশà§à¦šà¦¿à¦¤ করà§à¦¨ + create_account_warning: সতরà§à¦•তা তৈরি করà§à¦¨ + create_announcement: ঘোষণা তৈরি করà§à¦¨ + create_custom_emoji: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি তৈরি করà§à¦¨ + create_domain_allow: ডোমেন অনà§à¦®à§‹à¦¦à¦¨ তৈরি করà§à¦¨ + create_domain_block: ডোমেন বà§à¦²à¦• তৈরি করà§à¦¨ + create_email_domain_block: ইমেইল ডোমেন বà§à¦²à¦• তৈরি করà§à¦¨ + demote_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী কে হীনপদসà§à¦¥ করà§à¦¨ + destroy_announcement: ঘোষণা মà§à¦›à§à¦¨ + destroy_custom_emoji: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি মà§à¦›à§à¦¨ + destroy_domain_allow: ডোমেন অনà§à¦®à§‹à¦¦à¦¨ মà§à¦›à§à¦¨ + destroy_domain_block: ডোমেন বà§à¦²à¦• মà§à¦›à§à¦¨ + destroy_email_domain_block: ইমেইল ডোমেন বà§à¦²à¦• মà§à¦›à§à¦¨ + destroy_status: সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ মà§à¦›à§à¦¨ + disable_2fa_user: 2FA নিষà§à¦•à§à¦°à¦¿à§Ÿ করà§à¦¨ + disable_custom_emoji: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি নিষà§à¦•à§à¦°à¦¿à§Ÿ করà§à¦¨ + disable_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী কে নিষà§à¦•à§à¦°à¦¿à§Ÿ করà§à¦¨ + enable_custom_emoji: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি সকà§à¦°à¦¿à§Ÿ করà§à¦¨ + enable_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী কে সকà§à¦°à¦¿à§Ÿ করà§à¦¨ + memorialize_account: মেমোরিয়ালাইজ অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ + promote_user: বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী কে পদোনà§à¦¨à¦¤à¦¿ করà§à¦¨ + remove_avatar_user: অবতার অপসারণ করà§à¦¨ + reopen_report: পà§à¦°à¦¤à¦¿à¦¬à§‡à¦¦à¦¨à¦Ÿà¦¿ পà§à¦¨à¦°à¦¾à¦¯à¦¼ খà§à¦²à§à¦¨ + reset_password_user: পাসওয়ারà§à¦¡ পà§à¦¨à¦ƒà¦¸à§à¦¥à¦¾à¦ªà¦¨ করà§à¦¨ + resolve_report: পà§à¦°à¦¤à¦¿à¦¬à§‡à¦¦à¦¨à¦Ÿà¦¿ সমাধান করà§à¦¨ + silence_account: অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ নীরব করà§à¦¨ + suspend_account: অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ সà§à¦¥à¦—িত করà§à¦¨ + unassigned_report: রিপোরà§à¦Ÿ বরাদà§à¦¦ মà§à¦•à§à¦¤ করà§à¦¨ + unsilence_account: অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ নীরব মà§à¦•à§à¦¤ করà§à¦¨ + unsuspend_account: অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ সà§à¦¥à¦—িতমà§à¦•à§à¦¤ করà§à¦¨ + update_announcement: ঘোষণা আপডেট করà§à¦¨ + update_custom_emoji: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি আপডেট করà§à¦¨ + update_status: সà§à¦¥à¦¿à¦¤à¦¿ আপডেট করà§à¦¨ actions: assigned_to_self_report: "%{name} তাদের জনà§à¦¯ %{target} রিপোরà§à¦Ÿ অরà§à¦ªà¦£ করেছিলেন" + change_email_user: "%{name} %{target} বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর ইমেল ঠিকানা পরিবরà§à¦¤à¦¨ করেছেন" + confirm_user: "%{name} %{target} বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর ইমেল ঠিকানা নিশà§à¦šà¦¿à¦¤ করেছেন" + create_account_warning: "%{name} %{target} à¦à¦•টি সতরà§à¦•তা পà§à¦°à§‡à¦°à¦£ করেছেন" + create_announcement: "%{name} à¦à¦•টি নতà§à¦¨ ঘোষণা তৈরি করেছেন %{target}" + create_custom_emoji: "%{name} নতà§à¦¨ ইমোজি আপলোড করেছেন %{target}" + create_domain_allow: "%{name} ডোমেন %{target} à¦à¦° সঙà§à¦—ে ফেডারেশন অনà§à¦®à§‹à¦¦à¦¿à¦¤ করেছেন" + create_domain_block: "%{name} ডোমেন %{target} কে অবরà§à¦¦à§à¦§ করেছেন" + create_email_domain_block: "%{name} ই-মেইল ডোমেন %{target} কে অবরà§à¦¦à§à¦§ করেছেন" + demote_user: "%{name} বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী %{target} কে হীনপদসà§à¦¥ করেছেন" + custom_emojis: + destroyed_msg: ইমোজো সফলà¦à¦¾à¦¬à§‡ ধà§à¦¬à¦‚স হয়েছে! + disable: অকà§à¦·à¦® + disabled: অকà§à¦·à¦®à¦¿à¦¤ + disabled_msg: সফলà¦à¦¾à¦¬à§‡ সেই ইমোজি অকà§à¦·à¦® করা হয়েছে + emoji: ইমোজি + enable: সকà§à¦°à¦¿à§Ÿ + enabled: সকà§à¦°à¦¿à¦¯à¦¼ + enabled_msg: সফলà¦à¦¾à¦¬à§‡ সেই ইমোজি সকà§à¦·à¦® করা হয়েছে + image_hint: ৫০কেবি অবধি পিà¦à¦¨à¦œà¦¿ + list: তালিকা + listed: তালিকাà¦à§à¦•à§à¦¤ + new: + title: নতà§à¦¨ সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজি যোগ করà§à¦¨ + not_permitted: আপনার à¦à¦‡ কà§à¦°à¦¿à¦¯à¦¼à¦¾ সমà§à¦ªà¦¾à¦¦à¦¨ করার অনà§à¦®à¦¤à¦¿ নেই + overwrite: পà§à¦¨à¦°à§à¦²à¦¿à¦–ন + shortcode: শরà§à¦Ÿà¦•োড + shortcode_hint: কমপকà§à¦·à§‡ ২ টি অকà§à¦·à¦°, কেবলমাতà§à¦° বরà§à¦£à¦¾à¦¨à§à¦•à§à¦°à¦®à¦¿à¦• অকà§à¦·à¦° à¦à¦¬à¦‚ আনà§à¦¡à¦¾à¦°à¦¸à§à¦•োর + title: সà§à¦¬à¦¨à¦¿à¦°à§à¦§à¦¾à¦°à¦¿à¦¤ ইমোজিগà§à¦²à¦¿ + uncategorized: শà§à¦°à§‡à¦£à§€à¦¬à¦¿à¦¹à§€à¦¨ + unlist: তালিকামà§à¦•à§à¦¤ + unlisted: তালিকামà§à¦•à§à¦¤ + update_failed_msg: সেই ইমোজি আপডেট করতে পারেনি + updated_msg: ইমোজি সফলà¦à¦¾à¦¬à§‡ আপডেট হয়েছে! + upload: আপলোড + dashboard: + authorized_fetch_mode: সà§à¦°à¦•à§à¦·à¦¿à¦¤ মোড + backlog: বà§à¦¯à¦¾à¦•লগ জবগà§à¦²à¦¿ + config: কনফিগারেশন + feature_deletions: মোছা অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦—à§à¦²à¦¿ + feature_invites: আমনà§à¦¤à§à¦°à¦£ লিঙà§à¦•গà§à¦²à¦¿ + feature_profile_directory: পà§à¦°à§‹à¦«à¦¾à¦‡à¦² ডিরেকà§à¦Ÿà¦°à¦¿ + feature_registrations: নিবনà§à¦§à¦¨à¦—à§à¦²à¦¿ + feature_relay: ফেডারেশন রিলে + feature_spam_check: বিরোধী সà§à¦ªà§à¦¯à¦¾à¦® + feature_timeline_preview: পূরà§à¦¬à¦¦à¦°à§à¦¶à¦¨ সময়রেখা + features: বৈশিষà§à¦Ÿà§à¦¯à¦—à§à¦²à¦¿ + hidden_service: লà§à¦•ানো সেবা সহ ফেডারেশন + open_reports: খোলার রিপোরà§à¦Ÿà¦—à§à¦²à¦¿ + pending_tags: যে হà§à¦¯à¦¾à¦¶à¦Ÿà§à¦¯à¦¾à¦—গà§à¦²à¦¿ পà§à¦¨à¦ƒà¦®à§‚লà§à¦¯à¦¾à¦¯à¦¼à¦¨à¦¾à¦° জনà§à¦¯ অপেকà§à¦·à¦¾ করছে + pending_users: যে বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী পà§à¦¨à¦ƒà¦®à§‚লà§à¦¯à¦¾à¦¯à¦¼à¦¨à¦¾à¦° জনà§à¦¯ অপেকà§à¦·à¦¾ করছে + recent_users: সামà§à¦ªà§à¦°à¦¤à¦¿à¦• বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীরা + search: সমà§à¦ªà§‚রà§à¦£ পাঠà§à¦¯ অনà§à¦¸à¦¨à§à¦§à¦¾à¦¨ + single_user_mode: à¦à¦•ক বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী মোড + software: সফটওয়à§à¦¯à¦¾à¦° + space: সà§à¦¥à¦¾à¦¨ বà§à¦¯à¦¬à¦¹à¦¾à¦° + title: ডà§à¦¯à¦¾à¦¶à¦¬à§‹à¦°à§à¦¡ + total_users: মোট বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারী + trends: পà§à¦°à¦¬à¦£à¦¤à¦¾à¦—à§à¦²à¦¿ + week_interactions: à¦à¦‡ সপà§à¦¤à¦¾à¦¹à§‡ মিথষà§à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾à¦—à§à¦²à¦¿ + week_users_active: à¦à¦‡ সপà§à¦¤à¦¾à¦¹à§‡ সকà§à¦°à¦¿à¦¯à¦¼ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à¦•ারিরা + week_users_new: à¦à¦‡ সপà§à¦¤à¦¾à¦¹à§‡ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à¦•ারিরা + whitelist_mode: সীমিত ফেডারেশন মোড + instances: + moderation: + limited: সীমিত + title: পà§à¦°à¦¶à¦¾à¦¸à¦¨à¦¾ + private_comment: বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত মনà§à¦¤à¦¬à§à¦¯ + public_comment: জনমত + title: ফেডারেশন + total_blocked_by_us: আমাদের দà§à¦¬à¦¾à¦°à¦¾ অবরà§à¦¦à§à¦§ + total_followed_by_them: তাদের দà§à¦¬à¦¾à¦°à¦¾ অনà§à¦¸à¦°à¦£ + total_followed_by_us: আমাদের দà§à¦¬à¦¾à¦°à¦¾ অনà§à¦¸à¦°à¦£ + total_reported: তাদের সমà§à¦ªà¦°à§à¦•ে রিপোরà§à¦Ÿ + total_storage: মিডিয়া সংযà§à¦•à§à¦¤à¦¿à¦—à§à¦²à¦¿ + invites: + deactivate_all: সব নিষà§à¦•à§à¦°à¦¿à¦¯à¦¼ করà§à¦¨ + filter: + all: সব + available: সহজলà¦à§à¦¯ + expired: মেয়াদোতà§à¦¤à§€à¦°à§à¦£ + title: ফিলà§à¦Ÿà¦¾à¦° + title: আমনà§à¦¤à§à¦°à¦£à¦—à§à¦²à¦¿ + pending_accounts: + title: মà§à¦²à¦¤à§à¦¬à¦¿ থাকা অà§à¦¯à¦¾à¦•াউনà§à¦Ÿà¦—à§à¦²à¦¿ (%{count}) + relationships: + title: "%{acct} à¦à¦° সমà§à¦ªà¦°à§à¦•গà§à¦²à¦¿" + relays: + add_new: নতà§à¦¨ রিলে যোগ করà§à¦¨ + delete: মà§à¦›à§à¦¨ + description_html: à¦à¦•টি <strong>ফেডারেশন রিলে</strong> à¦à¦•টি মধà§à¦¯à¦¸à§à¦¥à¦¤à¦¾à¦•ারী সারà§à¦à¦¾à¦° যা সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করে à¦à¦Ÿà¦¿à¦¤à§‡ পà§à¦°à¦•াশ করে à¦à¦®à¦¨ সারà§à¦à¦¾à¦°à§‡à¦° মধà§à¦¯à§‡ পà§à¦°à¦šà§à¦° পরিমাণে সরà§à¦¬à¦œà¦¨à§€à¦¨ টটস বিনিময় করে। <strong>à¦à¦Ÿà¦¿ কà§à¦·à§à¦¦à§à¦° ও মাà¦à¦¾à¦°à¦¿ সারà§à¦à¦¾à¦°à¦—à§à¦²à¦¿à¦•ে ফেডাইà¦à¦¾à¦°à§à¦¸ থেকে সামগà§à¦°à§€ আবিষà§à¦•ার করতে সহায়তা করতে পারে</strong>, অনà§à¦¯à¦¥à¦¾à¦¯à¦¼ সà§à¦¥à¦¾à¦¨à§€à¦¯à¦¼ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের মà§à¦¯à¦¾à¦¨à§à¦¯à¦¼à¦¾à¦²à¦¿ অনà§à¦¯ লোককে দূরবরà§à¦¤à§€ সারà§à¦à¦¾à¦°à§‡ অনà§à¦¸à¦°à¦£ করতে হবে। + disable: অকà§à¦·à¦® + disabled: অকà§à¦·à¦®à¦¿à¦¤ + enable: সকà§à¦°à¦¿à§Ÿ + enable_hint: à¦à¦•বার সকà§à¦·à¦® হয়ে গেলে, আপনার সারà§à¦à¦¾à¦° à¦à¦‡ রিলে থেকে সমসà§à¦¤ পাবলিক টà§à¦Ÿà¦—à§à¦²à¦¿à¦¤à§‡ সাবসà§à¦•à§à¦°à¦¾à¦‡à¦¬ করবে à¦à¦¬à¦‚ à¦à¦¤à§‡ à¦à¦‡ সারà§à¦à¦¾à¦°à§‡à¦° সরà§à¦¬à¦œà¦¨à§€à¦¨ টটগà§à¦²à¦¿ পà§à¦°à§‡à¦°à¦£ শà§à¦°à§ করবে। + enabled: সকà§à¦°à¦¿à¦¯à¦¼à¦•ৃত + inbox_url: রিলে ইউআরà¦à¦² + pending: রিলের অনà§à¦®à§‹à¦¦à¦¨à§‡à¦° অপেকà§à¦·à¦¾à¦¯à¦¼ + save_and_enable: সংরকà§à¦·à¦£ করà§à¦¨ à¦à¦¬à¦‚ সকà§à¦·à¦® করà§à¦¨ + setup: রিলে সংযোগ সেটআপ করà§à¦¨ + signatures_not_enabled: সà§à¦°à¦•à§à¦·à¦¿à¦¤ মোড বা সীমিত ফেডারেশন মোড সকà§à¦·à¦® থাকা অবসà§à¦¥à¦¾à¦¯à¦¼ রিলেগà§à¦²à¦¿ সঠিকà¦à¦¾à¦¬à§‡ কাজ করবে না + status: অবসà§à¦¥à¦¾ + title: রিলেগà§à¦²à¦¿ + report_notes: + created_msg: রিপোরà§à¦Ÿ নোট সফলà¦à¦¾à¦¬à§‡ তৈরি করা হয়েছে! + destroyed_msg: রিপোরà§à¦Ÿ নোট সফলà¦à¦¾à¦¬à§‡ মোছা হয়েছে! errors: '400': The request you submitted was invalid or malformed. '403': You don't have permission to view this page. @@ -202,13 +351,5 @@ bn: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day verification: verification: সতà§à¦¯à¦¤à¦¾ নিরà§à¦§à¦¾à¦°à¦£ diff --git a/config/locales/br.yml b/config/locales/br.yml index 5da24d25c3e9abe275d5de6ae89dca3652492a06..451bbade8284395e7b661bab05aafc29d10c5f38 100644 --- a/config/locales/br.yml +++ b/config/locales/br.yml @@ -11,11 +11,39 @@ br: learn_more: Gouzout hiroc'h privacy_policy: Reolennoù prevezded source_code: Boneg tarzh + status_count_after: + few: toud + many: toud + one: toud + other: toud + two: toud terms: Divizoù gwerzhañ hollek unavailable_content_description: domain: Dafariad + user_count_after: + few: implijer·ez + many: implijer·ez + one: implijer·ez + other: implijer·ez + two: implijer·ez + what_is_mastodon: Petra eo Mastodon? accounts: + follow: Heuliañ + followers: + few: Heulier·ez + many: Heulier·ez + one: Heulier·ez + other: Heulier·ez + two: Heulier·ez + following: O heuliañ media: Media + never_active: Birviken + posts: + few: Toud + many: Toud + one: Toud + other: Toud + two: Toud posts_tab_heading: Toudoù posts_with_replies: Toudoù ha respontoù roles: @@ -29,11 +57,15 @@ br: account_moderation_notes: delete: Dilemel accounts: + by_domain: Domani change_email: current_email: Postel bremanel label: Kemm ar postel new_email: Postel nevez submit: Kemm ar postel + deleted: Dilamet + domain: Domani + email: Postel enable: Gweredekaat enabled: Gweredekaet followers: Heulier·ezed·ien @@ -58,7 +90,14 @@ br: admin: Merour moderator: Habaskaer·ez user: Implijer·ez + search: Klask + suspended: Astalet + title: Kontoù + username: Anv + web: Web action_logs: + action_types: + destroy_status: Dilemel ar statud deleted_status: "(statud dilemet)" announcements: new: @@ -66,15 +105,19 @@ br: title: Kemenn nevez title: Kemennoù custom_emojis: + by_domain: Domani + copy: Eilañ delete: Dilemel disable: Diweredekaat disabled: Diweredekaet emoji: Fromlun enable: Gweredekaat enabled: Gweredekaet + list: Listenn dashboard: config: Kefluniadur software: Meziant + title: Taolenn labour trends: Luskadoù domain_blocks: domain: Domani @@ -100,11 +143,50 @@ br: by_domain: Domani moderation: all: Pep tra + invites: + filter: + available: Hegerzh + relays: + delete: Dilemel + disable: Diweredekaat + disabled: Diweredekaet + enable: Gweredekaat + enabled: Gweredekaet + save_and_enable: Enrollañ ha gweredekaat + status: Toud + reports: + account: + notes: + few: "%{count} a notennoù" + many: "%{count} a notennoù" + one: "%{count} a notennoù" + other: "%{count} a notennoù" + two: "%{count} a notennoù" + are_you_sure: Ha sur oc'h? + notes: + delete: Dilemel + status: Statud + updated_at: Nevesaet settings: domain_blocks: all: D'an holl dud site_title: Anv ar servijer title: Arventennoù al lec'hienn + statuses: + batch: + delete: Dilemel + deleted: Dilamet + media: + title: Media + no_media: Media ebet + tags: + name: Ger-klik + title: Gerioù-klik + warning_presets: + add_new: Ouzhpenniñ unan nevez + delete: Dilemel + application_mailer: + salutation: "%{name}," auth: change_password: Ger-tremen delete_account: Dilemel ar gont @@ -116,18 +198,27 @@ br: security: Diogelroez setup: title: Kefluniañ + status: + account_status: Statud ar gont authorize_follow: + follow: Heuliañ title: Heuliañ %{acct} challenge: confirm: Kenderc' hel invalid_password: Ger-tremen diwiriek + date: + formats: + default: "%d %b %Y" + with_month_name: "%d a viz %B %Y" datetime: distance_in_words: about_x_hours: "%{count}e" about_x_months: "%{count}miz" about_x_years: "%{count}b" almost_x_years: "%{count}b" + half_a_minute: Diouzhtu less_than_x_minutes: "%{count}m" + less_than_x_seconds: Diouzhtu over_x_years: "%{count}b" x_days: "%{count}d" x_minutes: "%{count}m" @@ -147,6 +238,12 @@ br: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. + exports: + archive_takeout: + date: Deiziad + size: Ment + csv: CSV + lists: Listennoù featured_tags: add_new: Ouzhpenniñ unan nevez filters: @@ -155,6 +252,7 @@ br: notifications: Kemennoù index: delete: Dilemel + title: Siloù footer: developers: Diorroerien more: Muioc'h… @@ -163,11 +261,13 @@ br: copy: Eilañ delete: Dilemel order_by: Urzhiañ dre + identity_proofs: + identity: Identelezh invites: expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour + '1800': 30 munutenn + '21600': 6 eur + '3600': 1 eur '43200': 12 eur '604800': 1 sizhun '86400': 1 deiz @@ -178,8 +278,18 @@ br: title: Heulier nevez mention: action: Respont + number: + human: + decimal_units: + format: "%n%u" + otp_authentication: + enable: Gweredekaat + setup: Kefluniañ + pagination: + truncate: "…" relationships: followers: Heulier·ezed·ien + following: O heuliañ sessions: browser: Merdeer browsers: @@ -189,6 +299,7 @@ br: edge: Microsoft Edge electron: Electron firefox: Firefox + generic: Merdeer dianav ie: Internet Explorer micro_messenger: MicroMessenger nokia: Nokia S40 Ovi Browser @@ -199,6 +310,7 @@ br: safari: Safari uc_browser: UCBrowser weibo: Weibo + description: "%{browser} war %{platform}" ip: IP platforms: adobe_air: Adobe Air @@ -209,8 +321,33 @@ br: ios: iOS linux: Linux mac: macOS + other: savenn dianav windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone + settings: + account: Kont + account_settings: Arventennoù ar gont + development: Diorren + edit_profile: Aozañ ar profil + import: Enporzhiañ + import_and_export: Enporzhiañ hag ezporzhiañ + preferences: Gwellvezioù + profile: Profil statuses: + attached: + image: + few: "%{count} skeudenn" + many: "%{count} skeudenn" + one: "%{count} skeudenn" + other: "%{count} skeudenn" + two: "%{count} skeudenn" + video: + few: "%{count} video" + many: "%{count} video" + one: "%{count} video" + other: "%{count} video" + two: "%{count} video" show_more: Diskouez muioc'h title: '%{name}: "%{quote}"' visibilities: @@ -225,12 +362,15 @@ br: default: "%He%M, %d %b %Y" month: "%b %Y" two_factor_authentication: + add: Ouzhpennañ disable: Diweredekaat - enable: Gweredekaat - setup: Kefluniañ + edit: Aozañ user_mailer: warning: title: none: Diwall welcome: edit_profile_action: Kefluniañ ar profil + subject: Donemat e Mastodoñ + webauthn_credentials: + delete: Dilemel diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 10bb1269b7f0bcc4de678d0f0b110a26295553d9..ee3c554b469de3e2e26bd464232ac35db27b5cf7 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -60,6 +60,7 @@ ca: one: Seguidor other: Seguidors following: Seguint + instance_actor_flash: Aquest compte és un actor virtual usat per a representar el mateix servidor i no cap usuari individual. Es fa servir per a federar i no s'hauria d'esborrar. joined: Unit des de %{date} last_active: darrer actiu link_verified_on: La propietat d'aquest enllaç s'ha verificat el %{date} @@ -98,6 +99,7 @@ ca: add_email_domain_block: Afegir el domini de correu a la llista negra approve: Aprova approve_all: Aprova'ls tots + approved_msg: L’aplicació del registre de %{username} s’ha aprovat amb èxit are_you_sure: N'està s segur? avatar: Avatar by_domain: Domini @@ -111,8 +113,10 @@ ca: confirm: Confirma confirmed: Confirmat confirming: Confirmant + delete: Esborra les dades deleted: Esborrats demote: Degrada + destroyed_msg: Les dades de %{username} son a la cua per a ser esborrades en breu disable: Inhabilita disable_two_factor_authentication: Desactiva 2FA disabled: Inhabilitat @@ -123,10 +127,12 @@ ca: email_status: Estat de l'adreça electrònica enable: Habilita enabled: Habilitat + enabled_msg: El compte de %{username} s’ha descongelat amb èxit followers: Seguidors follows: Segueix header: Capçalera inbox_url: URL de la safata d'entrada + invite_request_text: Motiu del registre invited_by: Convidat per ip: IP joined: Unit @@ -138,6 +144,8 @@ ca: login_status: Estat d'accés media_attachments: Adjunts multimèdia memorialize: Converteix-lo en memorial + memorialized: Memorialitzat + memorialized_msg: S’ha canviat amb èxit a memorialitzat el compte de %{username} moderation: active: Actiu all: Tot @@ -158,10 +166,14 @@ ca: public: Públic push_subscription_expires: La subscripció PuSH expira redownload: Actualitza el perfil + redownloaded_msg: El perfil de %{username} s’ha refrescat des de l’origen amb èxit reject: Rebutja reject_all: Rebutja'ls tots + rejected_msg: L’aplicació de registre de %{username} s’ha rebutjat amb èxit remove_avatar: Eliminar avatar remove_header: Treu la capçalera + removed_avatar_msg: S’ha suprimit amb èxit l’imatge d’acabar de %{username} + removed_header_msg: S’ha suprimit amb èxit l’imatge de capçalera de %{username} resend_confirmation: already_confirmed: Aquest usuari ja està confirmat send: Reenviar el correu electrònic de confirmació @@ -178,6 +190,8 @@ ca: search: Cerca search_same_email_domain: Altres usuaris amb el mateix domini de correu search_same_ip: Altres usuaris amb la mateixa IP + sensitive: Sensible + sensitized: marcar com a sensible shared_inbox_url: URL de la safata d'entrada compartida show: created_reports: Informes creats @@ -187,13 +201,19 @@ ca: statuses: Tuts subscribe: Subscriu suspended: Suspès + suspension_irreversible: Les dades d’aquest compte s’han suprimit irreversiblament. Pots desfer la suspensió del compte per a fer-lo usable però això no recuperarà les dades si és que en tenia. + suspension_reversible_hint_html: El compte ha estat suspès i les dades seran totalment suprimides el %{date}. Fins llavors, el compte pot ser restaurat sense problemes. Si vols suprimir immediatament totes les dades del compte, ho pots fer a continuació. time_in_queue: Esperant en la cua %{time} title: Comptes unconfirmed_email: Correu electrònic sense confirmar + undo_sensitized: Desmarcar com a sensible undo_silenced: Deixa de silenciar undo_suspension: Desfés la suspensió + unsilenced_msg: El compte de %{username} ha estat il·limitat amb èxit unsubscribe: Cancel·la la subscripció + unsuspended_msg: S’ha desfet amb èxit la suspensió del compte de %{username} username: Nom d'usuari + view_domain: Veure el resumen del domini warn: AvÃs web: Web whitelisted: Llista blanca @@ -208,12 +228,14 @@ ca: create_domain_allow: Crea un domini permès create_domain_block: Crea un bloqueig de domini create_email_domain_block: Crea un bloqueig de domini d'adreça de correu + create_ip_block: Crear regla IP demote_user: Degrada l'usuari destroy_announcement: Esborra l'anunci destroy_custom_emoji: Esborra l'emoji personalitzat destroy_domain_allow: Esborra el domini permès destroy_domain_block: Esborra el bloqueig de domini destroy_email_domain_block: Esborra el bloqueig de domini de l'adreça de correu + destroy_ip_block: Eliminar regla IP destroy_status: Esborra el tut disable_2fa_user: Desactiva 2FA disable_custom_emoji: Desactiva l'emoji personalitzat @@ -226,13 +248,16 @@ ca: reopen_report: Reobre l'informe reset_password_user: Restableix la contrasenya resolve_report: Resolt l'informe + sensitive_account: Marcar els mèdia en el teu compte com a sensibles silence_account: Silencia el compte suspend_account: Suspèn el compte unassigned_report: Des-assigna l'informe + unsensitive_account: Desmarcar els mèdia en el teu compte com a sensibles unsilence_account: Desfés el silenci del compte unsuspend_account: Desfés la suspensió del compte update_announcement: Actualitza l'anunci update_custom_emoji: Actualitza l'emoji personalitzat + update_domain_block: Actualitza el Bloqueig de Domini update_status: Actualitza l'estat actions: assigned_to_self_report: "%{name} han assignat l'informe %{target} a ells mateixos" @@ -244,12 +269,14 @@ ca: create_domain_allow: "%{name} ha afegit a la llista blanca el domini %{target}" create_domain_block: "%{name} ha blocat el domini %{target}" create_email_domain_block: "%{name} ha afegit a la llista negra el domini del correu electrònic %{target}" + create_ip_block: "%{name} ha creat una regla IP per a %{target}" demote_user: "%{name} ha degradat l'usuari %{target}" destroy_announcement: "%{name} ha eliminat l'anunci %{target}" destroy_custom_emoji: "%{name} ha destruït l'emoji %{target}" destroy_domain_allow: "%{name} ha eliminat el domini %{target} de la llista blanca" destroy_domain_block: "%{name} ha desblocat el domini %{target}" destroy_email_domain_block: "%{name} ha afegit a la llista negra el domini de correu electrònic %{target}" + destroy_ip_block: "%{name} ha esborrat la regla IP per a %{target}" destroy_status: "%{name} eliminat l'estat per %{target}" disable_2fa_user: "%{name} ha desactivat el requisit de dos factors per a l'usuari %{target}" disable_custom_emoji: "%{name} ha desactivat l'emoji %{target}" @@ -262,13 +289,16 @@ ca: reopen_report: "%{name} ha reobert l'informe %{target}" reset_password_user: "%{name} ha restablert la contrasenya de l'usuari %{target}" resolve_report: "%{name} ha resolt l'informe %{target}" + sensitive_account: "%{name} ha marcat els mèdia de %{target} com a sensibles" silence_account: "%{name} ha silenciat el compte de %{target}" suspend_account: "%{name} ha suspès el compte de %{target}" unassigned_report: "%{name} ha des-assignat l'informe %{target}" + unsensitive_account: "%{name} ha desmarcat els mèdia de %{target} com a sensibles" unsilence_account: "%{name} ha silenciat el compte de %{target}" unsuspend_account: "%{name} ha llevat la suspensió del compte de %{target}" update_announcement: "%{name} ha actualitzat l'anunci %{target}" update_custom_emoji: "%{name} ha actualitzat l'emoji %{target}" + update_domain_block: "%{name} ha actualitzat el bloqueig de domini per %{target}" update_status: "%{name} estat actualitzat per %{target}" deleted_status: "(tut esborrat)" empty: No s’han trobat registres. @@ -372,6 +402,8 @@ ca: silence: Silenci suspend: Suspensió title: Bloqueig de domini nou + obfuscate: Oculta el nom del domini + obfuscate_hint: Oculta parcialment el nom del domini si està activat mostrar la llista de dominis limitats private_comment: Comentari privat private_comment_hint: Comentari sobre aquesta limitació del domini per a ús intern dels moderadors. public_comment: Comentari públic @@ -411,6 +443,7 @@ ca: instances: by_domain: Domini delivery_available: El lliurament està disponible + empty: No s'han trobat dominis. known_accounts: one: "%{count} compte conegut" other: "%{count} comptes coneguts" @@ -434,6 +467,21 @@ ca: expired: Caducat title: Filtre title: Convida + ip_blocks: + add_new: Crear regla + created_msg: S’ha afegit amb èxit la nova regla IP + delete: Suprimeix + expires_in: + '1209600': 2 setmanes + '15778476': 6 mesos + '2629746': 1 mes + '31556952': 1 any + '86400': 1 dia + '94670856': 3 anys + new: + title: Crea nova regla IP + no_ip_block_selected: No s’ha canviat cap regla IP perquè no s’han seleccionat + title: Regles IP pending_accounts: title: Comptes pendents (%{count}) relationships: @@ -473,6 +521,8 @@ ca: comment: none: Cap created_at: Reportat + forwarded: Reenviat + forwarded_to: Reenviat a %{domain} mark_as_resolved: Marca com a resolt mark_as_unresolved: Marcar com a sense resoldre notes: @@ -516,6 +566,7 @@ ca: domain_blocks_rationale: title: Mostra el raonament enable_bootstrap_timeline_accounts: + desc_html: Fer que els nous usuaris segueixin automà ticament als comptes configurats i la seva lÃnia de temps no arrenqui buida title: Activa els seguiments per defecte per els usuaris nous hero: desc_html: Es mostra en pà gina frontal. Recomanat al menys 600x100px. Si no es configura es mostrarà el del servidor @@ -542,6 +593,9 @@ ca: min_invite_role: disabled: Ningú title: Permet les invitacions de + require_invite_text: + desc_html: Quan el registre requereix aprovació manual, fer que sigui obligatori enlloc d'opcions l escriure el text de la solicitud d'invitació "Perquè vols unirte?" + title: Requerir als nous usuaris omplir el text de la solicitud d'invitació registrations_mode: modes: approved: Es requereix l’aprovació per registrar-se @@ -681,8 +735,11 @@ ca: prefix_sign_up: Registra't avui a Mastodon! suffix: Amb un compte serà s capaç de seguir persones, publicar i intercanviar missatges amb usuaris de qualsevol servidor de Mastodon i més! didnt_get_confirmation: No has rebut el correu de confirmació? + dont_have_your_security_key: No tens la teva clau de seguretat? forgot_password: Has oblidat la contrasenya? invalid_reset_password_token: L'enllaç de restabliment de la contrasenya no és và lid o ha caducat. Torna-ho a provar. + link_to_otp: Introdueix el teu codi de doble factor des d’el teu mòbil o un codi de recuperació + link_to_webauth: Usa el teu dispositiu de clau de seguretat login: Inicia sessió logout: Surt migrate_account: Mou a un compte diferent @@ -707,7 +764,9 @@ ca: functional: El teu compte és plenament operatiu. pending: La vostra sol·licitud està pendent de revisió pel nostre personal. Això pot trigar una mica. Rebreu un correu electrònic quan sigui aprovada. redirecting_to: El teu compte és inactiu perquè actualment està redirigint a %{acct}. + too_fast: Formulari enviat massa rà pid, torna a provar-ho. trouble_logging_in: Problemes per iniciar la sessió? + use_security_key: Usa clau de seguretat authorize_follow: already_following: Ja està s seguint aquest compte already_requested: Ja has enviat una sol·licitud de seguiment a aquest usuari @@ -732,6 +791,7 @@ ca: date: formats: default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count} h" @@ -796,6 +856,7 @@ ca: request: Sol·licita el teu arxiu size: Mida blocks: Persones que has blocat + bookmarks: Marcadors csv: CSV domain_blocks: Bloquejos de dominis lists: Llistes @@ -863,6 +924,8 @@ ca: status: Estat de verificació view_proof: Veure la prova imports: + errors: + over_rows_processing_limit: conté més de %{count} files modes: merge: Fusionar merge_long: Mantenir els registres existents i afegir-ne de nous @@ -872,6 +935,7 @@ ca: success: Les dades s'han rebut correctament i es processaran en breu types: blocking: Llista de blocats + bookmarks: Marcadors domain_blocking: Llistat de dominis bloquejats following: Llista de seguits muting: Llista de silenciats @@ -992,6 +1056,14 @@ ca: quadrillion: Q thousand: m trillion: T + otp_authentication: + code_hint: Introdueix el codi generat per l’aplicació d’autenticació per a confirmar + description_html: Si actives <strong>l’autenticació de factor doble</strong> usant l’aplicació d’autenticació, l’inici de sessió et requerirá tenir el teu mòbil, que generarà els tokens per a entrar. + enable: Activa + instructions_html: "<strong>Escaneja aquest codi QR en l'Autenticador de Google o una aplicació TOTP similar en el teu mòbil</strong>. Des d'ara, aquesta aplicació generarà tokens que haurà s d'introduir quan iniciïs sessió." + manual_instructions: 'Si no pots escanejar el codi QR i necessites introduir-lo manualment, aquà està el secret de text pla:' + setup: Configurar + wrong_code: El codi introduït no és và lid! És correcta l'hora del servidor i la del dispositiu? pagination: newer: Més recent next: Endavant @@ -1020,6 +1092,7 @@ ca: relationships: activity: Activitat del compte dormant: Inactiu + follow_selected_followers: Segueix als seguidors seleccionats followers: Seguidors following: Seguint invited: Convidat @@ -1116,6 +1189,7 @@ ca: profile: Perfil relationships: Seguits i seguidors two_factor_authentication: Autenticació de dos factors + webauthn_authentication: Claus de seguretat spam_check: spam_detected: Aquest és un informe automà tic. S'ha detectat spam. statuses: @@ -1154,6 +1228,8 @@ ca: other: "%{count} vots" vote: Vota show_more: Mostra'n més + show_newer: Mostra els més nous + show_older: Mostra els més vells show_thread: Mostra el fil sign_in_to_participate: Inicia la sessió per participar a la conversa title: '%{name}: "%{quote}"' @@ -1262,21 +1338,20 @@ ca: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Introdueix el codi generat per l'aplicació autenticadora per a confirmar - description_html: Si habilites l'<strong>autenticació de dos factors</strong>, et caldrà tenir el teu telèfon, que generarà tokens per a que puguis iniciar sessió. + add: Afegeix disable: Desactiva - enable: Activa + disabled_success: Autenticació de dos factors desactivada amb èxit + edit: Edita enabled: Autenticació de dos factors activada enabled_success: Autenticació de dos factors activada correctament generate_recovery_codes: Genera codis de recuperació - instructions_html: "<strong>Escaneja aquest codi QR desde Google Authenticator o una aplicació similar del teu telèfon</strong>. Desde ara, aquesta aplicació generarà tokens que tens que ingresar quan volguis iniciar sessió." lost_recovery_codes: Els codis de recuperació et permeten recuperar l'accés al teu compte si perds el telèfon. Si has perdut els codis de recuperació els pots tornar a generar aquÃ. S'anul·laran els codis de recuperació anteriors. - manual_instructions: 'Si no pots escanejar el codi QR i necessites introduir-lo manualment, aquà tens el secret en text pla:' + methods: Autenticació de dos factors + otp: Aplicació autenticadora recovery_codes: Codis de recuperació de còpia de seguretat recovery_codes_regenerated: Codis de recuperació regenerats amb èxit recovery_instructions_html: Si mai perds l'accés al teu telèfon pots utilitzar un dels codis de recuperació a continuació per a recuperar l'accés al teu compte. <strong>Cal mantenir els codis de recuperació en lloc segur</strong>. Per exemple, imprimint-los i guardar-los amb altres documents importants. - setup: Establir - wrong_code: El codi introduït no és và lid! És correcta l'hora del servidor i del dispositiu? + webauthn: Claus de seguretat user_mailer: backup_ready: explanation: Has sol·licitat una copia completa del teu compte Mastodon. Ara ja està a punt per a descà rrega! @@ -1285,12 +1360,13 @@ ca: sign_in_token: details: 'Aquà es mostren els detalls del intent:' explanation: 'Hem detectat un intent d’inici de sessió al teu compte des d’una IP desconeguda. Si ets tu, si us plau introdueix el codi de seguretat a sota, en la pà gina de desafiament d’inici de sessió:' - further_actions: 'Si no has estat tu, si us plau canvia la contrasenya i activa l’autentificació de dos factors del teu compte. Pots fer-ho aquÃ:' + further_actions: 'Si no has estat tu, si us plau canvia la contrasenya i activa l’autenticació de dos factors del teu compte. Pots fer-ho aquÃ:' subject: Si us plau confirma l’intent d’inici de sessió title: Intent d’inici de sessió warning: explanation: disable: Mentre el teu compte estigui congelat les dades romandran intactes però no pots dur a terme cap acció fins que no estigui desbloquejat. + sensitive: Els fitxers multimèdia pujats i els enllaçats seran tractas com a sensibles. silence: Mentre el teu compte estigui limitat només les persones que ja et segueixen veuen les teves dades en aquest servidor i pots ser exclòs de diverses llistes públiques. No obstant això, d'altres encara poden seguir-te manualment. suspend: El teu compte s'ha suspès i tots els teus tuts i fitxers multimèdia penjats s'han eliminat de manera irreversible d'aquest servidor i dels servidors on tenies seguidors. get_in_touch: Pots respondre a aquest correu electrònic per a contactar amb el personal de %{instance}. @@ -1299,11 +1375,13 @@ ca: subject: disable: S'ha congelat el teu compte %{acct} none: AvÃs per a %{acct} + sensitive: El teu compte %{acct} de publicació de mèdia ha estat marcat com a sensible silence: El teu compte %{acct} ha estat limitat suspend: S'ha suspès el teu compte %{acct} title: disable: Compte congelat none: AvÃs + sensitive: Els teus mèdia han estat marcats com a sensibles silence: Compte limitat suspend: Compte suspès welcome: @@ -1324,9 +1402,11 @@ ca: tips: Consells title: Benvingut a bord, %{name}! users: + blocked_email_provider: Aquest proveïdor de correu electrònic no és permés follow_limit_reached: No pots seguir més de %{limit} persones generic_access_help_html: Problemes accedint al teu compte? Pots contactar amb %{email} per a demanar assistència invalid_email: L'adreça de correu no és correcta + invalid_email_mx: Sembla que l’adreça de correu electrònic no existeix invalid_otp_token: El codi de dos factors no és correcte invalid_sign_in_token: Codi de seguretat invà lid otp_lost_help_html: Si has perdut l'accés a tots dos pots contactar per %{email} @@ -1336,3 +1416,20 @@ ca: verification: explanation_html: 'Pots <strong>verificar-te com a propietari dels enllaços a les metadades del teu perfil</strong>. Per això, el lloc web enllaçat ha de contenir un enllaç al teu perfil de Mastodon. El vincle <strong>ha de</strong> tenir l''atribut <code>rel="me"</code>. El contingut del text de l''enllaç no importa. Aquà tens un exemple:' verification: Verificació + webauthn_credentials: + add: Afegir nova clau de seguretat + create: + error: Hi ha hagut un problema en afegir la teva clau de seguretat. Tornau-ho a provar. + success: S'ha afegit correctament la teva clau de seguretat. + delete: Esborra + delete_confirmation: Segur que vols suprimir aquesta clau de seguretat? + description_html: Si actives <strong>l'autenticador amb clau de seguretat</strong>, l'inici de sessió et requerirà emprar un de les teves claus de seguretat. + destroy: + error: Hi ha hagut un problema al esborrar la teva clau de seguretat. Tornau-ho a provar. + success: La teva clau de seguretat s'ha esborrat correctament. + invalid_credential: Clau de seguretat invà lida + nickname_hint: Introdueix el sobrenom de la teva clau de seguretat nova + not_enabled: Encara no has activat WebAuthn + not_supported: Aquest navegador no suporta claus de seguretat + otp_required: Per emprar claus de seguretat si us plau activa primer l'autenticació de dos factors. + registered_on: Registrat en %{date} diff --git a/config/locales/co.yml b/config/locales/co.yml index b1d68b2d5993d9f50529fb2c4f1f18903d155649..29ba79688e72df4144899b6d833de5d9101fb526 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -32,18 +32,18 @@ co: status_count_after: one: statutu other: statuti - status_count_before: chì anu pubblicatu + status_count_before: Chì anu pubblicatu tagline: Siguità amichi è scopre ancu di più altri terms: Cundizione di u serviziu unavailable_content: Cuntinutu micca dispunibule unavailable_content_description: domain: Servore - reason: 'Ragione:' - rejecting_media: I fugliali media da stu servore ùn saranu micca arregistrati è e vignette ùn saranu micca affissate, duverete cliccà manualmente per accede à l'altru servore è vedeli. + reason: Ragione + rejecting_media: 'I fugliali media da stu servore ùn saranu micca arregistrati è e vignette ùn saranu micca affissate, duverete cliccà manualmente per accede à l''altru servore è vedeli:' rejecting_media_title: Media filtrati - silenced: I statuti da stu servore ùn saranu mai visti tranne nant'a vostra pagina d'accolta s'e voi siguitate l'autore. + silenced: 'I statuti da stu servore ùn saranu mai visti tranne nant''a vostra pagina d''accolta s''e voi siguitate l''autore:' silenced_title: Servori silenzati - suspended: Ùn puderete micca siguità qualsiasi nant'à stu servore, i dati versu o da quallà ùn saranu mai accessi, scambiati o arregistrati. + suspended: 'Ùn puderete micca siguità qualsiasi nant''à stu servore, i dati versu o da quallà ùn saranu mai accessi, scambiati o arregistrati:' suspended_title: Servori suspesi unavailable_content_html: Mastodon vi parmette in generale di vede u cuntinutu è interagisce cù l'utilizatori di tutti l'altri servori di u fediversu. Quessi sò l'eccezzione fatte nant'à stu servore in particulare. user_count_after: @@ -60,6 +60,7 @@ co: one: Abbunatu·a other: Abbunati following: Abbunamenti + instance_actor_flash: Stu contu virtuale riprisenta u servore stessu, micca un'utilizatore individuale. Hè utilizatu per scopi di federazione è ùn duveria mai esse suspesu. joined: Quì dapoi %{date} last_active: ultima attività link_verified_on: A pruprietà d'issu ligame hè stata verificata u %{date} @@ -98,6 +99,7 @@ co: add_email_domain_block: Mette u duminiu e-mail in lista nera approve: Appruvà approve_all: Appruvà tuttu + approved_msg: A dumanda d'arregistramente di %{username} hè stata appruvata are_you_sure: Site sicuru·a? avatar: Ritrattu di prufile by_domain: Duminiu @@ -111,8 +113,10 @@ co: confirm: Cunfirmà confirmed: Cunfirmata confirming: Cunfirmazione + delete: Sguassà dati deleted: Sguassatu demote: Ritrugradà + destroyed_msg: I dati di %{username} sò avà in fila d'attesa per esse tolti da quì à pocu disable: Disattivà disable_two_factor_authentication: Disattivà l’identificazione à 2 fattori disabled: Disattivatu @@ -121,12 +125,14 @@ co: edit: Mudificà email: E-mail email_status: Statutu di l’e-mail - enable: Attivà + enable: Riattivà enabled: Attivatu + enabled_msg: U contu di %{username} hè statu riattivatu followers: Abbunati follows: Abbunamenti - header: Intistatura + header: Ritrattu di cuprendula inbox_url: URL di l’inbox + invite_request_text: Ragione di l'arregistramentu invited_by: Invitatu da ip: IP joined: Ghjuntu @@ -138,6 +144,8 @@ co: login_status: Statutu di cunnessione media_attachments: Media aghjunti memorialize: Trasfurmà in mimuriale + memorialized: Mimurializatu + memorialized_msg: U contu di %{username} hè statu trasfurmatu in una pagina mimuriale moderation: active: Attivu all: Tutti @@ -158,10 +166,14 @@ co: public: Pubblicu push_subscription_expires: Spirata di l’abbunamentu PuSH redownload: Mette à ghjornu u prufile + redownloaded_msg: U prufile di %{username} hè statu attualizatu da l'urighjine reject: Righjittà reject_all: Righjittà tutti + rejected_msg: A dumanda d'arregistramente di %{username} hè stata righjittata remove_avatar: Toglie l’avatar - remove_header: Toglie l'intistatura + remove_header: Toglie a cuprendula + removed_avatar_msg: U ritrattu di prufile di %{username} hè statu toltu + removed_header_msg: U ritrattu di cuprendula di %{username} hè statu toltu resend_confirmation: already_confirmed: St’utilizatore hè digià cunfirmatu send: Rimandà un’e-mail di cunfirmazione @@ -178,22 +190,30 @@ co: search: Cercà search_same_email_domain: Altri utilizatori cù listessu duminiu d'e-mail search_same_ip: Altri utilizatori cù listessa IP + sensitive: Sensibile + sensitized: indicatu cum’è sensibile shared_inbox_url: URL di l’inbox spartuta show: created_reports: Signalamenti fatti targeted_reports: Signalatu da l'altri silence: Silenzà - silenced: Silenzatu + silenced: Limitatu statuses: Statuti subscribe: Abbunassi suspended: Suspesu + suspension_irreversible: I dati di stu contu sò stati irreversibilamente sguassati. Pudete annullà a suspensione di u contu per u rende utilizabile ma ùn pudete micca ricuperà i dati pricedenti. + suspension_reversible_hint_html: U contu hè statu suspesu, è i so dati saranu sguassati u %{date}. Da quì à là , u contu pò esse ricuperatu senza prublemu. S'e voi vulete toglie tutti i dati di u contu avà , pudete fallu quì sottu. time_in_queue: 'Attesa in fila: %{time}' title: Conti unconfirmed_email: E-mail micca cunfirmatu + undo_sensitized: Annullà sensibile undo_silenced: Ùn silenzà più undo_suspension: Ùn suspende più + unsilenced_msg: A limitazione di u contu di %{username} hè stata annullata unsubscribe: Disabbunassi + unsuspended_msg: A suspensione di u contu di %{username} hè stata annullata username: Cugnome + view_domain: Vede un riassuntu per u duminiu warn: Averte web: Web whitelisted: In a lista bianca @@ -208,12 +228,14 @@ co: create_domain_allow: Creà Auturizazione di Duminiu create_domain_block: Creà Blucchime di Duminiu create_email_domain_block: Creà Blucchime di Duminiu E-mail + create_ip_block: Creà regula IP demote_user: Ritrugadà Utilizatore destroy_announcement: Toglie Annunziu destroy_custom_emoji: Toglie Emoji Persunalizata destroy_domain_allow: Toglie Auturizazione di Duminiu destroy_domain_block: Toglie Blucchime di Duminiu destroy_email_domain_block: Toglie blucchime di duminiu e-mail + destroy_ip_block: Toglie regula IP destroy_status: Toglie u statutu disable_2fa_user: Disattivà l’identificazione à 2 fattori disable_custom_emoji: Disattivà Emoji Persunalizata @@ -226,13 +248,16 @@ co: reopen_report: Riapre Signalamentu reset_password_user: Riinizializà Chjave d'Accessu resolve_report: Chjode Signalamentu + sensitive_account: Marcà i media di u vostru contu cum'è sensibili silence_account: Silenzà Contu suspend_account: Suspende Contu unassigned_report: Disassignà signalamentu + unsensitive_account: Ùn marcà più i media di u vostru contu cum'è sensibili unsilence_account: Ùn Silenzà Più u Contu unsuspend_account: Ùn Suspende Più u Contu update_announcement: Cambià Annunziu update_custom_emoji: Cambià Emoji Persunalizata + update_domain_block: Mette à Ghjornu Blucchime di Duminiu update_status: Cambià Statutu actions: assigned_to_self_report: "%{name} s’hè assignatu u signalamentu %{target}" @@ -244,12 +269,14 @@ co: create_domain_allow: "%{name} hà messu u duminiu %{target} nant’a lista bianca" create_domain_block: "%{name} hà bluccatu u duminiu %{target}" create_email_domain_block: "%{name} hà messu u duminiu e-mail %{target} nant’a lista nera" + create_ip_block: "%{name} hà creatu a regula IP %{target}" demote_user: "%{name} hà ritrugradatu l’utilizatore %{target}" destroy_announcement: "%{name} hà sguassatu u novu annunziu %{target}" destroy_custom_emoji: "%{name} hà sguassatu l'emoji %{target}" destroy_domain_allow: "%{name} hà sguassatu u duminiu %{target} da a lista bianca" destroy_domain_block: "%{name} hà sbluccatu u duminiu %{target}" destroy_email_domain_block: "%{name} hà messu u duminiu e-mail %{target} nant’a lista bianca" + destroy_ip_block: "%{name} hà toltu a regula IP %{target}" destroy_status: "%{name} hà toltu u statutu di %{target}" disable_2fa_user: "%{name} hà disattivatu l’identificazione à dui fattori per %{target}" disable_custom_emoji: "%{name} hà disattivatu l’emoji %{target}" @@ -262,13 +289,16 @@ co: reopen_report: "%{name} hà riapertu u signalamentu %{target}" reset_password_user: "%{name} hà riinizializatu a chjave d’accessu di %{target}" resolve_report: "%{name} hà chjosu u signalamentu %{target}" - silence_account: "%{name} hà silenzatu u contu di %{target}" + sensitive_account: "%{name} hà marcatu i media di %{target} cum'è sensibili" + silence_account: "%{name} hà limitatu u contu di %{target}" suspend_account: "%{name} hà suspesu u contu di %{target}" unassigned_report: "%{name} hà disassignatu u signalamentu %{target}" - unsilence_account: "%{name} hà fattu che u contu di %{target} ùn hè più silenzatu" + unsensitive_account: "%{name} hà sguassatu a marcatura di i media di %{target} cum'è sensibili" + unsilence_account: "%{name} hà fattu che u contu di %{target} ùn hè più limitatu" unsuspend_account: "%{name} hà fattu che u contu di %{target} ùn hè più suspesu" update_announcement: "%{name} hà cambiatu u novu annunziu %{target}" update_custom_emoji: "%{name} hà messu à ghjornu l’emoji %{target}" + update_domain_block: "%{name} hà messu à ghjornu u blucchime di duminiu per %{target}" update_status: "%{name} hà cambiatu u statutu di %{target}" deleted_status: "(statutu sguassatu)" empty: Nunda trovu. @@ -411,6 +441,7 @@ co: instances: by_domain: Duminiu delivery_available: Rimessa dispunibule + empty: Mancun duminiu trovu. known_accounts: one: "%{count} contu cunnisciutu" other: "%{count} conti cunnisciuti" @@ -434,6 +465,21 @@ co: expired: Spirati title: Filtrà title: Invitazione + ip_blocks: + add_new: Creà regula + created_msg: Nova regula IP aghjunta + delete: Toglie + expires_in: + '1209600': 2 settimane + '15778476': 6 mesi + '2629746': 1 mese + '31556952': 1 annu + '86400': 1 ghjornu + '94670856': 3 anni + new: + title: Creà una nova regula IP + no_ip_block_selected: E regule ùn sò micca state mudificate perchè manc'un'era selezziunata + title: Regule IP pending_accounts: title: Conti in attesa (%{count}) relationships: @@ -473,6 +519,8 @@ co: comment: none: Nisunu created_at: Palisatu + forwarded: Trasferitu + forwarded_to: Trasferistu à %{domain} mark_as_resolved: Indicà cum’è chjosu mark_as_unresolved: Indicà cum’è sempre apertu notes: @@ -540,8 +588,10 @@ co: desc_html: Auturizà tuttu u mondu à sguassà u so propiu contu title: Auturizà à sguassà i conti min_invite_role: - disabled: Nisunu + disabled: Nimu title: Auturizà l’invitazione da + require_invite_text: + title: Richiede chì i novi utilizatori empiinu una dumanda d'invitazione registrations_mode: modes: approved: Apprubazione necessaria per arregistrassi @@ -549,7 +599,7 @@ co: open: Tutt'ognunu pò arregistrassi title: Modu d'arregistramenti show_known_fediverse_at_about_page: - desc_html: Quandu ghjè selezziunatu, statuti di tuttu l’istanze cunnisciute saranu affissati indè a vista di e linee. Altrimente soli i statuti lucali saranu mustrati. + desc_html: Quandu ghjè selezziunatu, statuti di tuttu l’istanze cunnisciute saranu affissati indè a vista di e linee. Altrimente soli i statuti lucali saranu mustrati title: Vedde tuttu u fediverse cunnisciutu nant’a vista di e linee show_staff_badge: desc_html: Mustrerà un badge Squadra nant’à un prufile d’utilizatore @@ -681,8 +731,11 @@ co: prefix_sign_up: Arregistratevi nant'à Mastodon oghji! suffix: Cù un contu, puderete siguità l'altri, pustà statuti è scambià missaghji cù l'utilizatori di tutti i servori Mastodon è ancu di più! didnt_get_confirmation: Ùn avete micca ricevutu l’istruzione di cunfirmazione? + dont_have_your_security_key: Ùn avete micca a chjave di sicurità ? forgot_password: Chjave scurdata? invalid_reset_password_token: U ligame di riinizializazione di a chjave d’accessu hè spiratu o ùn hè micca validu. Pudete dumandà un'altru ligame. + link_to_otp: Entrate u codice d’I2F da l'applicazione o un codice di ricuperazione + link_to_webauth: Utilizate a vostra chjave di sicurità login: Cunnettassi logout: Scunnettassi migrate_account: Cambià di contu @@ -707,7 +760,9 @@ co: functional: U vostru contu hè uperaziunale. pending: A vostra dumanda hè in attesa di rivista da a squadra di muderazione. Quessa pò piglià un certu tempu. Avete da riceve un'e-mail s'ella hè appruvata. redirecting_to: U vostru contu hè inattivu perchè riindirizza versu %{acct}. + too_fast: Furmulariu mandatu troppu prestu, ripruvate. trouble_logging_in: Difficultà per cunnettavi? + use_security_key: Utilizà a chjave di sicurità authorize_follow: already_following: Site digià abbunatu·a à stu contu already_requested: Avete digià mandatu una dumanda d'abbunamentu à stu contu @@ -732,6 +787,7 @@ co: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}o" @@ -796,6 +852,7 @@ co: request: Dumandà u vostr’archiviu size: Pesu blocks: Bluccate + bookmarks: Segnalibri csv: CSV domain_blocks: Blucchime di duminiu lists: Liste @@ -827,7 +884,7 @@ co: footer: developers: Sviluppatori more: Di più… - resources: Risorze + resources: Risorse trending_now: Tindenze d'avà generic: all: Tuttu @@ -872,6 +929,7 @@ co: success: I vostri dati sò stati impurtati è saranu trattati da quì à pocu types: blocking: Persone chì bluccate + bookmarks: Segnalibri domain_blocking: Lista di blucchimi di duminiu following: Persone chì seguitate muting: Persone chì piattate @@ -908,7 +966,7 @@ co: not_ready: Ùn si pò micca aghjunghje un fugliale micca ancu trattatu. Ripruvate più tardi! too_many: Ùn si pò micca aghjunghje più di 4 fugliali migrations: - acct: cugnome@duminiu di u novu contu + acct: Spiazzatu nant'à cancel: Annullà ridirezzione cancel_explanation: L'annullazione di a ridirezzione hà da riattivà stu contu, mà ùn si puderà micca ricuperà l'abbunati chì sò digià stati trasferriti à l'altru contu. cancelled_msg: Ridirezzione annullata. @@ -992,6 +1050,14 @@ co: quadrillion: P thousand: K trillion: T + otp_authentication: + code_hint: Entrate u codice generatu da l’applicazione per cunfirmà + description_html: S’ella hè attivata <strong>l’identificazione à dui fattori</strong> cù un'applicazione d'identificazione, duvete avè u vostru telefuninu pè ottene un codice di cunnezzione. + enable: Attivà + instructions_html: "<strong>Scanate stu QR code cù Google Authenticator, Authy o qualcosa cusì nant’à u vostru telefuninu</strong>. St’applicazione hà da creà codici da entrà ogni volta chì vi cunnettate." + manual_instructions: 'S’ellu ùn hè micca pussibule scanà u QR code, pudete entre sta chjave sicreta:' + setup: Attivà + wrong_code: U codice ùn hè micca currettu! Site sicuru·a chì l’ora di l'apparechju è di u servore sò esatte? pagination: newer: Più ricente next: Dopu @@ -1020,6 +1086,7 @@ co: relationships: activity: Attività di u contu dormant: Inattivu + follow_selected_followers: Abbunassi à l'abbunati selezziunati followers: Abbunati following: Abbunamenti invited: Invitatu @@ -1087,7 +1154,7 @@ co: firefox_os: Firefox OS ios: iOS linux: Linux - mac: Mac + mac: macOS other: piattaforma scunnisciuta windows: Windows windows_mobile: Windows Mobile @@ -1116,6 +1183,7 @@ co: profile: Prufile relationships: Abbunamenti è abbunati two_factor_authentication: Identificazione à dui fattori + webauthn_authentication: Chjave di sicurità spam_check: spam_detected: Quessu ghjè un riportu automaticu. Un spam hè statu ditettatu. statuses: @@ -1139,7 +1207,7 @@ co: in_reply_not_found: U statutu à quellu avete pruvatu di risponde ùn sembra micca esiste. language_detection: Truvà a lingua autumaticamente open_in_web: Apre nant’à u web - over_character_limit: Site sopr’à a limita di %{max} caratteri + over_character_limit: site sopr’à a limita di %{max} caratteri pin_errors: limit: Avete digià puntarulatu u numeru massimale di statuti ownership: Pudete puntarulà solu unu di i vostri propii statuti @@ -1154,6 +1222,8 @@ co: other: "%{count} voti" vote: Vutà show_more: Vede di più + show_newer: Vede i più ricenti + show_older: Vede i più anziani show_thread: Vede u filu sign_in_to_participate: Cunnettatevi per participà à a cunversazione title: '%{name}: "%{quote}"' @@ -1262,21 +1332,20 @@ co: default: "%d %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Entrate u codice generatu da l’applicazione per cunfirmà - description_html: S’ella hè attivata <strong>l’identificazione à dui fattori</strong>, duvete avè u vostru telefuninu pè ottene un codice di cunnezzione. + add: Aghjunghje disable: Disattivà - enable: Attivà + disabled_success: L’identificazione à dui fattori hè stata disattivata + edit: Cambià enabled: Identificazione à dui fattori attivata enabled_success: L’identificazione à dui fattori hè stata attivata generate_recovery_codes: Creà codici di ricuperazione - instructions_html: "<strong>Scanate stu QR code cù Google Authenticator, Authy o qualcosa cusì nant’à u vostru telefuninu</strong>. St’applicazione hà da creà codici da entrà ogni volta chì vi cunnettate." lost_recovery_codes: I codici di ricuperazione à usu unicu vi permettenu di sempre avè accessu à u vostru contu s’è voi avete persu u vostru telefuninu. S’elli sò ancu persi, pudete creà codici novi quì. I vechji codici ùn marchjeranu più. - manual_instructions: 'S’ellu ùn hè micca pussibule scanà u QR code, pudete entre sta chjave sicreta:' + methods: Manere d'I2F + otp: Applicazione d'identificazione recovery_codes: Codici di ricuperazione recovery_codes_regenerated: Codici di ricuperazione ricreati recovery_instructions_html: Pudete fà usu di i codici quì sottu per sempre avè accessu à u vostru contu s’ellu hè statu persu u vostru telefuninu. <strong>Guardateli in una piazza sicura</strong>. Per esempiu, stampati è cunservati cù altri ducumenti impurtanti. - setup: Attivà - wrong_code: U codice ùn hè micca currettu! Site sicuru·a chì l’ora di l'apparechju è di u servore sò esatte? + webauthn: Chjave di sicurità user_mailer: backup_ready: explanation: Avete dumandatu un’archiviu cumpletu di u vostru contu Mastodon. Avà hè prontu per scaricà ! @@ -1291,6 +1360,7 @@ co: warning: explanation: disable: Quandu u vostru contu hè ghjacciatu, i vostri dati stannu intatti, mà ùn pudete fà nunda fin'à ch'ellu sia sbluccatu. + sensitive: I vostri media caricati è in ligami saranu trattati cum'è sensibili. silence: Quandu u vostru contu hè limitatu, solu quelli chì sò digià abbunati à u vostru contu viderenu i vostri statuti nant'à quessu servore, è puderete esse esclusu·a di parechje liste pubbliche. Però, altri conti puderenu sempre seguitavi. suspend: U vostru contu hè statu suspesu, è tutti i vo statuti è fugliali media caricati sò stati sguassati di manera irreversibile di stu servore, è di i servori induve aviate abbunati. get_in_touch: Pudete risponde à quest'e-mail per cuntattà a squadra di muderazione di %{instance}. @@ -1299,11 +1369,13 @@ co: subject: disable: U vostru contu %{acct} hè statu ghjacciatu none: Avertimentu pè %{acct} + sensitive: I media di u vostru contu %{acct} sò stati marcati cum'è sensibili silence: U vostru contu %{acct} hè statu limitatu suspend: U vostru contu %{acct} hè statu suspesu title: disable: Contu ghjacciatu none: Avertimentu + sensitive: U vostru media hè statu marcatu cum'è sensibile silence: Contu limitatu suspend: Contu suspesu welcome: @@ -1324,9 +1396,11 @@ co: tips: Cunsiglii title: Benvenutu·a, %{name}! users: + blocked_email_provider: Stu serviziu e-mail ùn hè micca auturizatu follow_limit_reached: Ùn pidete seguità più di %{limit} conti generic_access_help_html: Prublemi d'accessu à u vostru contu? Pudete cuntattà %{email} per ottene aiutu invalid_email: L’indirizzu e-mail ùn hè currettu + invalid_email_mx: L'indirizzu e-mail ùn pare micca esiste invalid_otp_token: U codice d’identificazione ùn hè currettu invalid_sign_in_token: Codice di sicurità micca validu otp_lost_help_html: S’è voi avete persu i dui, pudete cuntattà %{email} @@ -1336,3 +1410,20 @@ co: verification: explanation_html: 'Pudete <strong>verificavi cum''è u pruprietariu di i ligami in i metadati di u vostru prufile</strong>. Per quessa, u vostru situ deve avè un ligame versu a vostra pagina Mastodon. U ligame <strong>deve</strong> avè un''attributu <code>rel="me"</code>. U cuntenutu di u testu di u ligame ùn hè micca impurtante. Eccu un''esempiu:' verification: Verificazione + webauthn_credentials: + add: Aghjunghje una chjave di sicurità + create: + error: C'hè statu un prublemu aghjunghjendu a vostra chjave di sicurità . Duvete ripruvà . + success: A vostra chjave di sicurità hè stata aghjunta. + delete: Sguassà + delete_confirmation: Site sicuru·a che vulete sguassà sta chjave? + description_html: S'e voi attivate l'<strong>autentificazione à chjave di sicurità </strong>, duverete utilizà una di e vostre chjave ogni volta chì vi cunnettate. + destroy: + error: C'hè statu un prublemu togliendu a vostra chjave di sicurità . Duvete ripruvà . + success: A vostra chjave di sicurità hè stata sguassata. + invalid_credential: Chjave di sicurità I2F micca validu + nickname_hint: Entrate u nome di a vostra nova chjave di sicurità + not_enabled: Ùn avete micca attivatu WebAuthn + not_supported: E chjave di sicurità ùn marchjanu micca cù quessu navigatore + otp_required: Per utilizà una chjave di sicurità duvete attivà l'identificazione à dui fattori prima. + registered_on: Arregistrata %{date} diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 73670dcc9ad9e19d1a760aeed51d6cd85ede176c..e54e635173d970dbe5fd1718f76516a19db3155f 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1285,21 +1285,14 @@ cs: default: "%d. %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Pro potvrzenà zadejte kód vygenerovaný vašà ověřovacà aplikacà - description_html: Zapnete-li <strong>dvoufázové ověřovánÃ</strong>, budete pro pÅ™ihlaÅ¡ovánà potÅ™ebovat telefon, který vám vygeneruje pÅ™Ãstupové tokeny, které musÃte zadat. disable: Vypnout - enable: Zapnout enabled: Dvoufázové ověřovánà je zapnuto enabled_success: Dvoufázové ověřovánà bylo úspěšnÄ› zapnuto generate_recovery_codes: Vygenerovat záložnà kódy - instructions_html: "<strong>Naskenujte tento QR kód Google Authenticatorem nebo jinou TOTP aplikacà na svém telefonu</strong>. Od teÄ bude tato aplikace generovat tokeny, které budete muset zadat pÅ™i pÅ™ihlášenÃ." lost_recovery_codes: Záložnà kódy vám dovolà dostat se k vaÅ¡emu úÄtu, pokud ztratÃte telefon. ZtratÃte-li záložnà kódy, můžete je zde znovu vygenerovat. VaÅ¡e staré záložnà kódy budou zneplatnÄ›ny. - manual_instructions: 'Nemůžete-li QR kód naskenovat a je potÅ™eba ho zadat ruÄnÄ›, zde je secret v prostém textu:' recovery_codes: Záložnà kódy pro obnovu recovery_codes_regenerated: Záložnà kódy byly úspěšnÄ› znovu vygenerovány recovery_instructions_html: ZtratÃte-li nÄ›kdy pÅ™Ãstup ke svému telefonu, můžete k zÃskánà pÅ™Ãstupu k úÄtu použÃt jeden ze záložnÃch kódů. <strong>Uchovejte tyto kódy v bezpeÄÃ</strong>. Můžete si je napÅ™Ãklad vytisknout a uložit je mezi jiné důležité dokumenty. - setup: Nastavit - wrong_code: Zadaný kód byl neplatný! Je Äas na serveru a na zaÅ™Ãzenà správný? user_mailer: backup_ready: explanation: Vyžádali jste si úplnou zálohu svého úÄtu Mastodon. Nynà je pÅ™ipravena ke staženÃ! diff --git a/config/locales/cy.yml b/config/locales/cy.yml index 40d70b838302e9d33aeb6bf59e424a5919bf7178..92ce53fe686c7a11b92f76ed577417aa8784f32e 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -44,8 +44,11 @@ cy: domain: Gweinydd reason: 'Rheswm:' rejecting_media: Ni fydd ffeiliau cyfryngau o'r gweinydd hwn yn cael eu prosesu ac ni fydd unrhyw fawd yn cael eu harddangos, sy'n gofyn am glicio â llaw i'r gweinydd arall. + rejecting_media_title: Cyfrwng hidliedig silenced: Ni fydd swyddi o'r gweinydd hwn yn ymddangos yn unman heblaw eich porthiant cartref os dilynwch yr awdur. + silenced_title: Gweinyddion wedi'i tawelu suspended: Ni fyddwch yn gallu dilyn unrhyw un o'r gweinydd hwn, ac ni fydd unrhyw ddata ohono'n cael ei brosesu na'i storio, ac ni chyfnewidir unrhyw ddata. + suspended_title: Gweinyddion wedi'i gwahardd unavailable_content_html: Yn gyffredinol, mae Mastodon yn caniatáu ichi weld cynnwys gan unrhyw weinyddwr arall yn y ffederasiwn a rhyngweithio â hi. Dyma'r eithriadau a wnaed ar y gweinydd penodol hwn. user_count_after: few: defnyddwyr @@ -325,6 +328,7 @@ cy: listed: Rhestredig new: title: Ychwanegu emoji personol newydd + not_permitted: Nid oes gennych caniatâd i gyflawni'r weithred hon overwrite: Trosysgrifio shortcode: Byrgod shortcode_hint: O leiaf 2 nodyn, dim ond nodau alffaniwmerig a tanlinellau @@ -962,6 +966,7 @@ cy: on_cooldown: Rydych wedi mudo eich cyfrif yn diweddar. Bydd y swyddogaeth hon ar gael eto mewn %{count} diwrnod. past_migrations: Ymfudiadau yn y gorffennol proceed_with_move: Symud dilynwyr + redirected_msg: Mae eich cyfrif yn awr yn ailgyfeirio at %{acct}. redirecting_to: Mae eich cyfrif yn ailgyfeirio at %{acct}. set_redirect: Gosod ailgyfeiriad warning: @@ -975,6 +980,10 @@ cy: redirect: Bydd proffil eich cyfrif presennol yn cael ei diweddaru gyda hysbysiad ailgyfeirio ac yn cael ei eithrio o chwiliadau moderation: title: Goruwchwyliad + move_handler: + carry_blocks_over_text: Wnaeth y defnyddiwr symud o %{acct}, a oeddech chi wedi'i flocio. + carry_mutes_over_text: Wnaeth y defnyddiwr symud o %{acct}, a oeddech chi wedi'i dawelu. + copy_account_note_text: 'Wnaeth y defnyddiwr symud o %{acct}, dyma oedd eich hen nodiadau amdanynt:' notification_mailer: digest: action: Gweld holl hysbysiadau @@ -1161,6 +1170,13 @@ cy: spam_detected: Mae hyn yn adrodd awtomatig. Caiff sbam ei ganfod. statuses: attached: + audio: + few: "%{count} ffeil clywedol" + many: "%{count} ffeil clywedol" + one: "%{count} ffeil clywedol" + other: "%{count} ffeil clywedol" + two: "%{count} ffeil clywedol" + zero: "%{count} ffeil clywedol" description: 'Ynghlwm: %{attached}' image: few: "%{count} o luniau" @@ -1320,26 +1336,25 @@ cy: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Mewnbynwch y côd a grewyd gan eich ap dilysu i gadarnhau - description_html: Os ydych yn galluogi <strong>awdurdodi dau-gam</strong>, bydd mewngofnodi yn gofyn i chi fod a'ch ffôn gerllaw er mwyn cynhyrchu tocyn i chi gael mewnbynnu. disable: Diffodd - enable: Galluogi enabled: Awdurdodi dau-gam wedi'i alluogi enabled_success: Awdurdodi dau-gam wedi'i alluogi'n llwyddiannus generate_recovery_codes: Cynhyrchu côdau adfer - instructions_html: "<strong>Sganiwch y côd QR yn Google Authenticator neu ap TOTP tebyg ar eich ffôn</strong>. O hyn ymlaen, bydd yr ap hwnnw yn cynhyrchu tocynnau y bydd rhaid i chi fewnbynnu tra'n mewngofnodi." lost_recovery_codes: Mae côdau adfer yn caniatau i chi gael mynediad i'ch cyfrif eto os ydych yn colli'ch ffôn. Os ydych wedi colli eich côdau adfer, mae modd i chi gynhyrchu nhw eto yma. Bydd eich hen gôdau wedyn yn annilys. - manual_instructions: 'Os nad ydych yn gallu sganio côd QR ac angen ei fewnbynnu a llaw, dyma''r gyfrinach testun-plaen:' recovery_codes: Creu copi wrth gefn o gôdau adfywio recovery_codes_regenerated: Llwyddwyd i ail greu côdau adfywio recovery_instructions_html: Os ydych byth yn colli mynediad i'ch ffôn, mae modd i chi ddefnyddio un o'r côdau adfywio isod i ennill mynediad i'ch cyfrif eto. <strong>Cadwch y côdau adfywio yn saff</strong>. Er enghraifft, gallwch eu argraffu a'u cadw gyda dogfennau eraill pwysig. - setup: Sefydlu - wrong_code: Roedd y cod y mewnbynnwyd yn annilys! A yw'r amser gweinydd ac amser dyfais yn gywir? user_mailer: backup_ready: explanation: Fe wnaethoch chi gais am gopi wrth gefn llawn o'ch cyfrif Mastodon. Mae nawr yn barod i'w lawrlwytho! subject: Mae eich archif yn barod i'w lawrlwytho title: Allfudo archif + sign_in_token: + details: 'Dyma''r manylion o''r ceisiad:' + explanation: 'Wnaethom ni synhwyro ceisiad i fewngofnodi i''ch cyfrif o gyfeiriad IP anabyddiedig. Os mae hyn yn chi, mewnbynnwch y cod diogelwch isod i fewn i''r dudalen herio mewngofnodiad:' + further_actions: 'Os nad oedd hyn yn chi, newidwch eich cyfrinair ac alluogi awdurdodi dauffactor ar eich cyfrif. Gallwch gwneud hyn fama:' + subject: Cadarnhewch yr ymgais mewngofnodi + title: Ymgais mewngofnodi warning: explanation: disable: Er bod eich cyfrif wedi'i rewi, mae eich data cyfrif yn parhau i fod yn gyfan, ond ni allwch chi berfformio unrhyw gamau nes ei ddatgloi. @@ -1376,12 +1391,17 @@ cy: tips: Awgrymiadau title: Croeso, %{name}! users: + blocked_email_provider: Nid yw'r darparwr ebost hon yn cael ei ganiatâu follow_limit_reached: Nid oes modd i chi ddilyn mwy na %{limit} o bobl + generic_access_help_html: Cael trafferth yn cyrchu eich cyfrif? Efallai hoffwch cysylltu â %{email} am gymorth invalid_email: Mae'r cyfeiriad e-bost hwn yn annilys + invalid_email_mx: Nid yw'r ebost yn edrcyh fel ei bod yn bodoli invalid_otp_token: Côd dau-ffactor annilys + invalid_sign_in_token: Cod diogelwch annilys otp_lost_help_html: Os colloch chi fynediad i'r ddau, mae modd i chi gysylltu a %{email} seamless_external_login: Yr ydych wedi'ch mewngofnodi drwy wasanaeth allanol, felly nid yw gosodiadau cyfrinair ac e-bost ar gael. signed_in_as: 'Wedi mewngofnodi fel:' + suspicious_sign_in_confirmation: Mae'n edrych fel nad ydych wedi mewngofnodi o'r dyfais hyn o'r blaen, a nid ydych wedi mewngofnodi am sbel, felly rydym yn anfon cod diogelwch i'ch cyfeiriad ebost i gadarnhau bod chi yw hi. verification: explanation_html: 'Mae modd i chi <strong>ddilysu eich hun fel perchenog y dolenni yn metadata eich proffil</strong>. Rhaid i''r wefan a dolen iddi gynnwys dolen yn ôl i''ch proffil Mastodon. <strong>Rhaid</strong> i''r ddolen yn ôl gael nodwedd <code>rel="fi"</code>. Nid oes ots beth yw cynnwys testun y ddolen. Dyma enghraifft:' verification: Dilysu diff --git a/config/locales/da.yml b/config/locales/da.yml index c7189ae34ba0f0f277c60958d188c55b33537374..c98404066e72f7cc9e7525f3a86a97946b5a2f4d 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -40,8 +40,11 @@ da: domain: Server reason: Ã…rsag rejecting_media: 'Medie filer fra disse servere vil ikke blive behandlet eller gemt, og ingen miniaturebilleder vil blive vist, som kræver tilgang til den originale fil:' + rejecting_media_title: Filtrerede medier silenced: 'Posteringer fra disse servere vil være skjulte i den offentlige tidslinje feed eller beskeder og ingen notifikationer vil blive genereret fra brugere du ikke følger:' + silenced_title: Dæmpede servere suspended: 'Ingen date fra disse servere vil blive behandlet, gemt eller udvekslet, at interagere eller kommunikere med brugere fra disse servere er ikke muligt:' + suspended_title: Suspenderede servere unavailable_content_html: Mastodon tillader dig generelt at se indhold og interagere med brugere fra enhver anden server i fediverset. Dette er undtagelser der er foretaget pÃ¥ netop denne server. user_count_after: one: bruger @@ -50,6 +53,7 @@ da: what_is_mastodon: Hvad er Mastodon? accounts: choices_html: "%{name}s valg:" + endorsements_hint: Du kan støtte folk du følger fra web-interface, og de vil dukke op her. featured_tags_hint: Du kan tilføje specifikke hashtags der vil blive vist her. follow: Følg followers: @@ -91,6 +95,7 @@ da: delete: Slet destroyed_msg: Moderator notat succesfuldt destrueret! accounts: + add_email_domain_block: Bloker e-mail domæne approve: Godkend approve_all: Godkend alle are_you_sure: Er du sikker? @@ -106,6 +111,7 @@ da: confirm: Bekræft confirmed: Bekræftet confirming: Bekræfter + delete: Slet data deleted: Slettet demote: Degrader disable: Deaktiver @@ -133,6 +139,7 @@ da: login_status: Status pÃ¥ login media_attachments: Medie bilag memorialize: Omdan til et memoriam + memorialized: Memorialiseret moderation: active: Aktiv all: Alle @@ -172,6 +179,8 @@ da: user: Bruger search: Søg search_same_ip: Andre brugere med den samme IP-adresse + sensitive: Følsomt + sensitized: markeret som følsomt shared_inbox_url: Link til delt indbakke show: created_reports: Anmeldelser oprettet @@ -188,16 +197,37 @@ da: undo_suspension: Fortryd udelukkelse unsubscribe: Abonner ikke længere username: Brugernavn + view_domain: Vis resumé for domæne warn: Advar web: Web whitelisted: Hvidlistet action_logs: action_types: + assigned_to_self_report: Tildel rapport + change_email_user: Ændre e-mail for bruger confirm_user: Bekræft bruger + create_account_warning: Opret advarsel + create_announcement: Opret bekendtgørelse + create_domain_allow: Opret domæne tillad + create_domain_block: Opret domæneblokering + create_ip_block: Opret IP-regel + destroy_announcement: Slet bekendtgørelse + destroy_domain_block: Slet domæneblokering + destroy_email_domain_block: Slet e-mail domæne blokering + destroy_ip_block: Slet IP-regel destroy_status: Slet status disable_2fa_user: Slet 2FA disable_user: Deaktiver brugeren enable_user: Aktiver brugeren + remove_avatar_user: Fjern profilbillede + reopen_report: GenÃ¥ben rapport + reset_password_user: Nulstil adgangskode + resolve_report: Løs rapport + silence_account: Dæmp konto + suspend_account: Suspendér Konto + unsilence_account: Fjern dæmpelse af konto + update_announcement: Opdater bekendtgørelse + update_status: Opdater status actions: assigned_to_self_report: "%{name} tildelte anmeldelsen %{target} til sig selv" change_email_user: "%{name} ændrede email adressen for brugeren %{target}" @@ -207,11 +237,13 @@ da: create_domain_allow: "%{name} godkendte domænet %{target}" create_domain_block: "%{name} blokerede domænet %{target}" create_email_domain_block: "%{name} sortlistede email domænet %{target}" + create_ip_block: "%{name} oprettede regel for IP %{target}" demote_user: "%{name} degraderede %{target}" destroy_custom_emoji: "%{name} fjernede emoji %{target}" destroy_domain_allow: "%{name} fjernede godkendelsen af domænet %{target}" destroy_domain_block: "%{name} fjernede blokeringen af domænet %{target}" destroy_email_domain_block: "%{name} hvid-listede email domænet %{target}" + destroy_ip_block: "%{name} slettede reglen for IP %{target}" destroy_status: "%{name} fjernede statussen fra %{target}" disable_2fa_user: "%{name} deaktiverede to faktor kravet for brugeren %{target}" disable_custom_emoji: "%{name} deaktiverede humørikonet %{target}" @@ -232,9 +264,23 @@ da: update_custom_emoji: "%{name} opdaterede humørikonet %{target}" update_status: "%{name} opdaterede status for %{target}" deleted_status: "(slettet status)" + empty: Ingen logs fundet. filter_by_action: Filtrer efter handling filter_by_user: Filtrer efter bruger title: Revisionslog + announcements: + destroyed_msg: Bekendtgørelsen blev slettet! + edit: + title: Rediger bekendtgørelse + empty: Ingen bekendtgørelser fundet. + live: Direkte + new: + create: Opret bekendtgørelse + title: Ny bekendtgørelse + published_msg: Bekendtgørelsen blev slettet! + scheduled_for: Planlagt til %{time} + title: Bekendtgørelser + updated_msg: Bekendtgørelsen blev opdateret! custom_emojis: assign_category: Vælg kategori by_domain: Domæne @@ -257,6 +303,7 @@ da: listed: Listet new: title: Tilføj nyt brugerdefineret humørikon + not_permitted: Du har ikke tilladelse til at udføre denne handling overwrite: Overskriv shortcode: Kortkode shortcode_hint: Mindst 2 tegn, kun alfabetiske tegn og understreger @@ -323,6 +370,7 @@ da: rejecting_media: afviser mediefiler rejecting_reports: afviser anmeldelser severity: + silence: dæmpet suspend: suspenderet show: affected_accounts: @@ -341,6 +389,7 @@ da: delete: Slet destroyed_msg: Fjernede succesfuldt email domænet fra sortliste domain: Domæne + empty: Ingen e-mail-domæner er i øjeblikket blokeret. from_html: fra %{domain} new: create: Tilføj domæne @@ -349,15 +398,21 @@ da: instances: by_domain: Domæne delivery_available: Levering er tilgængelig + known_accounts: + one: "%{count} kendt konto" + other: "%{count} kendte konti" moderation: all: Alle limited: Begrænset + title: Moderation private_comment: Privat kommentar public_comment: Offentlig kommentar title: Førderation total_blocked_by_us: Blokeret af os total_followed_by_them: Fulgt af dem total_followed_by_us: Fulgt af os + total_reported: Rapporter om dem + total_storage: Vedhæftede medier invites: deactivate_all: Deaktiver alle filter: @@ -366,6 +421,25 @@ da: expired: Udløbet title: Filtre title: Invitationer + ip_blocks: + add_new: Opret regel + created_msg: Ny IP-regel blev tilføjet + delete: Slet + expires_in: + '1209600': 2 uger + '15778476': 6 mÃ¥neder + '2629746': 1 mÃ¥ned + '31556952': 1 Ã¥r + '86400': 1 dag + '94670856': 3 Ã¥r + new: + title: Opret ny IP-regel + no_ip_block_selected: Ingen IP-regler blev ændret, da ingen blev valgt + title: IP-regler + pending_accounts: + title: Afventende konti (%{count}) + relationships: + title: "%{acct}'s relationer" relays: add_new: Tilføj nyt relay delete: Slet @@ -379,16 +453,22 @@ da: pending: Venter pÃ¥ godkendelse fra relæet save_and_enable: Gem og aktiver setup: Opsæt en videresendelses forbindelse + signatures_not_enabled: Relæer fungerer ikke korrekt, mens sikker tilstand eller begrænset føderationstilstand er aktiveret status: Status title: Videresendelser report_notes: created_msg: Anmeldelse note blev oprettet! destroyed_msg: Anmeldelse note blev slettet! reports: + account: + reports: + one: "%{count} rapport" + other: "%{count} rapporter" action_taken_by: Handling udført af are_you_sure: Er du sikker? assign_to_self: Tildel til mig assigned: Tildelt moderator + by_target_domain: Domæne for rapporteret konto comment: none: Ingen created_at: Anmeldt @@ -428,6 +508,8 @@ da: all: Til alle disabled: Til ingen title: Vis domæne blokeringer + enable_bootstrap_timeline_accounts: + title: Aktiver standard følger for nye brugere hero: desc_html: Vist pÃ¥ forsiden. Mindst 600x100px anbefales. Hvis ikke sat, vil dette falde tilbage til billedet fra serveren title: Billede af helt @@ -437,6 +519,9 @@ da: preview_sensitive_media: desc_html: ForhÃ¥ndsvisninger af links pÃ¥ andre websider vil vise et miniaturebillede selv hvis mediet er markeret som følsomt title: Vis følsomt medie i OpenGraph forhÃ¥ndsvisninger + profile_directory: + desc_html: Tillad bruger at kunne blive fundet + title: Aktivér profilmappe registrations: closed_message: desc_html: Vist pÃ¥ forsiden nÃ¥r registreringer er lukkede. Du kan bruge HTML tags @@ -449,8 +534,10 @@ da: title: Tillad invitationer af registrations_mode: modes: + approved: Godkendelse pÃ¥krævet for tilmelding none: Ingen kan tilmelde sig open: Alle kan tilmelde sig + title: Tilstand for registreringer show_known_fediverse_at_about_page: desc_html: NÃ¥r slÃ¥et til, vil det vise trut fra hele det kendte fedivers pÃ¥ forhÃ¥ndsvisning. Ellers vil det kun vise lokale trut. title: Vis kendte fedivers pÃ¥ tidslinje forhÃ¥ndsvisning @@ -470,6 +557,8 @@ da: desc_html: Du kan skrive din egen privatlivpolitik, servicevilkÃ¥r, eller lignende. Du kan bruge HTML tags title: Brugerdefineret servicevilkÃ¥r site_title: Navn af serveren + spam_check_enabled: + title: Anti-spam automatisering thumbnail: desc_html: Brugt til forhÃ¥ndsvisninger via OpenGraph og API. 1200x630px anbefales title: Miniaturebillede for serveren @@ -477,6 +566,10 @@ da: desc_html: Vis offentlig tidslinje pÃ¥ landingssiden title: Tidslinje forhÃ¥ndsvisning title: Indstillinger for side + trends: + title: Populære hashtags + site_uploads: + delete: Slet oplagt fil statuses: back_to_account: Tilbage til kontosiden batch: @@ -495,10 +588,22 @@ da: accounts_today: Unikke brug i dag accounts_week: Unikke brug denne uge context: Kontekst + directory: I mappe + in_directory: "%{count} i mappe" last_active: Sidst aktiv most_popular: Mest populære most_recent: Seneste + name: Hashtag + review: GennemgÃ¥ status + reviewed: GennemgÃ¥et + title: Hashtags + trending_right_now: Populære lige nu + unique_uses_today: "%{count} indlæg i dag" + unreviewed: Ikke gennemlæst + updated_msg: Hashtag-indstillinger opdateret + title: Administration warning_presets: + add_new: Tilføj ny delete: Slet admin_mailer: new_report: @@ -507,8 +612,11 @@ da: subject: Ny anmeldelse for %{instance} (#%{id}) aliases: add_new: Opret alias + empty: Du har ingen aliasser. appearance: + advanced_web_interface: Avanceret webgrænseflade animations_and_accessibility: Animationer og tilgængelighed + confirmation_dialogs: Bekræftelsesdialoger discovery: Opdagelse localization: body: Mastodon oversættes af frivillige. @@ -536,8 +644,10 @@ da: delete_account: Slet konto delete_account_html: Hvis du ønsker at slette din konto, kan du <a href="%{path}">gøre det her</a>. Du vil blive bedt om bekræftelse. description: + prefix_invited_by_user: "@%{name} inviterer dig til at deltage i denne Mastodons server!" prefix_sign_up: Tilmeld dig Mastodon i dag! didnt_get_confirmation: Har du endnu ikke modtaget instrukser for bekræftelse? + dont_have_your_security_key: Har du ikke dine sikkerhedsnøgler? forgot_password: Glemt dit kodeord? invalid_reset_password_token: Adgangskode nulstillings token er ugyldig eller udløbet. Anmod venligst om en ny. login: Log ind @@ -545,17 +655,26 @@ da: migrate_account: Flyt til en anden konto migrate_account_html: Hvis du ønsker at omdirigere denne konto til en anden, kan du <a href="%{path}">gøre det her</a>. or_log_in_with: Eller log in med + providers: + cas: CAS + saml: SAML register: Opret dig registration_closed: "%{instance} accepterer ikke nye medlemmer" resend_confirmation: Gensend bekræftelses instrukser reset_password: Nulstil kodeord security: Sikkerhed set_new_password: Sæt et nyt kodeord + setup: + email_settings_hint_html: Bekræftelsesmailen blev sendt til %{email}. Hvis denne e-mailadresse ikke er korrekt, kan du ændre den i kontoindstillinger. + title: Opsætning status: account_status: Kontostatus + confirming: Venter pÃ¥ at e-mail bekræftelsen er fuldført. trouble_logging_in: Har du problemer med at logge pÃ¥? + use_security_key: Brug sikkerhedsnøgle authorize_follow: already_following: Du følger allerede denne konto + already_requested: Du har allerede sendt en følgeanmodning til denne konto error: Der opstod desværre en fejl under søgningen af denne fjerne konto follow: Følg follow_request: 'Du har anmodet om at følge:' @@ -567,8 +686,17 @@ da: title: Følg %{acct} challenge: confirm: Fortsæt + hint_html: "<strong>Tip:</strong> We won't ask you for your password again for the next hour." invalid_password: Ugyldig adgangskode prompt: Bekræft din adgangskode for at fortsætte + crypto: + errors: + invalid_key: er ikke en gyldig Ed25519 eller Curve25519 nøgle + invalid_signature: er ikke en gylidig Ed25519 signatur + date: + formats: + default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}t" @@ -576,18 +704,26 @@ da: about_x_years: "%{count}Ã¥r" almost_x_years: "%{count}Ã¥r" half_a_minute: Lige nu + less_than_x_minutes: "%{count}m" less_than_x_seconds: Lige nu over_x_years: "%{count}Ã¥r" + x_days: "%{count}d" + x_minutes: "%{count}m" x_months: "%{count}md" + x_seconds: "%{count}s" deletes: + challenge_not_passed: De oplysninger, du indtastede var ikke korrekte confirm_password: Indtast dit nuværende kodeord for at bekræfte din identitet + confirm_username: Indtast dit brugernavn for at bekræfte proceduren proceed: Slet konto success_msg: Din konto er nu blevet slettet warning: + email_change_html: Du kan <a href="%{path}">ændre din e-mail-adresse</a> uden at slette din konto username_available: Dit brugernavn vil blive tilgængeligt igen username_unavailable: Dit brugernavn vil forblive utilgængeligt directories: directory: Profilliste + explanation: Opdag brugere baseret pÃ¥ deres interesser explore_mastodon: Uforsk %{title} domain_validator: invalid_domain: er ikke et gyldigt domænenavn @@ -604,7 +740,7 @@ da: '500': content: Beklager men der gik noget galt i vores ende. title: Siden er ikke korrekt - '503': The page could not be served due to a temporary server failure. + '503': Siden kunne ikke serveres pÃ¥ grund af en midlertidig serverfejl. noscript_html: For at bruge Mastodon web applikationen, aktiver JavaScript. Alternativt kan du prøve en af disse <a href="%{apps_path}">apps</a> til Mastodon for din platform. existing_username_validator: not_found: kunne ikke finde en lokal bruger med dette brugenavn @@ -618,11 +754,16 @@ da: request: Anmod om dit arkiv size: Størrelse blocks: Du blokerer + bookmarks: Bogmærker csv: CSV domain_blocks: Domæne blokeringer lists: Lister mutes: Du dæmper storage: Medie lager + featured_tags: + add_new: Tilføj ny + errors: + limit: Du har allerede vist det maksimale antal hashtags filters: contexts: account: Profiler @@ -637,6 +778,7 @@ da: invalid_irreversible: Uigenkaldelig filtrering virker kun med hjem eller notifikations kontekst index: delete: Slet + empty: Du har ingen filtre. title: Filtrer new: title: Tilføj nyt filter @@ -656,15 +798,27 @@ da: one: Der er noget der ikke er helt som det bør være! Tag lige et kig pÃ¥ følgende fejl forneden other: Der er noget der ikke er helt som det bør være! Tag lige et kig pÃ¥ følgende %{count} fejl forneden identity_proofs: + active: Aktiv + authorize: Ja, tillad i_am_html: Jeg er %{username} pÃ¥ %{service}. identity: Identitet + inactive: Inaktiv + publicize_checkbox: 'Og toot dette:' + publicize_toot: 'Det er bevist! Jeg er %{username} pÃ¥ %{service}: %{url}' + remove: Fjern bevis fra konto + removed: Beviset er fjernet fra kontoen + status: Status for verifikation + view_proof: Se bevis imports: modes: + merge: Sammenflet overwrite: Overskriv preface: Du kan importere data du har eksporteret fra en anden server, sÃ¥ som en liste over folk du følger eller blokerer. success: Dine data blev succesfuldt uploaded og vil nu blive behandlet hurtigst muligt types: blocking: Blokeringsliste + bookmarks: Bogmærker + domain_blocking: Domæne blokeringsliste following: Følgningsliste muting: Liste over dæmpninger upload: Læg op @@ -697,12 +851,23 @@ da: media_attachments: validations: images_and_video: Kan ikke vedhæfte en video til en status der allerede har billeder + not_ready: Kan ikke vedhæfte filer, der ikke er færdige med behandlingen. Prøv igen om et øjeblik! too_many: Kan ikke vedhæfte mere en 4 filer migrations: acct: username@domain af den nye konto errors: + missing_also_known_as: er ikke et alias for denne konto + move_to_self: kan ikke være den nuværende konto not_found: kunne ikke bive fundet + on_cooldown: Du er pÃ¥ nedkøling + followers_count: Følgere pÃ¥ tidspunktet for flytningen + incoming_migrations: Flytter fra en anden konto + past_migrations: Tidligere migrationer proceed_with_move: Flyt følgere + redirected_msg: Din konto omdirigerer nu til %{acct}. + redirecting_to: Din konto omdirigerer til %{acct}. + warning: + other_data: Ingen andre data vil blive flyttet automatisk moderation: title: Moderatering notification_mailer: @@ -739,12 +904,19 @@ da: body: 'Din status blev fremhævet af %{name}:' subject: "%{name} fremhævede din status" title: Ny fremhævelse + notifications: + email_events: Begivenheder for e-mail-meddelelser + other_settings: Andre indstillinger for notifikationer number: human: decimal_units: + format: "%n%u" units: billion: mia. million: mio. + otp_authentication: + enable: Aktiver + wrong_code: Den indtastede kode var ugyldig! Er serverens tid og enhedstid korrekt? pagination: newer: Nyere next: Næste @@ -754,22 +926,36 @@ da: polls: errors: already_voted: Du har allerede stemt i denne afstemning + duplicate_options: indeholder dublerede elementer duration_too_long: er for langt ude i fremtiden duration_too_short: er for tidligy expired: Denne afstemning er allerede afsluttet + invalid_choice: Den valgte stemmeindstilling findes ikke + over_character_limit: kan ikke være længere end %{max} tegn hver + too_few_options: skal have mere end et element + too_many_options: kan ikke indeholde flere end %{max} elementer preferences: other: Andet public_timelines: Offentlige tidslinjer + reactions: + errors: + limit_reached: Grænsen for forskellige reaktioner er nÃ¥et + unrecognized_emoji: er ikke en genkendt emoji relationships: activity: Aktivitet for konto + follow_selected_followers: Følg valgte følgere followers: Følgere following: Følger + invited: Inviteret last_active: Sidst aktiv most_recent: Seneste moved: Flyttet mutual: Fælles primary: Primær relationship: Relation + remove_selected_domains: Fjern alle følgere fra de valgte domæner + remove_selected_followers: Fjern valgte følgere + remove_selected_follows: Følg ikke valgte brugere status: Status for konto remote_follow: acct: Indtast dit brugernavn@domæne du vil handle fra @@ -777,6 +963,8 @@ da: no_account_html: Har du ikke en konto? Du kan <a href='%{sign_up_path}' target='_blank'>oprette dig her</a> proceed: Fortsæt for at følge prompt: 'Du er ved at følge:' + scheduled_statuses: + too_soon: Den planlagte dato skal være i fremtiden sessions: activity: Sidste aktivitet browser: Browser @@ -821,6 +1009,7 @@ da: settings: account: Konto account_settings: Kontoindstillinger + aliases: Konto-aliaser appearance: Udseende authorized_apps: Godkendte apps back: Tilbage til Mastodon @@ -828,6 +1017,7 @@ da: development: Udvikling edit_profile: Rediger profil export: Data eksportering + featured_tags: Fremhævede hashtags import: Importer import_and_export: Importer og eksporter migrate: Konto migrering @@ -836,8 +1026,12 @@ da: profile: Profil relationships: Følger og følgere two_factor_authentication: To-faktor godkendelse + webauthn_authentication: Sikkerhedsnøgler statuses: attached: + audio: + one: "%{count} lyd" + other: "%{count} lyd" description: 'Vedhæftede: %{attached}' image: one: "%{count} billede" @@ -859,10 +1053,19 @@ da: private: Ikke offentlige trut kan ikke blive fastgjort reblog: Fremhævede trut kan ikke fastgøres poll: + total_people: + one: "%{count} person" + other: "%{count} personer" + total_votes: + one: "%{count} stemme" + other: "%{count} stemmer" vote: Stem show_more: Vis mere + show_newer: Vis nyere + show_older: Vis ældre show_thread: Vis trÃ¥d sign_in_to_participate: Log ind for at deltage i samtalen + title: '%{name}: "%{quote}"' visibilities: private: Kun-følgere private_long: Vis kun til følgere @@ -874,6 +1077,8 @@ da: pinned: Fastgjort trut reblogged: fremhævede sensitive_content: Følsomt indhold + tags: + does_not_match_previous_name: stemmer ikke overens med det forrige navn terms: body_html: "<p><h2> Privatlivspolitik </h2> \n<h3 id=\"collect\">Hvilke information indsamler vi?</h3> \n\n<ul>\n  <li><em>Grundlæggende kontoinformation </em>: Hvis du registrerer dig pÃ¥ denne server, bliver du mÃ¥ske bedt om at indtaste et brugernavn, en e-mail-adresse og et kodeord. Du kan ogsÃ¥ indtaste yderligere profiloplysninger, sÃ¥som et visningsnavn og biografi, og uploade et profilbillede og headerbillede. Brugernavnet, visningsnavnet, biografien, profilbilledet og hovedbilledet vises altid offentligt. </li> \n  <li> <em>Stillinger, følgende og andre offentlige oplysninger </em>: Listen over personer du følger er offentliggjort, det samme gælder for dine tilhængere. NÃ¥r du sender en besked, gemmes datoen og klokkeslættet sÃ¥vel som det program, du sendte beskeden fra. Meddelelser kan indeholde medievedhæftninger, som f.eks. Billeder og videoer. Offentlige og unoterede indlæg er offentligt tilgængelige. NÃ¥r du har et indlæg pÃ¥ din profil, er det ogsÃ¥ offentligt tilgængelig information. Dine indlæg leveres til dine tilhængere, i nogle tilfælde betyder det, at de leveres til forskellige servere, og der gemmes kopier der. NÃ¥r du sletter indlæg, leveres det ogsÃ¥ til dine tilhængere. Handlingen med reblogging eller favorisering af et andet indlæg er altid offentligt. </li>\n  <li><em> Direkte og efterfølger-kun indlæg </ em>: Alle indlæg gemmes og behandles pÃ¥ serveren. Følgere-kun indlæg leveres til dine tilhængere og brugere, der er nævnt i dem, og direkte indlæg leveres kun til brugere nævnt i dem. I nogle tilfælde betyder det, at de leveres til forskellige servere, og der gemmes kopier der. Vi gør en god tro for at begrænse adgangen til disse stillinger kun til autoriserede personer, men andre servere kan undlade at gøre det. Derfor er det vigtigt at gennemgÃ¥ de servere, dine tilhængere tilhører. Du kan skifte en mulighed for at godkende og afvise nye følgere manuelt i indstillingerne. <em> Vær opmærksom pÃ¥, at operatørerne af serveren og enhver modtagende server muligvis kan se sÃ¥danne meddelelser </em>, og at modtagere muligvis skærmbilleder, kopierer eller pÃ¥ anden vis deler dem igen. <em> Del ikke nogen farlig information over Mastodon. </em> </li>\n  <li> <em> IP'er og andre metadata </em>: NÃ¥r du logger ind, registrerer vi den IP-adresse, du logger ind fra, samt navnet pÃ¥ din browser-applikation. Alle indloggede sessioner er tilgængelige til din anmeldelse og tilbagekaldelse i indstillingerne. Den seneste anvendte IP-adresse gemmes i op til 12 mÃ¥neder. Vi kan ogsÃ¥ beholde serverlogfiler, som indeholder IP-adressen til hver anmodning til vores server. </li>\n</ul>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"use\">Hvad bruger vi dine oplysninger til? </h3>\n\n<p> Enhver af de oplysninger, vi indsamler fra dig, kan bruges pÃ¥ følgende mÃ¥der: </p>\n\n<ul>\n  <li> At levere kernen funktionalitet Mastodon. Du kan kun interagere med andres indhold og indsende dit eget indhold, nÃ¥r du er logget ind. Du kan f.eks. Følge andre personer for at se deres kombinerede indlæg pÃ¥ din egen personlige tidslinje. </li>\n  <li> For at hjælpe moderering af samfundet, f.eks. sammenligning af din IP-adresse med andre kendte, for at bestemme forbud mod unddragelse eller andre overtrædelser. </li>\n  <li> Den e-mail-adresse, du angiver, kan bruges til at sende dig oplysninger, meddelelser om andre personer, der interagerer med dit indhold eller sender dig beskeder, og for at svare pÃ¥ henvendelser og / eller andre forespørgsler eller spørgsmÃ¥l. </li>\n</ul>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"protect\">Hvordan beskytter vi dine oplysninger? </h3>\n\n<p> Vi implementerer en række sikkerhedsforanstaltninger for at opretholde sikkerheden for dine personlige oplysninger, nÃ¥r du indtaster, indsender eller har adgang til dine personlige oplysninger. Bl.a. er din browsersession samt trafikken mellem dine applikationer og API'en sikret med SSL, og din adgangskode er hashed ved hjælp af en stærk envejsalgoritme. Du kan muligvis aktivere tofaktors godkendelse for yderligere at sikre adgang til din konto. </p>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"data-retention\"> Hvad er vores data retention politik? </h3>\n\n<p> Vi vil gøre en god tro indsats for at: </p>\n\n<ul>\n  <li> Behold serverlogfiler, der indeholder IP-adressen pÃ¥ alle anmodninger til denne server, for sÃ¥ vidt som sÃ¥danne logfiler holdes, ikke mere end 90 dage. </li>\n  <li> Behold de IP-adresser, der er forbundet med registrerede brugere, ikke mere end 12 mÃ¥neder. </li>\n</ul>\n\n<p> Du kan anmode om og downloade et arkiv af dit indhold, herunder dine indlæg, medievedhæftninger, profilbillede og headerbillede. </p>\n\n<p> Du kan til enhver tid slette din konto. </p>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"cookies\"> Bruger vi cookies? </h3>\n\n<p> Ja. Cookies er smÃ¥ filer, som et websted eller dets tjenesteudbyder overfører til din computers harddisk via din webbrowser (hvis du tillader det). Disse cookies gør det muligt for webstedet at genkende din browser og, hvis du har en registreret konto, associerer den med din registrerede konto. </p>\n\n<p> Vi bruger cookies til at forstÃ¥ og gemme dine præferencer til fremtidige besøg. </p>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"disclose\"> Viser vi nogen information til eksterne parter? </h3>\n\n<p> Vi sælger ikke, handler eller pÃ¥ anden mÃ¥de overfører dine personlige identificerbare oplysninger til eksterne parter. Dette omfatter ikke tillid til tredjeparter, der hjælper os med at drive vores hjemmeside, udføre vores forretning eller servicere dig, sÃ¥ længe parterne er enige om at holde disse oplysninger fortrolige. Vi kan ogsÃ¥ frigive dine oplysninger, nÃ¥r vi mener, at udgivelsen er hensigtsmæssig for at overholde loven, hÃ¥ndhæve vores webstedspolitikker eller beskytte vores eller andre rettigheder, ejendom eller sikkerhed. </p>\n\n<p> Dit offentlige indhold kan downloades af andre servere i netværket. Dine offentlige og efterfølger-kun indlæg leveres til de servere, hvor dine tilhængere er bosat, og direkte meddelelser leveres til modtagerens servere, for sÃ¥ vidt som disse tilhængere eller modtagere opholder sig pÃ¥ en anden server end dette. </p>\n\n<p> NÃ¥r du autoriserer et program til at bruge din konto, afhænger det af omfanget af tilladelser, du godkender, det kan fÃ¥ adgang til dine offentlige profiloplysninger, din følgende liste, dine tilhængere, dine lister, alle dine indlæg og dine favoritter. Applikationer kan aldrig fÃ¥ adgang til din e-mail-adresse eller adgangskode. </p>\n\n<hr class=\"spacer\" />\n\n<h3 id=\"children\"> Bebyggelse af børn </h3>\n\n<p> Hvis denne server er i EU eller EØS: Vores websted, produkter og tjenester er alle rettet mod personer, der er mindst 16 Ã¥r gamle. Hvis du er under 16 Ã¥r, skal du ikke bruge dette websted efter kravene i GDPR (<a href=\"https://en.wikipedia.org/wiki/General_Data_Protection_Regulation\"> Generel databeskyttelsesforordning </a>). . </p>\n\n<p> Hvis denne server er i USA: Vores websted, produkter og tjenester er alle rettet mod personer, der er mindst 13 Ã¥r. Hvis du er under 13 Ã¥r, skal du ikke bruge kravene i COPPA (<a href=\"https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act\"> Børns online beskyttelse af personlige oplysninger </a>) dette websted. </p>\n\n<p> Lovkrav kan være anderledes, hvis denne server er i en anden jurisdiktion. </p>\n\n<hr class = \"spacer\" />\n\n<h3 id=\"changes\"> Ændringer i vores privatlivspolitik </h3>\n\n<p> Hvis vi beslutter os for at ændre vores privatlivspolitik, vil vi sende disse ændringer pÃ¥ denne side. </p>\n\n<p> Dette dokument er CC-BY-SA. Det blev senest opdateret 7. marts 2018. </p>\n\n<p> Oprindelig tilpasset fra <a href=\"https://github.com/discourse/discourse\"> Discourse privacy policy </a>.</p>\n" title: VilkÃ¥r og privatlivpolitik for %{instance} @@ -881,28 +1086,40 @@ da: contrast: Mastodon (Høj kontrast) default: Mastodont (Mørk) mastodon-light: Mastodon (Lys) + time: + formats: + default: "%b %d, %Y, %H:%M" + month: "%b %Y" two_factor_authentication: - code_hint: Indtast koden der er genereret af din app for at bekræfte - description_html: Hvis du aktiverer <strong>to-faktor godkendelse</strong>, vil du være nødt til at være i besiddelse af din telefon, der genererer tokens som du skal indtaste, nÃ¥r du logger ind. + add: Tilføj disable: Deaktiver - enable: Aktiver + edit: Rediger enabled: To-faktor godkendelse er aktiveret enabled_success: To-faktor godkendelse succesfuldt aktiveret generate_recovery_codes: Generer gendannelseskoder - instructions_html: "<strong>Scan denne QR kode i Google Autehnticator eller lignende TOTP app pÃ¥ din telefon</strong>. Fra nu af vil den app generere koder som du vil være nødt til at indtaste nÃ¥r du logger ind." lost_recovery_codes: Gendannelseskoder vil lade dig fÃ¥ adgang til din konto hvis du mister din telefon. Hvis du har mistet dine gendannelseskoder, kan du regenerere dem her. Dine gamle gendannelseskoder vil blive ugyldige. - manual_instructions: 'Hvis du ikke kan scanne QR koden er er nødt til at skrive koden ind manuelt, kan er din almindelig tekst secret:' + methods: To-faktor metoder recovery_codes: Reserve koder recovery_codes_regenerated: Reserve koder blev succesfuldt regenereret recovery_instructions_html: Hvis du nogensinde mister adgang til din telefon, kan du bruge en af genoprettelses koderne forneden for at fÃ¥ adgang til din konto. <strong>Gem gendannelses koderne et sikkert sted</strong>. Foreksempel kan du printe dem ud og gemme dem sammen med andre vigtige dokumenter. - setup: Sæt op - wrong_code: Den indtastede kode var ugyldig! Er serverens tid og enhedens tid korrekte? + webauthn: Sikkerhedsnøgler user_mailer: backup_ready: explanation: Din anmodning for fuld backup af din Mastodon konto. Den er nu klar til at blive hentet! subject: Dit arkiv er klar til at blive hentet ned title: Udpluk af arkiv + sign_in_token: + details: 'Her er detaljer om forsøget:' + subject: Bekræft venligst forsøg pÃ¥ at logge ind + title: Login forsøg warning: + review_server_policies: GennemgÃ¥ serverpolitikker + statuses: 'Især for:' + subject: + disable: Din konto %{acct} er blevet frosset + none: Advarsel for %{acct} + silence: Din konto %{acct} er blevet begrænset + suspend: Din konto %{acct} er blevet suspenderet title: disable: Konto frosset none: Advarsel @@ -926,11 +1143,27 @@ da: tips: RÃ¥d title: Velkommen ombord, %{name}! users: + blocked_email_provider: Denne e-mail-udbyder er ikke tilladt follow_limit_reached: Du kan ikke følge mere end %{limit} personer + generic_access_help_html: Har du problemer med at fÃ¥ adgang til din konto? Du kan komme i kontakt med %{email} for hjælp invalid_email: E-mail adressen er ugyldig + invalid_email_mx: E-mail-adressen virker ikke til at eksistere invalid_otp_token: Ugyldig to-faktor kode + invalid_sign_in_token: Ugyldig sikkerhedskode otp_lost_help_html: Hvis du har mistet adgang til begge, kan du fÃ¥ kontakt via %{email} seamless_external_login: Du er logget ind via en ekstern service, sÃ¥ er kodeord og e-mail indstillinger ikke tilgængelige. signed_in_as: 'Logget ind som:' verification: verification: Verificering + webauthn_credentials: + add: Tilføj ny sikkerhedsnøgle + create: + success: Din sikkerhedsnøgle blev tilføjet. + delete: Slet + destroy: + success: Din sikkerhedsnøgle blev slettet. + invalid_credential: Ugyldig sikkerhedsnøgle + nickname_hint: Indtast kaldenavnet pÃ¥ din nye sikkerhedsnøgle + not_enabled: Du har endnu ikke aktiveret WebAuthn + not_supported: Denne browser understøtter ikke sikkerhedsnøgler + registered_on: Registreret den %{date} diff --git a/config/locales/de.yml b/config/locales/de.yml index 021c4b2b26d12fab106f8846a85a2ca4774c1bf1..34d03f808dbe8782b4922e3ce4c78823282d14f9 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -60,6 +60,7 @@ de: one: Folgender other: Folgende following: Folgt + instance_actor_flash: Dieses Konto ist ein virtueller Akteur, der den Server selbst repräsentiert und nicht ein einzelner Benutzer. Es wird für Föderationszwecke verwendet und sollte nicht gesperrt werden. joined: Beigetreten am %{date} last_active: zuletzt aktiv link_verified_on: Besitz des Links wurde überprüft am %{date} @@ -98,6 +99,7 @@ de: add_email_domain_block: E-Mail-Domain blacklisten approve: Akzeptieren approve_all: Alle akzeptieren + approved_msg: "%{username}'s Anmeldeantrag erfolgreich genehmigt" are_you_sure: Bist du sicher? avatar: Profilbild by_domain: Domain @@ -111,8 +113,10 @@ de: confirm: Bestätigen confirmed: Bestätigt confirming: Bestätigung + delete: Daten löschen deleted: Gelöscht demote: Degradieren + destroyed_msg: "%{username}'s Daten wurden zum Löschen in die Warteschlange eingereiht" disable: Ausschalten disable_two_factor_authentication: 2FA abschalten disabled: Ausgeschaltet @@ -123,10 +127,12 @@ de: email_status: E-Mail-Status enable: Freischalten enabled: Freigegeben + enabled_msg: "%{username}'s Konto erfolgreich freigegeben" followers: Folgende follows: Folgt header: Titelbild inbox_url: Posteingangs-URL + invite_request_text: Begründung für das beitreten invited_by: Eingeladen von ip: IP-Adresse joined: Beigetreten @@ -138,6 +144,8 @@ de: login_status: Loginstatus media_attachments: Dateien memorialize: In Gedenkmal verwandeln + memorialized: Memorialisiert + memorialized_msg: "%{username} wurde erfolgreich in ein memorialisiertes Konto umgewandelt" moderation: active: Aktiv all: Alle @@ -158,10 +166,14 @@ de: public: Öffentlich push_subscription_expires: PuSH-Abonnement läuft aus redownload: Profil neu laden + redownloaded_msg: Profil von %{username} erfolgreich von Ursprung aktualisiert reject: Ablehnen reject_all: Alle ablehnen + rejected_msg: "%{username}'s Anmeldeantrag erfolgreich abgelehnt" remove_avatar: Profilbild entfernen remove_header: Titelbild entfernen + removed_avatar_msg: Profilbild von %{username} erfolgreich entfernt + removed_header_msg: "%{username}'s Titelbild wurde erfolgreich entfernt" resend_confirmation: already_confirmed: Diese_r Benutzer_in wurde bereits bestätigt send: Bestätigungs-E-Mail erneut senden @@ -178,6 +190,8 @@ de: search: Suche search_same_email_domain: Andere Benutzer mit der gleichen E-Mail-Domain search_same_ip: Andere Benutzer mit derselben IP + sensitive: NSFW + sensitized: Als NSFW markieren shared_inbox_url: Geteilte Posteingang-URL show: created_reports: Erstellte Meldungen @@ -187,13 +201,19 @@ de: statuses: Beiträge subscribe: Abonnieren suspended: Verbannt + suspension_irreversible: Die Daten dieses Kontos wurden unwiderruflich gelöscht. Du kannst das Konto aufheben, um es brauchbar zu machen, aber es wird keine Daten wiederherstellen, die es davor schon hatte. + suspension_reversible_hint_html: Das Konto wurde gesperrt und die Daten werden am %{date} vollständig gelöscht. Bis dahin kann das Konto ohne irgendwelche negativen Auswirkungen wiederhergestellt werden. Wenn du alle Daten des Kontos sofort entfernen möchtest, kannst du dies nachfolgend tun. time_in_queue: "%{time} in der Warteschlange" title: Konten unconfirmed_email: Unbestätigte E-Mail-Adresse + undo_sensitized: Nicht mehr als NSFW markieren undo_silenced: Stummschaltung aufheben undo_suspension: Verbannung aufheben + unsilenced_msg: "%{username}'s Konto erfolgreich freigegeben" unsubscribe: Abbestellen + unsuspended_msg: "%{username}'s Konto erfolgreich freigegeben" username: Profilname + view_domain: Übersicht für Domain anzeigen warn: Warnen web: Web whitelisted: Auf der Whitelist @@ -208,31 +228,36 @@ de: create_domain_allow: Domain erlauben create_domain_block: Domain blockieren create_email_domain_block: E-Mail-Domain-Block erstellen + create_ip_block: IP-Regel erstellen demote_user: Benutzer degradieren destroy_announcement: Ankündigung löschen destroy_custom_emoji: Eigene Emoji löschen destroy_domain_allow: Erlaube das Löschen von Domains destroy_domain_block: Domain-Blockade löschen destroy_email_domain_block: E-Mail-Domain-Blockade löschen + destroy_ip_block: IP-Regel löschen destroy_status: Beitrag löschen disable_2fa_user: 2FA deaktivieren disable_custom_emoji: Benutzerdefiniertes Emoji deaktivieren disable_user: Benutzer deaktivieren enable_custom_emoji: Benutzerdefiniertes Emoji aktivieren enable_user: Benutzer aktivieren - memorialize_account: Konto in ein Konto von einer verstorbenen Person umwandeln + memorialize_account: Account deaktivieren promote_user: Benutzer befördern remove_avatar_user: Profilbild entfernen reopen_report: Meldung wieder eröffnen reset_password_user: Passwort zurücksetzen resolve_report: Bericht lösen + sensitive_account: Markiere die Medien in deinem Konto als NSFW silence_account: Konto stummschalten suspend_account: Konto sperren - unassigned_report: Berichtszuweisung entfernen + unassigned_report: Meldung widerrufen + unsensitive_account: Markiere die Medien in deinem Konto nicht mehr als NSFW unsilence_account: Konto nicht mehr stummschalten unsuspend_account: Konto nicht mehr sperren update_announcement: Ankündigung aktualisieren update_custom_emoji: Benutzerdefiniertes Emoji aktualisieren + update_domain_block: Domain Block aktualisieren update_status: Beitrag aktualisieren actions: assigned_to_self_report: "%{name} hat sich die Meldung %{target} selbst zugewiesen" @@ -244,12 +269,14 @@ de: create_domain_allow: "%{name} hat die Domain %{target} gewhitelistet" create_domain_block: "%{name} hat die Domain %{target} blockiert" create_email_domain_block: "%{name} hat die E-Mail-Domain %{target} geblacklistet" + create_ip_block: "%{name} hat eine Regel für IP %{target} erstellt" demote_user: "%{name} stufte Benutzer_in %{target} herunter" destroy_announcement: "%{name} hat die neue Ankündigung %{target} gelöscht" destroy_custom_emoji: "%{name} zerstörte Emoji %{target}" destroy_domain_allow: "%{name} hat die Domain %{target} von der Whitelist entfernt" destroy_domain_block: "%{name} hat die Domain %{target} entblockt" destroy_email_domain_block: "%{name} hat die E-Mail-Domain %{target} gewhitelistet" + destroy_ip_block: "%{name} hat eine Regel für IP %{target} gelöscht" destroy_status: "%{name} hat einen Beitrag von %{target} entfernt" disable_2fa_user: "%{name} hat Zwei-Faktor-Anforderung für Benutzer_in %{target} deaktiviert" disable_custom_emoji: "%{name} hat das %{target} Emoji deaktiviert" @@ -262,13 +289,16 @@ de: reopen_report: "%{name} hat die Meldung %{target} wieder geöffnet" reset_password_user: "%{name} hat das Passwort von %{target} zurückgesetzt" resolve_report: "%{name} hat die Meldung %{target} bearbeitet" + sensitive_account: "%{name} markierte %{target}'s Medien als NSFW" silence_account: "%{name} hat das Konto von %{target} stummgeschaltet" suspend_account: "%{name} hat das Konto von %{target} verbannt" unassigned_report: "%{name} hat die Zuweisung der Meldung %{target} entfernt" + unsensitive_account: "%{name} markierte %{target}'s Medien nicht als NSFW" unsilence_account: "%{name} hat die Stummschaltung von %{target} aufgehoben" unsuspend_account: "%{name} hat die Verbannung von %{target} aufgehoben" update_announcement: "%{name} aktualisierte Ankündigung %{target}" update_custom_emoji: "%{name} hat das %{target} Emoji geändert" + update_domain_block: "%{name} hat den Domain-Block für %{target} aktualisiert" update_status: "%{name} hat einen Beitrag von %{target} aktualisiert" deleted_status: "(gelöschter Beitrag)" empty: Keine Protokolle gefunden. @@ -372,6 +402,8 @@ de: silence: Stummschaltung suspend: Sperre title: Neue Domain-Blockade + obfuscate: Domainname verschleiern + obfuscate_hint: Den Domainnamen in der Liste teilweise verschleiern, wenn die Liste der Domänenbeschränkungen aktiviert ist private_comment: Privater Kommentar private_comment_hint: Kommentar zu dieser Domain-Beschränkung für die interne Nutzung durch die Moderatoren. public_comment: Öffentlicher Kommentar @@ -411,6 +443,7 @@ de: instances: by_domain: Domain delivery_available: Zustellung funktioniert + empty: Keine Domains gefunden. known_accounts: one: "%{count} bekanntes Konto" other: "%{count} bekannte Konten" @@ -434,6 +467,21 @@ de: expired: Ausgelaufen title: Filter title: Einladungen + ip_blocks: + add_new: Regel erstellen + created_msg: Neue IP-Regel erfolgreich hinzugefügt + delete: Löschen + expires_in: + '1209600': 2 Wochen + '15778476': 6 Monate + '2629746': 1 Monat + '31556952': 1 Jahr + '86400': 1 Tag + '94670856': 3 Jahre + new: + title: Neue IP-Regel erstellen + no_ip_block_selected: Keine IP-Regeln wurden geändert, weil keine ausgewählt wurden + title: IP-Regeln pending_accounts: title: Ausstehende Konten (%{count}) relationships: @@ -473,6 +521,8 @@ de: comment: none: Kein created_at: Gemeldet + forwarded: Weitergeleitet + forwarded_to: Weitergeleitet an %{domain} mark_as_resolved: Als gelöst markieren mark_as_unresolved: Als ungelöst markieren notes: @@ -516,6 +566,7 @@ de: domain_blocks_rationale: title: Rationale anzeigen enable_bootstrap_timeline_accounts: + desc_html: Neue Benutzer automatisch den konfigurierten Konten folgen lassen, sodass ihr Home-Feed nicht leer startet title: Aktiviere die Option "Konten, denen Neu-Angemeldete automatisch folgen" hero: desc_html: Wird auf der Startseite angezeigt. Mindestens 600x100px sind empfohlen. Wenn es nicht gesetzt wurde, wird das Server-Thumbnail dafür verwendet @@ -527,8 +578,8 @@ de: desc_html: Domain-Namen, die der Server im Fediversum gefunden hat title: Veröffentliche entdeckte Server durch die API preview_sensitive_media: - desc_html: Linkvorschauen auf anderen Webseiten werden ein Vorschaubild anzeigen, obwohl die Medien als heikel gekennzeichnet sind - title: Heikle Medien im OpenGraph-Vorschau anzeigen + desc_html: Linkvorschauen auf anderen Webseiten werden ein Vorschaubild anzeigen, obwohl die Medien als NSFW markiert sind + title: NSFW-Medien in OpenGraph-Vorschau anzeigen profile_directory: desc_html: Erlaube Benutzer auffindbar zu sein title: Aktiviere Profilverzeichnis @@ -542,6 +593,9 @@ de: min_invite_role: disabled: Niemand title: Einladungen erlauben von + require_invite_text: + desc_html: Wenn eine Registrierung manuell genehmigt werden muss, mache den "Warum möchtest du beitreten?" Text eher obligatorisch als optional + title: Neue Benutzer müssen einen Einladungstext ausfüllen registrations_mode: modes: approved: Zustimmung benötigt zur Registrierung @@ -590,8 +644,8 @@ de: back_to_account: Zurück zum Konto batch: delete: Löschen - nsfw_off: Als nicht heikel markieren - nsfw_on: Als heikel markieren + nsfw_off: Als nicht NSFW markieren + nsfw_on: Als NSFW markieren deleted: Gelöscht failed_to_execute: Ausführen fehlgeschlagen media: @@ -652,7 +706,7 @@ de: body: Mastodon wurde von Freiwilligen übersetzt. guide_link: https://de.crowdin.com/project/mastodon guide_link_text: Jeder kann etwas dazu beitragen. - sensitive_content: Heikle Inhalte + sensitive_content: NSFW toot_layout: Beitragslayout application_mailer: notification_preferences: Ändere E-Mail-Einstellungen @@ -681,8 +735,11 @@ de: prefix_sign_up: Melde dich heute bei Mastodon an! suffix: Mit einem Konto kannst du Leuten folgen, Updates veröffentlichen und Nachrichten mit Benutzern von jedem Mastodon-Server austauschen und mehr! didnt_get_confirmation: Keine Bestätigungs-Mail erhalten? + dont_have_your_security_key: Hast du keinen Sicherheitsschlüssel? forgot_password: Passwort vergessen? invalid_reset_password_token: Das Token zum Zurücksetzen des Passworts ist ungültig oder abgelaufen. Bitte fordere ein neues an. + link_to_otp: Gib einen Zwei-Faktor-Code von deinem Handy oder einen Wiederherstellungscode ein + link_to_webauth: Verwende deinen Sicherheitsschlüssel login: Anmelden logout: Abmelden migrate_account: Ziehe zu einem anderen Konto um @@ -707,7 +764,9 @@ de: functional: Dein Konto ist voll funktionsfähig. pending: Deine Bewerbung wird von unseren Mitarbeitern noch überprüft. Dies kann einige Zeit dauern. Du erhältst eine E-Mail, wenn deine Bewerbung genehmigt wurde. redirecting_to: Dein Konto ist inaktiv, da es derzeit zu %{acct} umgeleitet wird. + too_fast: Formular zu schnell gesendet, versuchen Sie es erneut. trouble_logging_in: Schwierigkeiten beim Anmelden? + use_security_key: Sicherheitsschlüssel verwenden authorize_follow: already_following: Du folgst diesem Konto bereits already_requested: Du hast bereits eine Anfrage zum Folgen diesen Accounts versendet @@ -732,6 +791,7 @@ de: date: formats: default: "%d. %b %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -796,6 +856,7 @@ de: request: Dein Archiv anfragen size: Größe blocks: Du hast blockiert + bookmarks: Lesezeichen csv: CSV domain_blocks: Domainblockaden lists: Listen @@ -863,6 +924,8 @@ de: status: Verifizierungsstatus view_proof: Zeige Nachweis imports: + errors: + over_rows_processing_limit: enthält mehr als %{count} Zeilen modes: merge: Zusammenführen merge_long: Behalte existierende Datensätze und füge neue hinzu @@ -872,6 +935,7 @@ de: success: Deine Daten wurden erfolgreich hochgeladen und werden in Kürze verarbeitet types: blocking: Blockierliste + bookmarks: Lesezeichen domain_blocking: Domain-Blockliste following: Folgeliste muting: Stummschaltungsliste @@ -992,6 +1056,14 @@ de: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: Gib den von deiner Authentifizierungs-App generierten Code ein, um deine Anmeldung zu bestätigen + description_html: Wenn du <strong>Zwei-Faktor-Authentifizierung</strong> mit einer Authentifizierungs-App aktivierst, musst du, um dich anzumelden, im Besitz deines Handys sein, dass Tokens für dein Konto generiert. + enable: Aktivieren + instructions_html: "<strong>Scanne diesen QR-Code in Google Authenticator oder einer ähnlichen TOTP-App auf deinem Handy</strong>. Von nun an generiert diese App Tokens, die du beim Anmelden eingeben musst." + manual_instructions: 'Wenn du den QR-Code nicht scannen kannst und ihn manuell eingeben musst, ist hier das Klartext-Geheimnis:' + setup: Einrichten + wrong_code: Der eingegebene Code war ungültig! Sind die Serverzeit und die Gerätezeit korrekt? pagination: newer: Neuer next: Vorwärts @@ -1020,6 +1092,7 @@ de: relationships: activity: Kontoaktivität dormant: Inaktiv + follow_selected_followers: Ausgewählte Follower folgen followers: Folgende following: Folgt invited: Eingeladen @@ -1116,6 +1189,7 @@ de: profile: Profil relationships: Folgende und Gefolgte two_factor_authentication: Zwei-Faktor-Auth + webauthn_authentication: Sicherheitsschlüssel spam_check: spam_detected: Dies ist ein automatisierter Bericht. Es wurde Spam erkannt. statuses: @@ -1154,6 +1228,8 @@ de: other: "%{count} Stimmen" vote: Abstimmen show_more: Mehr anzeigen + show_newer: Neuere anzeigen + show_older: Ältere anzeigen show_thread: Zeige Konversation sign_in_to_participate: Melde dich an, um an der Konversation teilzuhaben title: '%{name}: "%{quote}"' @@ -1167,7 +1243,7 @@ de: stream_entries: pinned: Angehefteter Beitrag reblogged: teilte - sensitive_content: Heikle Inhalte + sensitive_content: NSFW tags: does_not_match_previous_name: entspricht nicht dem vorherigen Namen terms: @@ -1264,21 +1340,20 @@ de: default: "%d.%m.%Y %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Gib zur Bestätigung den Code ein, den deine Authenticator-App generiert hat - description_html: Wenn du <strong>Zwei-Faktor-Authentifizierung (2FA)</strong> aktivierst, wirst du dein Telefon zum Anmelden benötigen. Darauf werden Sicherheitscodes erzeugt, die du bei der Anmeldung eingeben musst. + add: Hinzufügen disable: Deaktivieren - enable: Aktivieren + disabled_success: Zwei-Faktor-Authentifizierung erfolgreich deaktiviert + edit: Bearbeiten enabled: Zwei-Faktor-Authentisierung ist aktiviert enabled_success: Zwei-Faktor-Authentisierung erfolgreich aktiviert generate_recovery_codes: Wiederherstellungscodes generieren - instructions_html: "<strong>Lies diesen QR-Code mit Google Authenticator oder einer ähnlichen TOTP-App auf deinem Telefon ein.</strong> Von nun an wird diese App Tokens generieren, die du beim Anmelden eingeben musst." lost_recovery_codes: Wiederherstellungscodes erlauben dir, wieder den Zugang zu deinem Konto zu erlangen, falls du dein Telefon verlieren solltest. Wenn du deine Wiederherstellungscodes verloren hast, kannst du sie hier neu generieren. Deine alten Wiederherstellungscodes werden damit ungültig gemacht. - manual_instructions: 'Wenn du den QR-Code nicht einlesen kannst und ihn manuell eingeben musst, ist hier das Klartext-Geheimnis:' + methods: Zwei-Faktor-Methoden + otp: Authentifizierungs-App recovery_codes: Wiederherstellungs-Codes sichern recovery_codes_regenerated: Wiederherstellungscodes erfolgreich neu generiert recovery_instructions_html: Wenn du den Zugang zu deinem Telefon verlieren solltest, kannst du einen untenstehenden Wiederherstellungscode benutzen, um wieder auf dein Konto zugreifen zu können. <strong>Bewahre die Wiederherstellungscodes gut auf.</strong> Du könntest sie beispielsweise ausdrucken und bei deinen restlichen wichtigen Dokumenten aufbewahren. - setup: Einrichten - wrong_code: Der eingegebene Code war ungültig! Stimmen Serverzeit und Gerätezeit? + webauthn: Sicherheitsschlüssel user_mailer: backup_ready: explanation: Du hast ein vollständiges Backup von deinem Mastodon-Konto angefragt. Es kann jetzt heruntergeladen werden! @@ -1293,6 +1368,7 @@ de: warning: explanation: disable: Solange dein Konto eingefroren ist, sind deine Benutzerdaten intakt; aber du kannst nichts tun, bis dein Konto entsperrt wurde. + sensitive: Deine hochgeladenen Mediendateien und verknüpften Medien werden als NSFW markiert. silence: Solange dein Konto limitiert ist, können nur die Leute, die dir bereits folgen, deine Beiträge auf dem Server sehen und es könnte sein, dass du von verschiedenen öffentlichen Listungen ausgeschlossen wirst. Andererseits können andere dir manuell folgen. suspend: Dein Konto wurde gesperrt und alle deine Beiträge und hochgeladenen Medien wurden unwiderruflich vom Server und anderen Servern, bei denen du Folgende hattest, gelöscht. get_in_touch: Du kannst auf diese E-Mail antworten, um mit dem Personal von %{instance} in Kontakt zu treten. @@ -1301,11 +1377,13 @@ de: subject: disable: Dein Konto %{acct} wurde eingefroren none: Warnung für %{acct} + sensitive: Die Medien deines Konto %{acct} wurden als NSFW markiert silence: Dein Konto %{acct} wurde limitiert suspend: Dein Konto %{acct} wurde gesperrt title: disable: Konto eingefroren none: Warnung + sensitive: Deine Medien wurden als NSFW markiert silence: Konto limitiert suspend: Konto gesperrt welcome: @@ -1326,9 +1404,11 @@ de: tips: Tipps title: Willkommen an Bord, %{name}! users: + blocked_email_provider: Dieser E-Mail-Anbieter ist nicht erlaubt follow_limit_reached: Du kannst nicht mehr als %{limit} Leuten folgen generic_access_help_html: Probleme beim Zugriff auf dein Konto? Du kannst dich mit %{email} in Verbindung setzen, um Hilfe zu erhalten invalid_email: Ungültige E-Mail-Adresse + invalid_email_mx: Die E-Mail-Adresse scheint nicht vorhanden zu sein invalid_otp_token: Ungültiger Zwei-Faktor-Authentisierungs-Code invalid_sign_in_token: Ungültiger Sicherheitscode otp_lost_help_html: Wenn Du beides nicht mehr weißt, melde Dich bei uns unter der E-Mailadresse %{email} @@ -1338,3 +1418,20 @@ de: verification: explanation_html: 'Du kannst <strong>bestätigen, dass die Links in deinen Profil-Metadaten dir gehören</strong>. Dafür muss die verlinkte Website einen Link zurück auf dein Mastodon-Profil enthalten. Dieser Link <strong>muss</strong> ein <code>rel="me"</code>-Attribut enthalten. Der Linktext ist dabei egal. Hier ist ein Beispiel:' verification: Verifizierung + webauthn_credentials: + add: Sicherheitsschlüssel hinzufügen + create: + error: Beim Hinzufügen des Sicherheitsschlüssels ist ein Fehler aufgetreten. Bitte versuche es erneut. + success: Dein Sicherheitsschlüssel wurde erfolgreich hinzugefügt. + delete: Löschen + delete_confirmation: Bist du sicher, dass du diesen Sicherheitsschlüssel löschen möchtest? + description_html: Wenn du die <strong>Authentifizierung mit Sicherheitsschlüssel</strong> aktivierst, musst du einen deiner Sicherheitsschlüssel verwenden, um dich anmelden zu können. + destroy: + error: Es gab ein Problem beim Löschen deines Sicherheitsschlüssels. Bitte versuche es erneut. + success: Dein Sicherheitsschlüssel wurde erfolgreich gelöscht. + invalid_credential: Ungültiger Sicherheitsschlüssel + nickname_hint: Gib den Spitznamen deines neuen Sicherheitsschlüssels ein + not_enabled: Du hast WebAuthn noch nicht aktiviert + not_supported: Dieser Browser unterstützt keine Sicherheitsschlüssel + otp_required: Um Sicherheitsschlüssel zu verwenden, aktiviere zuerst die Zwei-Faktor-Authentifizierung. + registered_on: Registriert am %{date} diff --git a/config/locales/devise.ca.yml b/config/locales/devise.ca.yml index cca8764eadb40845a2c5ad9bea2a8e4facefe17f..e1600bc6ac228f4556d74963c7d126febd811592 100644 --- a/config/locales/devise.ca.yml +++ b/config/locales/devise.ca.yml @@ -53,7 +53,7 @@ ca: subject: 'Mastodon: autenticació de dos factors desactivada' title: 2FA desactivat two_factor_enabled: - explanation: L'autenticació de dos factors ha estat habilitada pel teu compte. Un token generat pel emparellat TOTP app serà requerit per a iniciar sessió. + explanation: L'autenticació de dos factors ha estat habilitada pel teu compte. Un token generat per l'aplicació d'emparellat TOTP serà requerit per a iniciar sessió. subject: 'Mastodon: autenticació de dos factors activada' title: 2FA activat two_factor_recovery_codes_changed: @@ -62,9 +62,26 @@ ca: title: 2FA codis de recuperació canviats unlock_instructions: subject: 'Mastodon: Instruccions per a desbloquejar' + webauthn_credential: + added: + explanation: La següent clau de seguretat s'ha afegit al teu compte + subject: 'Mastodon: Nova clau de seguretat' + title: S'ha afegit una nova clau de seguretat + deleted: + explanation: La següent clau de seguretat s'ha esborrat del teu compte + subject: 'Mastodon: clau de seguretat esborrada' + title: Una de les teves claus de seguretat ha estat esborrada + webauthn_disabled: + explanation: S'ha desactivat l'autenticació amb claus de seguretat per al teu compte. L'inici de sessió és ara possible emprant només el token generat per l'aplicació TOTP. + subject: 'Mastodon: S''ha desactivat l''autenticació amb claus de seguretat' + title: Claus de seguretat desactivades + webauthn_enabled: + explanation: S'ha activat l'autenticació amb claus de seguretat. La teva clau de seguretat por ser emprada per a iniciar sessió. + subject: 'Mastodon: Autenticació amb clau de seguretat activada' + title: Claus de seguretat activades omniauth_callbacks: - failure: No podem autentificar-te des de %{kind} degut a "%{reason}". - success: Autentificat amb èxit des del compte %{kind}. + failure: No podem autenticar-te des de %{kind} degut a "%{reason}". + success: Autenticat amb èxit des del compte %{kind}. passwords: no_token: No pots accedir a aquesta pà gina sense provenir des del correu de restabliment de la contrasenya. Si vens des del correu de restabliment de contrasenya, assegura't que està s emprant l'adreça completa proporcionada. send_instructions: Si el teu correu electrònic existeix en la nostra base de dades, rebrà s en pocs minuts un enllaç de restabliment de contrasenya en l'adreça de correu. Si us plau verifica la teva carpeta de correu brossa if no rebut aquest correu. diff --git a/config/locales/devise.co.yml b/config/locales/devise.co.yml index c9511d14d14f245490072202ce8d84b63d0626c8..8409cfad9b2b8291c0ae213c130f4d86b5c291a7 100644 --- a/config/locales/devise.co.yml +++ b/config/locales/devise.co.yml @@ -60,6 +60,23 @@ co: title: Cambiamentu di i codici di ricuperazione d'A2F unlock_instructions: subject: 'Mastodon: Riapre u contu' + webauthn_credential: + added: + explanation: A chjave di sicurità quì sottu hè stata aghjunta à u vostru contu + subject: 'Mastodon: Nova chjave di sicurità ' + title: Una nova chjave di sicurità hè stata aghjunta + deleted: + explanation: A chjave di sicurità quì sottu hè stata sguassata di u vostru contu + subject: 'Mastodon: Chjave di sicurità sguassata' + title: Una di e vostre chjave di sicurità hè stata sguassata + webauthn_disabled: + explanation: L'autentificazione cù una chjave di sicurità hè stata disattivata per u vostru contu. Avà pudete solu cunnettavi cù u codice di cunnessione generatu da l'applicazione TOTP appaghjata. + subject: 'Mastodon: Autentificazione cù chjave di sicurità disattivata' + title: Chjave di sicurità disattivate + webauthn_enabled: + explanation: L'autentificazione cù una chjave di sicurità hè stata attivata per u vostru contu. Avà a vostra chjave pò esse utilizata per cunnettavi. + subject: 'Mastodon: Identificazione cù chjave di sicurità attivata' + title: Chjave di sicurità attivate omniauth_callbacks: failure: Ùn pudemu micca cunnettavi da %{kind} perchè "%{reason}". success: Vi site cunnettatu·a da %{kind}. @@ -94,5 +111,5 @@ co: not_found: ùn hè micca statu trovu not_locked: ùn era micca chjosu not_saved: - one: 'Un prublemu hà impeditu a cunservazione di stu (sta) %{resource}:' - other: "%{count} prublemi anu impeditu a cunservazione di stu (sta) %{resource} :" + one: 'Un prublemu hà impeditu a cunservazione di stu/sta %{resource}:' + other: "%{count} prublemi anu impeditu a cunservazione di stu/sta %{resource} :" diff --git a/config/locales/devise.cs.yml b/config/locales/devise.cs.yml index 743a1bfd5b679e8450d08ff0069bb5ba933c35c6..56ec4637dfae5f309fd1d2a05cd862062582b90c 100644 --- a/config/locales/devise.cs.yml +++ b/config/locales/devise.cs.yml @@ -60,6 +60,19 @@ cs: title: Záložnà kódy pro 2FA zmÄ›nÄ›ny unlock_instructions: subject: 'Mastodon: Instrukce pro odemÄenà úÄtu' + webauthn_credential: + added: + explanation: NásledujÃcà bezpeÄnostnà klÃÄ byl pÅ™idán k vaÅ¡emu úÄtu + subject: 'Mastodon: Nový bezpeÄnostnà klÃÄ' + title: Byl pÅ™idán nový bezpeÄnostnà klÃÄ + deleted: + explanation: NásledujÃcà bezpeÄnostnà klÃÄ byl odstranÄ›n z vaÅ¡eho úÄtu + subject: 'Mastodon: BezpeÄnostnà klÃÄ byl smazán' + title: Jeden z vaÅ¡ich bezpeÄnostnÃch klÃÄů byl smazán + webauthn_disabled: + title: BezpeÄnostnà klÃÄe zakázány + webauthn_enabled: + title: BezpeÄnostnà klÃÄe povoleny omniauth_callbacks: failure: Nelze vás ověřit z %{kind}, protože „%{reason}“. success: ÚspěšnÄ› ověřeno z úÄtu %{kind}. diff --git a/config/locales/devise.da.yml b/config/locales/devise.da.yml index 75a03593550cae3a22dd6ef30615b4dc5daf27d4..c23d2bbbfdd360bf4e7d0dc61a877f1b1a29f44b 100644 --- a/config/locales/devise.da.yml +++ b/config/locales/devise.da.yml @@ -60,6 +60,17 @@ da: title: 2FA gendannelseskoder er ændret unlock_instructions: subject: 'Mastodon: Instruktioner for oplÃ¥sning' + webauthn_credential: + added: + subject: 'Mastodon: Ny sikkerhedsnøgle' + title: En ny sikkerhedsnøgle er blevet tilføjet + deleted: + subject: 'Mastodon: Sikkerhedsnøgle slettet' + title: En af dine sikkerhedsnøgler er blevet slettet + webauthn_disabled: + title: Sikkerhedsnøgler deaktiveret + webauthn_enabled: + title: Sikkerhedsnøgler aktiveret omniauth_callbacks: failure: Kunne ikke godkende dig fra %{kind} fordi "%{reason}". success: Godkendelse fra %{kind} konto lykkedes. diff --git a/config/locales/devise.de.yml b/config/locales/devise.de.yml index c2eb057f53ba8cd7db6855439cd727c15a50b404..0512ca12956dbc031e0f2e1c7fd50765caeb4cd8 100644 --- a/config/locales/devise.de.yml +++ b/config/locales/devise.de.yml @@ -20,7 +20,7 @@ de: confirmation_instructions: action: E-Mail-Adresse verifizieren action_with_app: Bestätigen und zu %{app} zurückkehren - explanation: Du hast einen Account auf %{host} mit dieser E-Mail-Adresse erstellt. Du bist nur noch einen Klick weit entfernt von der Aktivierung. Wenn du das nicht warst, kannst du diese E-Mail ignorieren. + explanation: Du hast einen Account auf %{host} mit dieser E-Mail-Adresse erstellt. Du bist nur noch einen Klick weit von der Aktivierung entfernt. Wenn du das nicht warst, kannst du diese E-Mail ignorieren. explanation_when_pending: Du hast dich für eine Einladung bei %{host} mit dieser E-Mailadresse beworben. Sobald du deine E-Mailadresse bestätigst werden wir deine Anfrage überprüfen. Du kannst dich in dieser Zeit nicht anmelden. Wenn deine Anfrage abgelehnt wird, werden deine Daten entfernt, also wird keine weitere Handlung benötigt. Wenn du das nicht warst kannst du diese E-Mail ignorieren. extra_html: Bitte lies auch die <a href="%{terms_path}">Regeln des Servers</a> und <a href="%{policy_path}">unsere Nutzungsbedingungen</a>. subject: 'Mastodon: Bestätigung deines Kontos bei %{instance}' @@ -60,6 +60,23 @@ de: title: 2FA Wiederherstellungscodes geändert unlock_instructions: subject: 'Mastodon: Konto entsperren' + webauthn_credential: + added: + explanation: Der folgende Sicherheitsschlüssel wurde zu deinem Konto hinzugefügt + subject: 'Mastodon: Neuer Sicherheitsschlüssel' + title: Ein neuer Sicherheitsschlüssel wurde hinzugefügt + deleted: + explanation: Der folgende Sicherheitsschlüssel wurde aus deinem Konto gelöscht + subject: 'Mastodon: Sicherheitsschlüssel gelöscht' + title: Einer deiner Sicherheitsschlüssel wurde gelöscht + webauthn_disabled: + explanation: Die Authentifizierung mit Sicherheitsschlüssel wurde für dein Konto deaktiviert. Der Login ist nun nur mit dem Token möglich, der von der eingerichteten TOTP-App generiert wird. + subject: 'Mastodon: Authentifizierung mit Sicherheitsschlüssel deaktiviert' + title: Sicherheitsschlüssel deaktiviert + webauthn_enabled: + explanation: Die Authentifizierung mit einem Sicherheitsschlüssel wurde für dein Konto aktiviert. Dein Sicherheitsschlüssel kann nun für die Anmeldung verwendet werden. + subject: 'Mastodon: Authentifizierung mit Sicherheitsschlüssel aktiviert' + title: Sicherheitsschlüssel aktiviert omniauth_callbacks: failure: Du konntest nicht mit deinem %{kind}-Konto angemeldet werden, weil »%{reason}«. success: Du hast dich erfolgreich mit deinem %{kind}-Konto angemeldet. diff --git a/config/locales/devise.el.yml b/config/locales/devise.el.yml index 7eb064e5d95eea7c6ccdcbcf3e4801e9ada19ce4..ba3ee59fab366c9520a619e4758ecdd327c3cfb7 100644 --- a/config/locales/devise.el.yml +++ b/config/locales/devise.el.yml @@ -60,6 +60,23 @@ el: title: Οι κωδικοί ανάκτησης επαλήθευσης 2 βημάτων (2FA) άλλαξαν unlock_instructions: subject: 'Mastodon: Οδηγίες ξεκλειδώματος' + webauthn_credential: + added: + explanation: Î ÏοστÎθηκε το ακόλουθο κλειδί ασφαλείας στο λογαÏιασμό σου + subject: 'Mastodon: ÎÎο κλειδί ασφαλείας' + title: Î ÏοστÎθηκε νÎο κλειδί ασφαλείας + deleted: + explanation: ΔιαγÏάφηκε το ακόλουθο κλειδί ασφαλείας από το λογαÏιασμό σου + subject: 'Mastodon: ΔιαγÏάφηκε Îνα κλειδί ασφαλείας' + title: Ένα από τα κλειδιά ασφαλείας σου διαγÏάφηκε + webauthn_disabled: + explanation: Η επαλήθευση με κλειδί ασφαλείας Îχει απενεÏγοποιηθεί για τον λογαÏιασμό σας. Η σÏνδεση είναι τώÏα εφικτή μόνο με τη χÏήση ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï Ï€Î¿Ï… δημιουÏγημÎνου με την συνδεδεμÎνη εφαÏμογή TOTP. + subject: 'Mastodon: Η αυθεντικοποίηση με χÏήση κλειδιών ασφαλείας απενεÏγοποιήθηκε' + title: Τα κλειδιά ασφαλείας απενεÏγοποιήθηκαν + webauthn_enabled: + explanation: Η επαλήθευση με κλειδί ασφαλείας Îχει ενεÏγοποιηθεί για τον λογαÏιασμό σας. ΜποÏείτε να το χÏησιμοποιήσετε για να συνδεθείτε. + subject: 'Mastodon: ΕνεÏγοποιήθηκε η επαλήθευση με κλειδί ασφαλείας' + title: Τα κλειδιά ασφαλείας ενεÏγοποιήθηκαν omniauth_callbacks: failure: Δεν μπόÏεσαμε να σε πιστοποιήσουμε μÎσω %{kind} γιατί "%{reason}". success: ΕπιτυχημÎνη πιστοποίηση μÎσω %{kind} λογαÏιασμοÏ. diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 726d2426a77804095201b1ed845083c8d2d1ccec..a3f2c5796a02fb4a7b6435457fec7b895f5852ae 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -60,6 +60,23 @@ en: title: 2FA recovery codes changed unlock_instructions: subject: 'Mastodon: Unlock instructions' + webauthn_credential: + added: + explanation: The following security key has been added to your account + subject: 'Mastodon: New security key' + title: A new security key has been added + deleted: + explanation: The following security key has been deleted from your account + subject: 'Mastodon: Security key deleted' + title: One of you security keys has been deleted + webauthn_disabled: + explanation: Authentication with security keys has been disabled for your account. Login is now possible using only the token generated by the paired TOTP app. + subject: 'Mastodon: Authentication with security keys disabled' + title: Security keys disabled + webauthn_enabled: + explanation: Security key authentication has been enabled for your account. Your security key can now be used for login. + subject: 'Mastodon: Security key authentication enabled' + title: Security keys enabled omniauth_callbacks: failure: Could not authenticate you from %{kind} because "%{reason}". success: Successfully authenticated from %{kind} account. diff --git a/config/locales/devise.es-AR.yml b/config/locales/devise.es-AR.yml index bb229e8f5d10d39e5a3825c0f936b1e23ac3d01a..d4dc4b7a7427fc6b18e7ffd4c945fd7fa1cc20f1 100644 --- a/config/locales/devise.es-AR.yml +++ b/config/locales/devise.es-AR.yml @@ -39,7 +39,7 @@ es-AR: explanation: Confirmá la nueva dirección para cambiar tu correo electrónico. extra: Si no pediste este cambio, por favor, ignorá este mensaje. No se cambiará la dirección de correo electrónico de tu cuenta de Mastodon hasta que no accedas al enlace de arriba. subject: 'Mastodon: confirmar correo electrónico para %{instance}' - title: Verifique dirección de correo electrónico + title: Verificar dirección de correo electrónico reset_password_instructions: action: Cambiar contraseña explanation: Pediste una nueva contraseña para tu cuenta. @@ -60,6 +60,23 @@ es-AR: title: Códigos de recuperación 2FA cambiados unlock_instructions: subject: 'Mastodon: instrucciones de desbloqueo' + webauthn_credential: + added: + explanation: Se agregó la siguiente llave de seguridad a tu cuenta + subject: 'Mastodon: nueva llave de seguridad' + title: Se agregó una nueva llave de seguridad + deleted: + explanation: Se eliminó la siguiente llave de seguridad de tu cuenta + subject: 'Mastodon: llave de seguridad eliminada' + title: Se eliminó una de tus llaves de seguridad + webauthn_disabled: + explanation: Se deshabilitó la autenticación con llaves de seguridad en tu cuenta. El inicio de sesión ahora es posible usando sólo la clave generada por la aplicación TOTP asociada. + subject: 'Mastodon: autenticación con llaves de seguridad, deshabilitada' + title: Llaves de seguridad deshabilitadas + webauthn_enabled: + explanation: Se habilitó la autenticación de llave de seguridad en tu cuenta. Ahora tu llave de seguridad se puede usar para iniciar sesión. + subject: 'Mastodon: autenticación con llaves de seguridad, habilitada' + title: Llaves de seguridad habilitadas omniauth_callbacks: failure: 'No se te pudo autenticar desde %{kind} debido a esto: "%{reason}".' success: Se autenticó exitosamente para la cuenta %{kind}. @@ -67,7 +84,7 @@ es-AR: no_token: No podés acceder a esta página sin venir desde un correo electrónico destinado al cambio de contraseña. Si venÃs desde dicho mensaje, por favor, asegurate que usaste toda la dirección web ofrecida. send_instructions: Si tu dirección de correo electrónico existe en nuestra base de datos, en unos minutos, vas a recibir un correo electrónico con un enlace para cambiar tu contraseña. Si pasa el tiempo y no recibiste ningún mensaje, por favor, revisá tu carpeta de correo basura / no deseado / spam. send_paranoid_instructions: Si tu dirección de correo electrónico existe en nuestra base de datos, en unos minutos, vas a recibir un correo electrónico con un enlace para cambiar tu contraseña. Si pasa el tiempo y no recibiste ningún mensaje, por favor, revisá tu carpeta de correo basura / no deseado / spam. - updated: Se cambió existosamente tu contraseña. Ya iniciaste sesión. + updated: Se cambió exitosamente tu contraseña. Ya iniciaste sesión. updated_not_active: Se cambió exitosamente tu contraseña. registrations: destroyed: "¡Chauchas! Se canceló exitosamente tu cuenta. Esperamos verte pronto de nuevo." diff --git a/config/locales/devise.es.yml b/config/locales/devise.es.yml index 80d4380923339e75cf59b583431585a61f02e8f8..11ec46594238d7b6f5d700379f80f8102171c07f 100644 --- a/config/locales/devise.es.yml +++ b/config/locales/devise.es.yml @@ -60,6 +60,23 @@ es: title: Códigos de recuperación 2FA cambiados unlock_instructions: subject: 'Mastodon: Instrucciones para desbloquear' + webauthn_credential: + added: + explanation: La siguiente clave de seguridad ha sido añadida a su cuenta + subject: 'Mastodon: Nueva clave de seguridad' + title: Se agregó una nueva clave de seguridad + deleted: + explanation: La siguiente clave de seguridad ha sido eliminada de su cuenta + subject: 'Mastodon: Clave de seguridad eliminada' + title: Una de sus claves de seguridad ha sido eliminada + webauthn_disabled: + explanation: La autenticación con claves de seguridad ha sido desactivada para tu cuenta. El inicio de sesión es ahora posible únicamente utilizando el token generado por la aplicación emparejada TOTP. + subject: 'Mastodon: Autenticación con claves de seguridad desactivada' + title: Claves de seguridad desactivadas + webauthn_enabled: + explanation: La autenticación con clave de seguridad ha sido habilitada para su cuenta. Su clave de seguridad ahora puede ser usada para iniciar sesión. + subject: 'Mastodon: Autenticación con clave de seguridad activada' + title: Claves de seguridad activadas omniauth_callbacks: failure: No podemos autentificarle desde %{kind} debido a "%{reason}". success: Autentificado con éxito desde la cuenta %{kind} . diff --git a/config/locales/devise.fa.yml b/config/locales/devise.fa.yml index 753da6b9ce4bf38f15c42904236c92b336d64ccf..c13df99892f16a1eca44b0084e04586a49edf2f0 100644 --- a/config/locales/devise.fa.yml +++ b/config/locales/devise.fa.yml @@ -60,6 +60,23 @@ fa: title: کدهای بازیابی تأیید هویت دو مرØÙ„ه‌ای عوض شده‌اند unlock_instructions: subject: 'ماستودون: دستورالعمل‌های Ù‚Ùل‌گشایی' + webauthn_credential: + added: + explanation: کلید امنیتی زیر به ØØ³Ø§Ø¨ØªØ§Ù† Ø§ÙØ²ÙˆØ¯Ù‡ شد + subject: 'ماستودون: کلید امنیتی جدید' + title: کلید امنیتی جدیدی Ø§ÙØ²ÙˆØ¯Ù‡ شد + deleted: + explanation: کلید امنیتی زیر از ØØ³Ø§Ø¨ØªØ§Ù† ØØ°Ù شد + subject: 'ماستودون: کلید امنیتی ØØ°Ù شد' + title: یکی از کلیدهای امنیتیتان ØØ°Ù شد + webauthn_disabled: + explanation: تأیید هویت با کلیدهای امنیتی برای ØØ³Ø§Ø¨ØªØ§Ù† از کار Ø§ÙØªØ§Ø¯Ù‡ است. ورود اکنون Ùقط با ژتون ایجاد شده با کارهٔ TOTP Ø¬ÙØªâ€ŒØ´Ø¯Ù‡ امکان‌پذیر است. + subject: 'ماستودون: تأیید هویت با کلیدهای امنیتی از کار Ø§ÙØªØ§Ø¯' + title: کلیدهای امنیتی از کار Ø§ÙØªØ§Ø¯Ù†Ø¯ + webauthn_enabled: + explanation: تأیید هویت با کلید امنیتی برای ØØ³Ø§Ø¨ØªØ§Ù† به کار Ø§ÙØªØ§Ø¯Ù‡ است. اکنون کلید امنیتیتان می‌تواند برای ورود Ø§Ø³ØªÙØ§Ø¯Ù‡ شود. + subject: 'ماستودون: تأیید هویت با کلید امنیتی به کار Ø§ÙØªØ§Ø¯' + title: کلیدهای امنیتی به کار Ø§ÙØªØ§Ø¯Ù†Ø¯ omniauth_callbacks: failure: تآیید هویتتان از %{kind} نتوانست انجام شود چرا Ú©Ù‡ «%{reason}». success: تأیید هویت از ØØ³Ø§Ø¨ %{kind} با موÙقیت انجام شد. diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml index 3edd348e673ddab8923ae59e7f4831b3c37cdc3e..b918b7fb2c140207c882bfc79f25401c4912fbb7 100644 --- a/config/locales/devise.fr.yml +++ b/config/locales/devise.fr.yml @@ -60,6 +60,23 @@ fr: title: Codes de récupération 2FA modifiés unlock_instructions: subject: 'Mastodon : Instructions pour déverrouiller votre compte' + webauthn_credential: + added: + explanation: La clé de sécurité suivante a été ajoutée à votre compte + subject: 'Mastodon: Nouvelle clé de sécurité' + title: Une nouvelle clé de sécurité a été ajoutée + deleted: + explanation: La clé de sécurité suivante a été supprimée de votre compte + subject: 'Mastodon: Clé de sécurité supprimée' + title: Une de vos clés de sécurité a été supprimée + webauthn_disabled: + explanation: L'authentification avec les clés de sécurité a été désactivée pour votre compte. La connexion est maintenant possible en utilisant uniquement le jeton généré par l'application TOTP appairée. + subject: 'Mastodon: Authentification avec clés de sécurité désactivée' + title: Clés de sécurité désactivées + webauthn_enabled: + explanation: L'authentification par clé de sécurité a été activée pour votre compte. Votre clé de sécurité peut maintenant être utilisée pour vous connecter. + subject: 'Mastodon: Authentification de la clé de sécurité activée' + title: Clés de sécurité activées omniauth_callbacks: failure: 'Nous n’avons pas pu vous authentifier via %{kind} : ''%{reason}''.' success: Authentifié avec succès via %{kind}. diff --git a/config/locales/devise.gl.yml b/config/locales/devise.gl.yml index f2eb2b77b1413e669b6bab73de1e844c6ddf8df3..6c8718f28cbed31d04f94884eb3cbba4077b531c 100644 --- a/config/locales/devise.gl.yml +++ b/config/locales/devise.gl.yml @@ -19,7 +19,7 @@ gl: mailer: confirmation_instructions: action: Verificar o enderezo de email - action_with_app: Confirmar e voltar a %{app} + action_with_app: Confirmar e volver a %{app} explanation: Creaches unha conta en %{host} con este enderezo de email. Estás a un clic de activala. Se non foches ti o que fixeches este rexisto, por favor ignora esta mensaxe. explanation_when_pending: Solicitaches un convite para %{host} con este enderezo de email. Logo de que confirmes o teu enderezo de email, imos revisar a túa inscrición. Podes iniciar sesión para mudar os teus datos ou eliminar a túa conta, mais non poderás aceder á meirande parte das funcións até que a túa conta sexa aprobada. Se a túa inscrición for rexeitada, os teus datos serán eliminados, polo que non será necesaria calquera acción adicional da túa parte. Se non solicitaches este convite, por favor, ignora este correo. extra_html: Por favor, le <a href="%{terms_path}">as regras do servidor</a> e os <a href="%{policy_path}">nosos termos do servizo</a>. @@ -60,6 +60,23 @@ gl: title: Códigos de recuperación 2FA mudados unlock_instructions: subject: 'Mastodon: Instrucións para desbloquear' + webauthn_credential: + added: + explanation: Engadeuse a seguinte chave de seguridade á túa conta + subject: 'Mastodon: Nova chave de seguridade' + title: Engadeuse unha nova chave de seguridade + deleted: + explanation: Eliminouse a seguinte chave de seguridade da túa conta + subject: 'Mastodon: Chave de seguridade eliminada' + title: Eliminouse unha das túas chaves de seguridade + webauthn_disabled: + explanation: Desactivouse para a túa conta a autenticación con chaves de seguridade. Agora a conexión é posible usando só o token creado pola app TOTP emparellada. + subject: 'Mastodon: Desactivouse a autenticación con chave de seguridade' + title: Chaves de seguridade desactivadas + webauthn_enabled: + explanation: Activouse para a conta a autenticación con chave de seguridade. Xa podes usar a chave de seguridade para contectar. + subject: 'Mastodon: Autenticación con chave de seguridade activada' + title: Chaves de seguridade activas omniauth_callbacks: failure: Non foi posÃbel autenticar %{kind} porque "%{reason}". success: Autenticado con éxito na conta %{kind}. diff --git a/config/locales/devise.hi.yml b/config/locales/devise.hi.yml index d758a5b5357d76effdf363eeb2c8e0dfb231c4aa..62048c9f5d09d186c5cec43b291a134511435f74 100644 --- a/config/locales/devise.hi.yml +++ b/config/locales/devise.hi.yml @@ -1 +1,12 @@ +--- hi: + devise: + confirmations: + confirmed: आपका ईमेल पता का सफलतापूरà¥à¤µà¤• पà¥à¤·à¥à¤Ÿà¤¿ कर लिया गया था + failure: + already_authenticated: आप पहले से ही साइन इन है| + inactive: आपका खाता सकà¥à¤°à¤¿à¤¯ नहीं है! + locked: आपके अकाउंट को बà¥à¤²à¥‰à¤• किया गया है। + mailer: + email_changed: + title: नया ईमेल पता diff --git a/config/locales/devise.hr.yml b/config/locales/devise.hr.yml index e0c569ceed8304271cb57771d5cb939be9ed06bf..235e354140fca10683d636daf4878ee9a4be2759 100644 --- a/config/locales/devise.hr.yml +++ b/config/locales/devise.hr.yml @@ -2,50 +2,56 @@ hr: devise: confirmations: - confirmed: Tvoja email adresa je uspjeÅ¡no potvrÄ‘ena. - send_instructions: Primit ćeÅ¡ email sa uputama kako potvrditi svoju email adresu za nekoliko minuta. - send_paranoid_instructions: Ako tvoja email adresa postoji u naÅ¡oj bazi podataka, primit ćeÅ¡ email sa uputama kako ju potvrditi za nekoliko minuta. + confirmed: VaÅ¡a adresa e-poÅ¡te uspjeÅ¡no je potvrÄ‘ena. + send_instructions: Za nekoliko minuta primit ćete e-poÅ¡tu s uputama kako potvrditi VaÅ¡u adresu e-poÅ¡te. Molimo pogledajte VaÅ¡u mapu s neželjenom poÅ¡tom, ako niste primili ovu e-poÅ¡tu. + send_paranoid_instructions: Ako VaÅ¡a adresa e-poÅ¡te postoji u naÅ¡oj bazi podataka, za nekoliko minuta primit ćete e-poÅ¡tu s uputama kako ju potvrditi. Molimo provjerite mapu s neželjenom poÅ¡tom, ako niste primili ovu e-poÅ¡tu. mailer: confirmation_instructions: - subject: 'Mastodon: Upute za potvrÄ‘ivanje %{instance}' + action: Potvrdi adresu e-poÅ¡te + action_with_app: Potvrdi i vrati se na %{app} + subject: 'Mastodon: upute za potvrÄ‘ivanje za %{instance}' + title: Potvrdi adresu e-poÅ¡te email_changed: - subject: 'Mastodon: Email adresa je promijenjena' - title: Nova email adresa + subject: 'Mastodon: adresa e-poÅ¡te je promijenjena' + title: Nova adresa e-poÅ¡te password_change: - subject: 'Mastodon: Lozinka je promijenjena' + subject: 'Mastodon: lozinka je promijenjena' reset_password_instructions: - subject: 'Mastodon: Upute za resetiranje lozinke' + subject: 'Mastodon: upute za ponovno postavljanje lozinke' + title: Ponovno postavljanje lozinke + two_factor_disabled: + title: 2FA je onemogućen unlock_instructions: - subject: 'Mastodon: Upute za otkljuÄavanje' + subject: 'Mastodon: upute za otkljuÄavanje' omniauth_callbacks: - failure: Ne možemo te autentificirati sa %{kind} zbog "%{reason}". - success: UspjeÅ¡no autentificiran sa %{kind} raÄuna. + failure: Ne možemo Vas autentificirati s %{kind} zbog "%{reason}". + success: UspjeÅ¡no ste autentificirani s raÄunom na %{kind}. passwords: - no_token: Ne možeÅ¡ pristupiti ovoj stranici bez dolaženja sa emaila za resetiranje lozinke. Ako dolaziÅ¡ sa tog emaila, pazi da koristiÅ¡ potpuni link koji ti je dan. - send_instructions: Primit ćeÅ¡ email sa uputama kako resetirati svoju lozinku za nekoliko minuta. - send_paranoid_instructions: Ako tvoja email adresa postoji u naÅ¡oj bazi podataka, primit ćeÅ¡ link za povrat lozinke na svoju email adresu za nekoliko minuta. - updated: Tvoja lozinka je uspjeÅ¡no izmijenjena. Sada si prijavljen. - updated_not_active: Toja lozinka je uspjeÅ¡no izmijenjena. + no_token: Ovoj stranici ne možete pristupiti, ako ne stižete iz e-poÅ¡te za ponovno postavljanje lozinke. Ako dolazite iz e-poÅ¡te za ponovno postavljanje lozinke, molimo budite sigurni da koristite puni URL koji ste primili. + send_instructions: Ako VaÅ¡a adresa e-poÅ¡te postoji u naÅ¡oj bazi podataka, za nekoliko minuta primit ćete poveznicu za oporavak lozinke. Molimo provjerite mapu s neželjenom poÅ¡tom, ako niste primili ovu e-poÅ¡tu. + send_paranoid_instructions: Ako VaÅ¡a adresa e-poÅ¡te postoji u naÅ¡oj bazi podataka, za nekoliko minuta primit ćete e-poÅ¡tu s poveznicom za oporavak lozinke. Molimo provjerite mapu s neželjenom poÅ¡tom, ako niste primili ovu e-poÅ¡tu. + updated: VaÅ¡a lozinka uspjeÅ¡no je promijenjena. Sada ste prijavljeni. + updated_not_active: VaÅ¡a lozinka uspjeÅ¡no je promijenjena. registrations: - destroyed: Zbogom! Tvoj raÄun je uspjeÅ¡no otkazan. Nadamo se da ćemo te vidjeti ponovo. - signed_up: Dobro doÅ¡ao! UspjeÅ¡no si se prijavio. - signed_up_but_inactive: UspjeÅ¡no si se registrirao. No, ne možeÅ¡ se prijaviti, jer ti raÄun joÅ¡ nije aktiviran. - signed_up_but_locked: UspjeÅ¡no si se registrirao. No, ne možeÅ¡ se prijaviti jer je tvoj raÄun zakljuÄan. - signed_up_but_unconfirmed: Poruka sa linkom za potvrÄ‘ivanje je poslana na tvoju email adresu. Molimo, slijedi link kako bi tvoj raÄun bio aktiviran. - update_needs_confirmation: Tvoj raÄun je uspjeÅ¡no ažuriran, ali trebamo provjeriti tvoju novu email adresu. Molimo, provjeri svoj email i slijedi link za potvrÄ‘ivanje kako bi tvoja nova email adresa bila potvrÄ‘ena. - updated: Tvoj raÄun je uspjeÅ¡no ažuriran. + destroyed: Zbogom! VaÅ¡ je raÄun uspjeÅ¡no otkazan. Nadamo se da ćemo Vas uskoro ponovno vidjeti. + signed_up: Dobro doÅ¡li! UspjeÅ¡no ste se prijavili. + signed_up_but_inactive: UspjeÅ¡no ste se registrirali. No, ne možemo Vas prijaviti jer VaÅ¡ raÄun joÅ¡ nije aktiviran. + signed_up_but_locked: UspjeÅ¡no ste se registrirali. No, ne možemo Vas prijaviti jer je VaÅ¡ raÄun zakljuÄan. + signed_up_but_unconfirmed: Poruka s poveznicom za potvrÄ‘ivanje poslana je na VaÅ¡u adresu e-poÅ¡te. Molimo slijedite poveznicu za aktivaciju VaÅ¡eg raÄuna. Molimo provjerite mapu neželjene poÅ¡te, ako niste primili ovu e-poÅ¡tu. + update_needs_confirmation: VaÅ¡ raÄun uspjeÅ¡no je ažuriran, ali moramo potvrditi VaÅ¡u novu adresu e-poÅ¡te. Molimo provjerite VaÅ¡u e-poÅ¡tu i slijedite poveznicu za potvrÄ‘ivanje VaÅ¡e nove adrese e-poÅ¡te. Molimo provjerite mapu neželjene poÅ¡te, ako niste primili ovu e-poÅ¡tu. + updated: VaÅ¡ je raÄun uspjeÅ¡no ažuriran. sessions: - already_signed_out: UspjeÅ¡no si odjavljen. - signed_in: UspjeÅ¡no si prijavljen. - signed_out: UspjeÅ¡no si odjavljen. + already_signed_out: UspjeÅ¡no ste odjavljeni. + signed_in: UspjeÅ¡no ste prijavljeni. + signed_out: UspjeÅ¡no ste odjavljeni. unlocks: - send_instructions: Primit ćeÅ¡ email sa uputama kako otkljuÄati svoj raÄun za nekoliko minuta. - send_paranoid_instructions: Ako tvoj raÄun postoji, primit ćeÅ¡ email sa uputama kako ga otkljuÄati za nekoliko minuta. - unlocked: Tvoj raÄun je uspjeÅ¡no otkljuÄan. Prijavi se kako bi nastavio. + send_instructions: Primit ćete e-poÅ¡tu s uputama kako otkljuÄati VaÅ¡ raÄun za nekoliko minuta. Molimo provjerite neželjenu poÅ¡tu, ako niste primili ovu e-poÅ¡tu. + send_paranoid_instructions: Ako VaÅ¡ raÄun postoji, za nekoliko minuta primit ćete e-poÅ¡tu s uputama kako ga otkljuÄati. Molimo provjerite mapu neželjene poÅ¡te, ako niste primili ovu e-poÅ¡tu. + unlocked: VaÅ¡ je raÄun uspjeÅ¡no otkljuÄan. Molimo prijavite se za nastavak. errors: messages: - already_confirmed: je već potvrÄ‘en, pokuÅ¡aj se prijaviti - confirmation_period_expired: mora biti potvrÄ‘en u roku od %{period}, molimo zatraži novi - expired: je istekao, zatraži novu - not_found: nije naÄ‘en + already_confirmed: je već potvrÄ‘en, pokuÅ¡ajte se prijaviti + confirmation_period_expired: mora biti potvrÄ‘en unutar %{period}, molimo zatražite novi + expired: je istekao, zatražite novi + not_found: nije pronaÄ‘en not_locked: nije zakljuÄan diff --git a/config/locales/devise.hu.yml b/config/locales/devise.hu.yml index 62888be74e597d4567159217596f946535fe3a66..a60d2e88b0ff26601362f362f688e8d4c1e3f5ec 100644 --- a/config/locales/devise.hu.yml +++ b/config/locales/devise.hu.yml @@ -60,6 +60,23 @@ hu: title: A kétlépcsÅ‘s kódok megváltozott unlock_instructions: subject: 'Mastodon: Feloldási lépések' + webauthn_credential: + added: + explanation: A következÅ‘ biztonsági kulcsot hozzáadtuk a fiókodhoz + subject: 'Mastodon: Új biztonsági kulcs' + title: Új biztonsági kulcsot vettünk fel + deleted: + explanation: A következÅ‘ biztonsági kulcsot töröltük a fiókodból + subject: 'Mastodon: Biztonsági kulcs törölve' + title: Az egyik biztonsági kulcsodat törölték + webauthn_disabled: + explanation: A biztonsági kulccsal történÅ‘ hitelesÃtést letiltottuk a fiókodon. Bejelentkezni csak a párosÃtott TOTP app által generált tokennel lehet. + subject: 'Mastodon: Biztonsági kulccsal történÅ‘ hitelesÃtés letiltva' + title: Biztonsági kulcsok letiltva + webauthn_enabled: + explanation: A biztonsági kulccsal történÅ‘ hitelesÃtést engedélyeztük a fiókodon. A biztonsági kulcsodat mostantól használhatod bejelentkezésre. + subject: 'Mastodon: Biztonsági kulcsos hitelesÃtés engedélyezve' + title: Biztonsági kulcsok engedélyezve omniauth_callbacks: failure: Sikertelen hitelesÃtés %{kind} fiókról, mert "%{reason}". success: Sikeres hitelesÃtés %{kind} fiókról. @@ -94,5 +111,5 @@ hu: not_found: nem található not_locked: nincs lezárva not_saved: - one: '1 hiba megakadályozta %{resource} mentését:' - other: "%{count} számú hiba megakadályozta %{resource} mentését:" + one: '1 hiba megakadályozta e %{resource} mentését:' + other: "%{count} hiba megakadályozta e %{resource} mentését:" diff --git a/config/locales/devise.hy.yml b/config/locales/devise.hy.yml index d7ebe3338fd50283eddbafca2c369407c90bf89f..2a75385e9fbfd90dba26bf0e8475ea2fb09afa95 100644 --- a/config/locales/devise.hy.yml +++ b/config/locales/devise.hy.yml @@ -2,12 +2,12 @@ hy: devise: confirmations: - confirmed: ÕÕ¥Ö€ Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ¥Õ¶ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¥ÖÖ‰ - send_instructions: Õ„Õ¥Õ¶Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¥Õ¶Ö„ ÕÕ¥Õ¦ Õ§Õ¬â€¤Õ¶Õ¡Õ´Õ¡Õ¯Õ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¸Õ¾, Õ©Õ¥ Õ«Õ¶Õ¹ÕºÕ¥Õ½ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Ö„ էլ․փոստը Õ´Õ« Ö„Õ¡Õ¶Õ« Õ¾Õ¡ÕµÖ€Õ¯ÕµÕ¡Õ¶Õ¸Ö‚Õ´Ö‰ ÕÕ¿Õ¸Ö‚Õ£Õ¥ Õ±Õ¥Ö€ Õ©Õ¡ÖƒÕ¸Õ¶ Õ©Õ²Õ©Õ¡ÕºÕ¡Õ¶Õ¡Õ¯Õ¨, Õ¥Õ©Õ¥ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¹Õ¥Ö„ Õ½Õ¿Õ¡ÖÕ¥Õ¬Ö‰ + confirmed: ÕÕ¥Ö€ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§Õ¶ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¥ÖÖ‰ + send_instructions: Õ„Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ§Õ«Ö Õ¤Õ¸Ö‚ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Õ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¸Õ¾, Õ©Õ§ Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¤Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¤, Õ¥Õ©Õ§ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Ö‰ send_paranoid_instructions: ÔµÕ©Õ¥ Õ±Õ¥Ö€ էլ․փոստի Õ°Õ¡Õ½ÖÕ¥Õ¶ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¯Õ¡ Õ´Õ¥Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¢Õ¡Õ¦Õ¡ÕµÕ¸Ö‚Õ´, Õ¡ÕºÕ¡ Õ´Õ¥Õ¶Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¥Õ¶Ö„ ÕÕ¥Õ¦ Õ§Õ¬â€¤Õ¶Õ¡Õ´Õ¡Õ¯Õ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¸Õ¾, Õ©Õ¥ Õ«Õ¶Õ¹ÕºÕ¥Õ½ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Ö„ էլ․փոստը Õ´Õ« Ö„Õ¡Õ¶Õ« Õ¾Õ¡ÕµÖ€Õ¯ÕµÕ¡Õ¶Õ¸Ö‚Õ´Ö‰ ÕÕ¿Õ¸Ö‚Õ£Õ¥ Õ±Õ¥Ö€ Õ©Õ¡ÖƒÕ¸Õ¶ Õ©Õ²Õ©Õ¡ÕºÕ¡Õ¶Õ¡Õ¯Õ¨, Õ¥Õ©Õ¥ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¹Õ¥Ö„ Õ½Õ¿Õ¡ÖÕ¥Õ¬Ö‰ failure: - already_authenticated: Ô´Õ¸Ö‚Ö„ Õ¡Ö€Õ¤Õ¥Õ¶ Õ´Õ¸Ö‚Õ¿Ö„ Õ¥Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Ö‰ - inactive: ÕÕ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¤Õ¥Õ¼ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¾Õ¡Õ® Õ¹Õ§Ö‰ + already_authenticated: Ô±Ö€Õ¤Õ§Õ¶ Õ´Õ¸Ö‚Õ¿Ö„ Õ¥Õ½ Õ£Õ¸Ö€Õ®Õ¥Õ¬ + inactive: Õ€Õ¡Õ·Õ«Ö‚Õ¤ Õ¤Õ¥Õ¼ Õ¡Õ¯Õ¿Õ«Ö‚ Õ¹Õ§ invalid: ÕÕÕ¡Õ¬ %{authentication_keys} Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰ last_attempt: Ô´Õ¸Ö‚Ö„ Õ¸Ö‚Õ¶Õ¥Ö„ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨, Õ¸Ö€Õ«Ö Õ°Õ¥Õ¿Õ¸ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¯Õ¡Ö€Õ£Õ¥Õ¡Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ«Ö‰ locked: ÕÕ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Ö‰ @@ -20,28 +20,96 @@ hy: confirmation_instructions: action: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ¥Õ¶ action_with_app: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Ö„ Ö‡ Õ¥Õ¿ Õ¡Õ¶ÖÕ¥Ö„ %{app} - title: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ¥Õ¶ + explanation: Ô´Õ¸Ö‚ Õ¡Ö€Õ¤Õ§Õ¶ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¥Õ½ Õ°Õ¡Õ·Õ«Ö‚ %{host}Õ¸Ö‚Õ´ Õ¡ÕµÕ½ էլ․ ÖƒÕ¸Õ½Õ¿Õ¸Õ¾Ö‰ Ô´Õ¸Ö‚ Õ¡ÕµÕ¶ Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚Ö Õ°Õ¥Õ¼Õ¸Ö‚ Õ¥Õ½ Õ´Õ§Õ¯ Õ¯Õ¿Õ¿Õ¸ÖÕ¸Õ¾Ö‰ ÔµÕ©Õ§ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ Õ¥Õ²Õ¥Õ¬, Õ¡ÕºÕ¡ Õ¡Õ¶Õ¿Õ¥Õ½Õ«Ö€ Õ¡ÕµÕ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ + explanation_when_pending: Ô´Õ¸Ö‚ Õ¡Ö€Õ¤Õ§Õ¶ Õ¡ÕµÕ½ էլ․ ÖƒÕ¸Õ½Õ¿Õ¸Õ¾ Õ¤Õ«Õ´Õ¥Õ¬ Õ¥Õ½ %{host}Õ¸Ö‚Õ´ Õ°Ö€Õ¡Ö‚Õ§Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÔµÖ€Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶, Õ´Õ¥Õ¶Ö„ Õ¯Õ¨ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¥Õ¶Ö„ Ö„Õ¸ Õ¤Õ«Õ´Õ¸Ö‚Õ´Õ¨Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¤ ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Õ´ Õ°Õ¡Õ·Õ«Ö‚Õ¤ Õ»Õ¶Õ»Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€, Õ¢Õ¡ÕµÖ Õ¡ÕµÕ¬ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½Õ Õ¶Õ¡ÕÖ„Õ¡Õ¶ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¤ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´Õ¨Ö‰ ÔµÕ©Õ§ Õ¤Õ«Õ´Õ¸Ö‚Õ´Õ¤ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ«, Ö„Õ¸ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯Õ¨ Õ¾Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¥Õ¶, Õ¥Ö‚ Ö„Õ¥Õ¦Õ¶Õ«Ö Õ¡ÕµÕ¬ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ« Õ½ÕºÕ¡Õ½Õ¸Ö‚Õ«Ö‰ ÔµÕ©Õ§ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ Õ¥Õ²Õ¥Õ¬, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ¡Õ¶Õ¿Õ¥Õ½Õ«Ö€ Õ¡ÕµÕ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ + extra_html: Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ¿Õ¥Õ½ Õ¶Õ¡Õ¥Ö‚ <a href="%{terms_path}">Õ½Õ¥Ö€Õ¸Ö‚Õ¥Ö€Õ« Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Õ¨</a> Õ¥Ö‚ <a href="%{policy_path}">Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨</a>Ö‰ + subject: Մաստոդոն․ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ %{instance}Õ« Õ°Õ¡Õ´Õ¡Ö€ + title: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ email_changed: - subject: Մաստոդոն․ Էլ․փոստը ÖƒÕ¸ÖƒÕ¸ÕÕ¾Õ¥Ö - title: Õ†Õ¸Ö€ էլ․ Õ°Õ¡Õ½ÖÕ¥ + explanation: Õ”Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ ÖƒÕ¸ÕÕ¸Ö‚Õ¥Õ¬ է․ + extra: ÔµÕ©Õ§ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ ÖƒÕ¸ÕÕ¥Õ¬ Ö„Õ¸ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶Õ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ¸Ö€Õ¥Ö‚Õ§ Õ´Õ§Õ¯Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¸Ö‚Õ¶Õ« Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¶Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ·Õ¿Õ¡Õº ÖƒÕ¸ÕÕ«Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¸Ö‚Õ«Ö€ Õ½Õ¥Ö€Õ¸Ö‚Õ§Ö€Õ« Õ¡Õ¤Õ´Õ«Õ¶Õ« Õ°Õ¥Õ¿, Õ¸Ö€ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¤Ö‰ + subject: Մաստոդոն․ Էլ․ ÖƒÕ¸Õ½Õ¿Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö + title: Õ†Õ¸Ö€ էլ․ Õ°Õ¡Õ½ÖÕ§ password_change: - subject: Մաստոդոն․ Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¾Õ¥Ö - title: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¾Õ¥Ö + explanation: Õ€Õ¡Õ·Õ¸Ö‚Õ«Õ¤ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥ÖÖ‰ + extra: ÔµÕ©Õ§ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ ÖƒÕ¸ÕÕ¥Õ¬ Ö„Õ¸ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Õ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ¸Ö€Õ¥Ö‚Õ§ Õ´Õ§Õ¯Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¸Ö‚Õ¶Õ« Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¶Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ·Õ¿Õ¡Õº ÖƒÕ¸ÕÕ«Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¸Ö‚Õ«Ö€ Õ½Õ¥Ö€Õ¸Ö‚Õ§Ö€Õ« Õ¡Õ¤Õ´Õ«Õ¶Õ« Õ°Õ¥Õ¿, Õ¸Ö€ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¤Ö‰ + subject: Մաստոդոն․ Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö + title: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö reconfirmation_instructions: - explanation: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Ö„ Õ¶Õ¸Ö€ էլ․հասÖÕ¥Õ¶, Õ±Õ¥Ö€ էլ․թոստը ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ - title: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ¥Õ¶ + explanation: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ«Ö€ Ö„Õ¸ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¡ÕµÕ¶ ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ + extra: ÔµÕ©Õ§ Õ¡ÕµÕ½ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ Õ¶Õ¡ÕÕ¡Õ±Õ¥Õ¼Õ¶Õ¥Õ¬Õ Õ¡Õ¶Õ¿Õ¥Õ½Õ«Ö€ Õ¡ÕµÕ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ Էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ¹Õ« ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ«, Ö„Õ¡Õ¶Õ« Õ¤Õ¥Õ¼ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¾Õ¥Ö€Õ¥Ö‚Õ« ÕµÕ²Õ¸Ö‚Õ´Õ¨Ö‰ + subject: Մաստոդոն․ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ«Ö€ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ %{instance}Õ« Õ°Õ¡Õ´Õ¡Ö€ + title: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ reset_password_instructions: action: Õ“Õ¸ÕÕ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ - title: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡ÕµÕ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ + explanation: Ô´Õ¸Ö‚ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬ Õ¥Õ½ Õ¶Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ Õ¡ÕµÕ½ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ + extra: ÔµÕ©Õ§ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ¶, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¡Õ¶Õ¿Õ¥Õ½Õ«Ö€ Õ¡ÕµÕ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ Õ”Õ¸ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¹Õ« ÖƒÕ¸ÕÕ¸Ö‚Õ«, Ö„Õ¡Õ¶Õ« Õ¤Õ¥Õ¼ Õ¤Õ¸Ö‚ Õ¹Õ¥Õ½ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¾Õ¥Ö€Õ¥Ö‚Õ« ÕµÕ²Õ¸Ö‚Õ´Õ¨ Õ¥Ö‚ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€Õ¨Ö‰ + subject: Մաստոդոն․ Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ + title: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ two_factor_disabled: - title: 2FA Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§ + explanation: 2FAÖŠÕ¶ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ¡Õ¶Õ»Õ¡Õ¿Õ¸Ö‚Õ¥ÖÖ‰ Õ„Õ¸Ö‚Õ¿Ö„Õ¶ Õ¡ÕµÕªÕ´ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ§ Õ´Õ«Õ¡ÕµÕ¶ էլ․ ÖƒÕ¸Õ¿Õ« Õ¥Ö‚ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾Ö‰ + subject: Մաստոդոն․ 2FAÖŠÕ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¸Ö‚Õ¥Ö + title: 2FA Õ¡Õ¶Õ»Õ¡Õ¿Õ¸Ö‚Õ¡Õ® Õ§ two_factor_enabled: - title: 2FA Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ + explanation: 2FAÖŠÕ¶ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§Ö‰ TOTP Õ®Ö€Õ¡Õ£Ö€Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® tokenÖŠÕ¨ ÕºÕ§Õ¿Ö„ Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ½ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ + subject: Մաստոդոն․ 2FA-Õ¶ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¥Ö + title: 2FA Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§ + two_factor_recovery_codes_changed: + explanation: Õ†Õ¡ÕÕ¸Ö€Õ¤ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¶ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ¥Õ¶, ÕºÕ§Õ¿Ö„ Õ§ Õ¶Õ¸Ö€Õ¨ Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ«Ö‰ + subject: Մաստոդոն․ 2FA Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨ Õ¯Ö€Õ¯Õ«Õ¶ Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ + title: 2FA Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ unlock_instructions: - subject: Մաստոդոն․ Ô±ÕºÕ¡Õ¯Õ¸Õ²ÕºÕ¥Õ¬Õ¸Ö‚ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ + subject: Մաստոդոն․ Ô±ÕºÕ¡Õ¯Õ¸Õ²ÕºÕ¥Õ¬Õ¸Ö‚ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ + webauthn_credential: + added: + explanation: Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¡Õ¬ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶ Õ§ Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¸Ö‚Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¤ + subject: Մաստոդոն․ Õ†Õ¸Ö€ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ« + title: Õ†Õ¸Ö€ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ« Õ§ Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¸Ö‚Õ¥Õ¬ + deleted: + explanation: Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¡Õ¬ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö Õ»Õ¶Õ»Õ¸Ö‚Õ¥Õ¬ Õ§ + subject: Մաստոդոն․ Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶ Õ»Õ¶Õ»Õ¸Ö‚Õ¥Õ¬ Õ§ + title: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ«ÖÕ¤ Õ´Õ¥Õ¯Õ¨ Õ»Õ¶Õ»Õ¸Ö‚Õ¥Õ¬ Õ§ + webauthn_disabled: + explanation: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ¸Õ¾ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¥Õ¬ Õ§Ö‰ Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¶ Õ¡ÕµÕªÕ´ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ§Õ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Õ¾ Õ´Õ«Õ¡ÕµÕ¶ Õ¦Õ¸Ö‚Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ¡Õ® TOTP ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ«Ö Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ¯Õ¿Ö€Ö…Õ¶Õ¨Ö‰ + subject: Մաստոդոն․ Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¶ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ¸Õ¾ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¡Õ® Õ§ + title: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ + webauthn_enabled: + explanation: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¸Õ¾ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§Ö‰ Õ”Õ¸ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶ Õ¡ÕµÕªÕ´ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¥Õ¬ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ + subject: Մաստոդոն․ Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¸Õ¾ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§ + title: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ¨ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ + omniauth_callbacks: + failure: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Ö‚ %{kind}Õ«Ö Ö„Õ¡Õ¶Õ« Õ¸Ö€ %{reason}Ö‰ + success: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ¥Ö %{kind} Õ°Õ¡Õ·Õ¸Ö‚Õ«ÖÖ‰ + passwords: + no_token: Ô´Õ¸Ö‚ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¡ÕµÕ½ Õ§Õ»Õ«Õ¶, Õ¡Õ¼Õ¡Õ¶Ö Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« ÖƒÕ¸ÖƒÕ¸ÕÕ´Õ¡Õ¶ Õ«Õ´Õ¡Õ¯Õ« ÕµÕ²Õ´Õ¡Õ¶Ö‰ ÔµÕ©Õ§ Õ¥Õ¯Õ¥Õ¬ Õ¥Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ´Õ¡Õ¶ Õ«Õ´Õ¡Õ¯Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾, Õ¡ÕºÕ¡ ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ°Õ¡Õ´Õ¸Õ¦Õ¸Ö‚Õ«Ö€, Õ¸Ö€ Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® URLÖŠÕ¶ ÖƒÕ¡Õ¯ÖÖ€Õ¥Õ¬ Õ¥Õ½ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢Ö‰ + send_instructions: ÔµÕ©Õ§ Ö„Õ¸ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¡Ö€Õ¤Õ§Õ¶ Õ¯Õ¡Õµ Õ´Õ¥Ö€ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¢Õ¡Õ¦Õ¡ÕµÕ¸Ö‚Õ´, Õ¤Õ¸Ö‚ Õ´Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ§Õ«Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ«Õ¤ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ ÕµÕ²Õ¸Ö‚Õ´Õ¨Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¤, Õ¥Õ©Õ§ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ + send_paranoid_instructions: ÔµÕ©Õ§ Ö„Õ¸ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¡Ö€Õ¤Õ§Õ¶ Õ¯Õ¡Õµ Õ´Õ¥Ö€ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¢Õ¡Õ¦Õ¡ÕµÕ¸Ö‚Õ´, Õ¤Õ¸Ö‚ Õ´Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ§Õ«Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ«Õ¤ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ ÕµÕ²Õ¸Ö‚Õ´Õ¨Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¤, Õ¥Õ©Õ§ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Õ¨Ö‰ + updated: Ô³Õ¡Õ²Õ¿Õ¡Õ¢Õ¡Õ¼Õ¤ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢Ö‰ Ô±ÕµÕªÕ´ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¡Õ® Õ¥Õ½Ö‰ + updated_not_active: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢Ö‰ + registrations: + destroyed: Ցը՜․ Õ”Õ¸ Õ°Õ¡Õ·Õ«Ö‚Õ¨ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥ÖÖ‰ Õ…Õ¸ÕµÕ½ Õ¸Ö‚Õ¶Õ¥Õ¶Ö„ Ö„Õ¥Õ¦ Õ¯Ö€Õ¯Õ«Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬Ö‰ + signed_up: Ողջո՜յն։ Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥ÖÕ«Ö€Ö‰ + signed_up_but_inactive: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥ÖÕ«Ö€Ö‰ ÕÕ¡Õ¯Õ¡ÕµÕ¶, Õ¤Õ¥Õ¼ Õ¹Õ¥Õ½ Õ¯Õ¡Ö€Õ¸Õ² Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¤ Õ¤Õ¥Õ¼ Õ¡Õ¯Õ¿Õ«Ö‚ Õ¹Õ§Ö‰ + signed_up_but_locked: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥ÖÕ«Ö€Ö‰ ÕÕ¡Õ¯Õ¡ÕµÕ¶, Õ¤Õ¥Õ¼ Õ¹Õ¥Õ½ Õ¯Õ¡Ö€Õ¸Õ² Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¤ ÖƒÕ¡Õ¯ Õ§Ö‰ + signed_up_but_pending: Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Õ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕµÕ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§ Ö„Õ¸ էլ․ ÖƒÕ¸Õ½Õ¿Õ«Õ¶Ö‰ Õ…Õ²Õ´Õ¡Õ¶Õ¨ Õ¯Õ¿Õ¿Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚Ö ÕµÕ¥Õ¿Õ¸Õµ Õ´Õ¥Õ¶Ö„ Õ¯Õ¨ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¥Õ¶Ö„ Ö„Õ¸ Õ¤Õ«Õ´Õ¸Ö‚Õ´Õ¨Ö‰ Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´Õ«Ö ÕµÕ¥Õ¿Õ¸Õµ Ö„Õ¥Õ¦ Õ¯Õ¨ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡ÖÕ¶Õ¥Õ¶Ö„Ö‰ + signed_up_but_unconfirmed: Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Õ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕµÕ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§ Ö„Õ¸ էլ․ ÖƒÕ¸Õ½Õ¿Õ«Õ¶Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ«Ö€ ÕµÕ²Õ´Õ¡Õ¶Õ¨ Õ°Õ¡Õ·Õ«Ö‚Õ¤ Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¨, Õ¥Õ©Õ§ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Ö‰ + update_needs_confirmation: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ«Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¤, Õ¢Õ¡ÕµÖ Õ´Õ¥Õ¶Ö„ ÕºÕ§Õ¿Ö„ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¶Ö„ Ö„Õ¸ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ ÖƒÕ¸Õ½Õ¿Õ¤ Õ¥Ö‚ Õ°Õ¥Õ¿Õ¥Ö‚Õ«Ö€ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕµÕ²Õ´Õ¡Õ¶Õ¨Õ Õ¶Õ¸Ö€ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¤ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÕÕ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¨, Õ«Õ´Õ¡Õ¯ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´Ö‰ + updated: Õ€Õ¡Õ·Õ«Ö‚Õ¤ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥ÖÖ‰ sessions: - signed_in: Õ„Õ¸Ö‚Õ¿Ö„Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥ÖÖ‰ + already_signed_out: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¤Õ¸Ö‚Ö€Õ½ Õ¥Õ¯Õ¡Ö€Ö‰ + signed_in: Õ„Õ¸Ö‚Õ¿Ö„Õ¨ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ¥ÖÖ‰ + signed_out: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¤Õ¸Ö‚Ö€Õ½ Õ¥Õ¯Õ¡Ö€Ö‰ + unlocks: + send_instructions: Õ„Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ§Õ«Ö Õ¤Õ¸Ö‚ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Õ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¸Õ¾, Õ©Õ§ Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¢Õ¡ÖÕ¥Õ½ Õ°Õ¡Õ·Õ«Ö‚Õ¤Ö‰ Ô»Õ´Õ¡Õ¯ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¨Ö‰ + send_paranoid_instructions: ÔµÕ©Õ§ Õ°Õ¡Õ·Õ«Ö‚Õ¤ Õ£Õ¸ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¸Ö‚Õ¶Õ«Õ Õ´Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ§Õ«Ö Õ¤Õ¸Ö‚ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ½ Õ«Õ´Õ¡Õ¯Õ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¸Õ¾, Õ©Õ§ Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¢Õ¡ÖÕ¥Õ½ Õ¡ÕµÕ¶Ö‰ Ô»Õ´Õ¡Õ¯ Õ¹Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€ Õ½ÕºÕ¡Õ´ ÕºÕ¡Õ¶Õ¡Õ¯Õ¨Ö‰ + unlocked: Õ€Õ¡Õ·Õ«Ö‚Õ¤ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¢Õ¡ÖÕ¸Ö‚Õ¥ÖÖ‰ Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ«Ö€Ö‰ errors: messages: - not_found: Õ¹Õ£Õ¿Õ¶Õ¾Õ¥Ö - not_locked: Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ¹Õ§ + already_confirmed: Õ¡Ö€Õ¤Õ§Õ¶ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¡Õ® Õ§, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ«Ö€ + confirmation_period_expired: ÕºÕ§Õ¿Ö„ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ§Ö€ %{period} Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ«Ö€ Õ¶Õ¸Ö€Õ¨ + expired: Õ½ÕºÕ¡Õ¼Õ¸Ö‚Õ¥Õ¬ Õ§, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¶Õ¸Ö€Õ¨ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ«Ö€ + not_found: Õ¹Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Ö + not_locked: Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ¹Õ§ + not_saved: + one: 1 Õ½ÕÕ¡Õ¬ Õ©Õ¸ÕµÕ¬ Õ¹Õ¿Õ¸Ö‚Õ¥Ö ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ Õ¡ÕµÕ½ %{resource}ը․ + other: "%{count} Õ½ÕÕ¡Õ¬Õ¶Õ¥Ö€ Õ©Õ¸ÕµÕ¬ Õ¹Õ¿Õ¸Ö‚Õ¥ÖÕ«Õ¶ ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ Õ¡ÕµÕ½ %{resource}ը․" diff --git a/config/locales/devise.id.yml b/config/locales/devise.id.yml index 5b4e8af43da85803ea6898671182cd62e5f0e74b..6fe6c257d36d167f5d11885feaedaafb3fcee18a 100644 --- a/config/locales/devise.id.yml +++ b/config/locales/devise.id.yml @@ -60,6 +60,23 @@ id: title: Kode pemulihan 2FA diubah unlock_instructions: subject: 'Mastodon: Petunjuk membuka' + webauthn_credential: + added: + explanation: Kunci keamanan berikut telah ditambahkan ke akun Anda + subject: 'Mastodon: Kunci keamanan baru' + title: Kunci keamanan baru telah ditambahkan + deleted: + explanation: Kunci keamanan berikut telah dihapus dari akun Anda + subject: 'Mastodon: Kunci keamanan dihapus' + title: Salah satu dari kunci keamanan Anda telah dihapus + webauthn_disabled: + explanation: Autentikasi dengan kunci keamanan telah dinonaktifkan untuk akun ini. Proses masuk akun hanya mungkin menggunakan token yang dibuat dengan aplikasi TOTP. + subject: 'Mastodon: Autentikasi dengan kunci keamanan dinoaktifkan' + title: Kunci keamanan dinonaktifkan + webauthn_enabled: + explanation: Autentikasi kunci keamanan telah diaktifkan untuk akun Anda. Kunci keamanan Anda kini dapat dipakai untuk masuk. + subject: 'Mastodon: Autentikasi kunci keamanan aktif' + title: Kunci keamanan aktif omniauth_callbacks: failure: Tidak dapat mengautentikasi anda dari %{kind} karena "%{reason}". success: Autentikasi dari akun %{kind} berhasil dilakukan. diff --git a/config/locales/devise.is.yml b/config/locales/devise.is.yml index 4d6fb39024753964650723c65420970a6374b6c6..e595f77afdf2c4abb0e998e98d660369a81d55fe 100644 --- a/config/locales/devise.is.yml +++ b/config/locales/devise.is.yml @@ -60,6 +60,23 @@ is: title: Endurheimtukóðar tveggja-þátta auðkenningar breyttust unlock_instructions: subject: 'Mastodon: Leiðbeiningar til að aflæsa' + webauthn_credential: + added: + explanation: Eftirfarandi öryggislykli hefur verið bætt við notandaaðganginn þinn + subject: 'Mastodon: Nýr öryggislykill' + title: Nýjum öryggislykli hefur verið bætt við + deleted: + explanation: Eftirfarandi öryggislykli hefur verið eytt úr notandaaðgangnum þÃnum + subject: 'Mastodon: Öryggislykli eytt' + title: Einum af öryggilyklunum þÃnum hefur verið eytt + webauthn_disabled: + explanation: Auðkenning með öryggislyklum hefur verið gerð óvirk fyrir aðganginn þinn. Innskráning er núna einungis möguleg með teikni útbúnu af paraða TOTP-forritinu. + subject: 'Mastodon: Auðkenning með öryggislyklum er óvirk' + title: Öryggislyklar eru óvirkir + webauthn_enabled: + explanation: Auðkenning með öryggislykli hefur verið gerð virk fyrir aðganginn þinn. Nú er hægt að nota öryggislykilinn þinn til að skrá inn. + subject: 'Mastodon: Auðkenning með öryggislykli er virk' + title: Öryggislyklar eru virkir omniauth_callbacks: failure: Gat ekki auðkennt þig frá %{kind} vegna "%{reason}". success: Tókst að auðkenna frá %{kind} notandaaðgangnum. diff --git a/config/locales/devise.it.yml b/config/locales/devise.it.yml index 714684924983c2d9fa7cfc09c7d6c5cae2b6f5f3..31e3c7f944242d5a887a68936d23d1a9d27d4578 100644 --- a/config/locales/devise.it.yml +++ b/config/locales/devise.it.yml @@ -60,6 +60,23 @@ it: title: Codici di recupero 2FA modificati unlock_instructions: subject: 'Mastodon: Istruzioni di sblocco' + webauthn_credential: + added: + explanation: La seguente chiave di sicurezza è stata aggiunta al tuo account + subject: 'Mastodon: Nuova chiave di sicurezza' + title: È stata aggiunta una nuova chiave di sicurezza + deleted: + explanation: La seguente chiave di sicurezza è stata cancellata dal tuo account + subject: 'Mastodon: Chiave di sicurezza cancellata' + title: Una delle tue chiavi di sicurezza è stata cancellata + webauthn_disabled: + explanation: L'autenticazione con le chiavi di sicurezza è stata disabilitata per il tuo account. L'accesso è ora possibile utilizzando solo il codice generato dall'app TOTP abbinata. + subject: 'Mastodon: Autenticazione con chiavi di sicurezza disabilitata' + title: Chiavi di sicurezza disattivate + webauthn_enabled: + explanation: L'autenticazione con chiave di sicurezza è stata attivata per il tuo account. La chiave di sicurezza può ora essere utilizzata per l'accesso. + subject: 'Mastodon: Autenticazione della chiave di sicurezza abilitata' + title: Chiave di sicurezza abilitata omniauth_callbacks: failure: Impossibile autenticarti da %{kind} perché "%{reason}". success: Autenticato con successo con account %{kind}. diff --git a/config/locales/devise.ja.yml b/config/locales/devise.ja.yml index e697e290de7246dafd8b71d33bb99d6aa3820a4d..73e79be23a383487fe8d37773c1779e67ec7db1c 100644 --- a/config/locales/devise.ja.yml +++ b/config/locales/devise.ja.yml @@ -60,6 +60,23 @@ ja: title: 二段階èªè¨¼ã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ãŒå¤‰æ›´ã•れã¾ã—㟠unlock_instructions: subject: 'Mastodon: アカウントã®ãƒãƒƒã‚¯ã®è§£é™¤' + webauthn_credential: + added: + explanation: 次ã®ã‚»ã‚ュリティã‚ーãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«è¿½åŠ ã•れã¾ã—㟠+ subject: 'Mastodon: ã‚»ã‚ュリティã‚ーãŒè¿½åŠ ã•れã¾ã—ãŸ' + title: æ–°ã—ã„ã‚»ã‚ュリティã‚ーãŒè¿½åŠ ã•れã¾ã—㟠+ deleted: + explanation: 次ã®ã‚»ã‚ュリティã‚ーãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‹ã‚‰å‰Šé™¤ã•れã¾ã—㟠+ subject: 'Mastodon: ã‚»ã‚ュリティã‚ーãŒå‰Šé™¤ã•れã¾ã—ãŸ' + title: ã‚»ã‚ュリティã‚ーãŒå‰Šé™¤ã•れã¾ã—㟠+ webauthn_disabled: + explanation: アカウントã®ã‚»ã‚ュリティã‚ーã«ã‚ˆã‚‹èªè¨¼ãŒç„¡åйã«ãªã‚Šã¾ã—ãŸã€‚ペアリングã•れãŸTOTPアプリã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒˆãƒ¼ã‚¯ãƒ³ã®ã¿ã‚’使用ã—ã¦ãƒã‚°ã‚¤ãƒ³ãŒå¯èƒ½ã«ãªã‚Šã¾ã—ãŸã€‚ + subject: 'Mastodon: ã‚»ã‚ュリティã‚ーèªè¨¼ãŒç„¡åйã«ãªã‚Šã¾ã—ãŸ' + title: ã‚»ã‚ュリティã‚ーã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ + webauthn_enabled: + explanation: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã‚»ã‚ュリティã‚ーèªè¨¼ãŒæœ‰åйã«ãªã‚Šã¾ã—ãŸã€‚ã‚»ã‚ュリティã‚ーをãƒã‚°ã‚¤ãƒ³ã«ä½¿ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã—ãŸã€‚ + subject: 'Mastodon: ã‚»ã‚ュリティã‚ーèªè¨¼ãŒæœ‰åйã«ãªã‚Šã¾ã—ãŸ' + title: ã‚»ã‚ュリティã‚ãƒ¼ã¯æœ‰åйã«ãªã£ã¦ã„ã¾ã™ omniauth_callbacks: failure: "%{reason}ã«ã‚ˆã£ã¦%{kind}ã‹ã‚‰ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’èªè¨¼ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" success: "%{kind}ã‹ã‚‰ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯æ£å¸¸ã«èªè¨¼ã•れã¾ã—ãŸã€‚" diff --git a/config/locales/devise.ko.yml b/config/locales/devise.ko.yml index fbe036875e593ba18117f4335d813c5755edc533..92cda21ef7d88c47db9938d7d5674efe33a8fb29 100644 --- a/config/locales/devise.ko.yml +++ b/config/locales/devise.ko.yml @@ -60,13 +60,30 @@ ko: title: 2FA 복구 코드 ë³€ê²½ë¨ unlock_instructions: subject: 'ë§ˆìŠ¤í† ëˆ: ìž ê¸ˆ í•´ì œ 방법' + webauthn_credential: + added: + explanation: ê³„ì •ì— ë‹¤ìŒ ë³´ì•ˆ 키가 등ë¡ë˜ì—ˆìŠµë‹ˆë‹¤ + subject: 'ë§ˆìŠ¤í† ëˆ: 새로운 보안 키' + title: 새 보안 키가 추가ë˜ì—ˆìŠµë‹ˆë‹¤ + deleted: + explanation: ê³„ì •ì—서 ë‹¤ìŒ ë³´ì•ˆ 키가 ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤ + subject: 'ë§ˆìŠ¤í† ëˆ: 보안 키 ì‚ì œ' + title: 보안 키가 ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤ + webauthn_disabled: + explanation: 보안 키를 ì´ìš©í•œ ì¸ì¦ì´ ë‹¹ì‹ ì˜ ê³„ì •ì— ëŒ€í•´ 비활성화 ë˜ì–´ 있습니다. TOTP ì•±ì˜ í† í°ë§Œìœ¼ë¡œ ë¡œê·¸ì¸ í• ìˆ˜ 있습니다. + subject: 'ë§ˆìŠ¤í† ëˆ: 보안 키를 ì´ìš©í•œ ì¸ì¦ì´ 비활성화 ë¨' + title: 보안 키 비활성화 ë¨ + webauthn_enabled: + explanation: 보안 키 ì¸ì¦ì´ ë‹¹ì‹ ì˜ ê³„ì •ì— ëŒ€í•´ 활성화 ë˜ì–´ 있습니다. 보안 키를 통해 ë¡œê·¸ì¸ í• ìˆ˜ 있습니다. + subject: 'ë§ˆìŠ¤í† ëˆ: 보안 키 ì¸ì¦ 활성화 ë¨' + title: 보안 키 활성화 ë¨ omniauth_callbacks: failure: '"%{reason}" ë•Œë¬¸ì— ë‹¹ì‹ ì„ %{kind}ì—서 ì¸ì¦í• 수 없습니다.' success: 성공ì 으로 %{kind} ê³„ì •ì„ ì¸ì¦ 했습니다. passwords: no_token: 패스워드 ìž¬ì„¤ì • ì´ë©”ì¼ì„ 거치지 ì•Šê³ ëŠ” ì—¬ê¸°ì— ì˜¬ 수 없습니다. 만약 패스워드 ìž¬ì„¤ì • ë©”ì¼ì—서 온 것ì´ë¼ë©´ URLì´ ë§žëŠ”ì§€ 확ì¸í•´ 주세요. - send_instructions: ë‹¹ì‹ ì˜ ì´ë©”ì¼ ì£¼ì†Œê°€ ìš°ë¦¬ì˜ DBì— ìžˆì•„ë©´ 패스워드 복구 ë§í¬ê°€ 몇 ë¶„ ì´ë‚´ì— ë©”ì¼ë¡œ 발송 ë©ë‹ˆë‹¤. 만약 ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. - send_paranoid_instructions: ë‹¹ì‹ ì˜ ì´ë©”ì¼ ì£¼ì†Œê°€ ìš°ë¦¬ì˜ DBì— ìžˆì•„ë©´ 패스워드 복구 ë§í¬ê°€ 몇 ë¶„ ì´ë‚´ì— ë©”ì¼ë¡œ 발송 ë©ë‹ˆë‹¤. 만약 ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. + send_instructions: ë‹¹ì‹ ì˜ ì´ë©”ì¼ ì£¼ì†Œê°€ ìš°ë¦¬ì˜ DBì— ìžˆë‹¤ë©´ 패스워드 복구 ë§í¬ê°€ 몇 ë¶„ ì´ë‚´ì— ë©”ì¼ë¡œ 발송 ë©ë‹ˆë‹¤. 만약 ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. + send_paranoid_instructions: ë‹¹ì‹ ì˜ ì´ë©”ì¼ ì£¼ì†Œê°€ ìš°ë¦¬ì˜ DBì— ìžˆë‹¤ë©´ 패스워드 복구 ë§í¬ê°€ 몇 ë¶„ ì´ë‚´ì— ë©”ì¼ë¡œ 발송 ë©ë‹ˆë‹¤. 만약 ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. updated: 패스워드가 ìž¬ì„¤ì • ë˜ì—ˆìŠµë‹ˆë‹¤. ë¡œê·¸ì¸ ë˜ì—ˆìŠµë‹ˆë‹¤. updated_not_active: 패스워드가 성공ì 으로 변경 ë˜ì—ˆìŠµë‹ˆë‹¤. registrations: @@ -79,9 +96,9 @@ ko: update_needs_confirmation: ê³„ì • ì •ë³´ë¥¼ ì—…ë°ì´íЏ 했습니다. 하지만 새 ì´ë©”ì¼ ì£¼ì†Œì— ëŒ€í•œ 확ì¸ì´ 필요합니다. ì´ë©”ì¼ì„ í™•ì¸ í•œ 후 ë§í¬ë¥¼ 통해 새 ì´ë©”ì¼ì„ í™•ì¸ í•˜ì„¸ìš”. ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. updated: ê³„ì • ì •ë³´ê°€ 성공ì 으로 ì—…ë°ì´íЏ ë˜ì—ˆìŠµë‹ˆë‹¤. sessions: - already_signed_out: 로그아웃 ë˜ì—ˆìŠµë‹ˆë‹¤. - signed_in: ë¡œê·¸ì¸ ë˜ì—ˆìŠµë‹ˆë‹¤. - signed_out: 로그아웃 ë˜ì—ˆìŠµë‹ˆë‹¤. + already_signed_out: 성공ì 으로 로그아웃 ë˜ì—ˆìŠµë‹ˆë‹¤. + signed_in: 성공ì 으로 ë¡œê·¸ì¸ ë˜ì—ˆìŠµë‹ˆë‹¤. + signed_out: 성공ì 으로 로그아웃 ë˜ì—ˆìŠµë‹ˆë‹¤. unlocks: send_instructions: 몇 ë¶„ ì´ë‚´ë¡œ ê³„ì • ìž ê¸ˆ í•´ì œì— ëŒ€í•œ 안내 ë©”ì¼ì´ 발송 ë©ë‹ˆë‹¤. ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. send_paranoid_instructions: ê³„ì •ì´ ì¡´ìž¬í•œë‹¤ë©´ 몇 ë¶„ ì´ë‚´ë¡œ ê³„ì • ìž ê¸ˆ í•´ì œì— ëŒ€í•œ 안내 ë©”ì¼ì´ 발송 ë©ë‹ˆë‹¤. ë©”ì¼ì„ 받지 못 í•˜ì‹ ê²½ìš° 스팸 í´ë”를 확ì¸í•´ 주세요. diff --git a/config/locales/devise.ku.yml b/config/locales/devise.ku.yml index cc251e86ae3fc9c96ba4a32a86e9e41868ac09d9..64c305681d3408c34f6099c68796cb601a1364cf 100644 --- a/config/locales/devise.ku.yml +++ b/config/locales/devise.ku.yml @@ -1 +1,115 @@ -ckb-IR: +--- +ku: + devise: + confirmations: + confirmed: ناونیشانی ئیمەیڵەکەت بە سەرکەوتوویی پشتڕاستکرایەوە. + send_instructions: ئیمەیڵێکت بۆ دەنێردرێت Ù„Û•Ú¯Û•Úµ ڕێنمایی بۆ چۆنیەتی دڵنیابوون Ù„Û• ناونیشانی ئیمەیلەکەت Ù„Û• چەند خولەکێکدا. تکایە بوخچەی سپامەکەت چاولێبکە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + send_paranoid_instructions: ئەگەر ناونیشانی ئیمەیڵەکەت Ù„Û• بنکەی زانیارێکانماندا هەبێت، ئیمەیڵێکت پێدەگات Ù„Û•Ú¯Û•Úµ ڕێنماییەکانی چۆنیەتی دڵنیابوون Ù„Û• ناونیشانی ئیمەیلەکەت Ù„Û• چەند خولەکێکدا. تکایە بۆخچەی سپامەکەت بپشکنە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + failure: + already_authenticated: تۆ پێشتر چوونە ژوورەوەت کردووە. + inactive: هەژمارەکەت هێشتا کارا نەکراوە. + invalid: "%{authentication_keys} یان نهێنوشە نادروستە." + last_attempt: تۆ یەک هەوڵیدیکەت ماوە Ù¾ÛŽØ´ ئەوەی ئەژمێرەکەت قوÙÚµ بێت. + locked: هەژمارەکت داخراوە. + not_found_in_database: "%{authentication_keys} یان نهێنوشە نادروستە." + pending: هەژمێرەکەت هێشتا لەژێر پێداچوونەوەدایە. + timeout: کۆبوونەوەکەت بەسەرچووە. تکایە دووبارە بچۆ ژوورەوە بۆ بەردەوام بوون. + unauthenticated: پێویستە بچیتە ژوورەوە یان بچیتە ناو چوونە ناو Ù¾ÛŽØ´ بەردەوام بوون. + unconfirmed: دەبێت ناونیشانی ئیمەیڵەکەت پشتڕاست بکەیتەوە Ù¾ÛŽØ´ بەردەوام بوون. + mailer: + confirmation_instructions: + action: ناونیشانی ئیمەیڵ ساخ بکەرەوە + action_with_app: پشتڕاستی بکەوە Ùˆ بگەڕێوە بۆ %{app} + explanation: ئەژمێرێکت دروست کردووە لەسەر %{host} بەم ناونیشانی ئیمەیڵە. تۆ یەک کرتە دووریت Ù„Û• کاراکردنی. ئەگەر ئەمە تۆ نەبووی، تکایە ئەم ئیمەیڵە Ùەرامۆش بکە. + explanation_when_pending: تۆ داوای بانگهێشتت کرد بۆ %{host} بەم ناونیشانی ئیمەیڵە. هەر Ú©Û• دڵنیایی Ù„Û• ناونیشانی ئیمەیڵەکەت دەکەیت، ئێمە پێداچوونەوە دەکەین بە بەرنامەکەتدا. دەتوانیت بچیت بۆ چوونە ژوورەوە بۆ گۆڕینی ووردەکاریەکانت یان سڕینەوەی هەژمارەکەت، بەڵام ناتوانیت دەستگەیشتنت هەبێت بە زۆربەی ئەرکەکان تا ئەژمێرەکەت پەسەند ناکرێت. ئەگەر کاربەرنامەکەت ڕەتکرایەوە، داتاکەت لادەبرێت، بۆیە پێویست بە کاری زیاتر Ù„Û• تۆ ناکرێت. ئەگەر ئەمە تۆ نەبووی، تکایە ئەم ئیمەیڵە Ùەرامۆش بکە. + extra_html: تکایە تێڕوانە Ù„Û• <a href="%{terms_path}"> ڕێساکانی ڕاژەکار</a> Ùˆ <a href="%{policy_path}"> مەرجەکانی خزمەتگوزاری</a>. + subject: 'ماستۆدۆن: ڕێنماییەکانی پشتڕاستکردنەوە بۆ %{instance}' + title: ناونیشانی ئیمەیڵ ساخ بکەرەوە + email_changed: + explanation: 'ناونیشانی ئیمەیڵەکەی ئەژمێرەکەت دەگۆڕدرێت بۆ:' + extra: ئەگەر ئیمەیلەکەت نەگۆڕیت، لەوانەیە کەسێک دەستگەیشتنی بۆ هەژمارەکەت بەدەست بێت. تکایە تێپەڕوشەکەت بگۆڕە دەستبەجێ یان پەیوەندی بکە بە بەڕێوەبەری ڕاژەوە ئەگەر تۆ Ù„Û• هەژمارەکەت داخرایت. + subject: 'ماستۆدۆن: ئیمەیڵ گۆڕا' + title: ناونیشانی ئیمەیڵی نوێ + password_change: + explanation: تێپەڕوشە بۆ هەژمارەکەت گۆڕاوە. + extra: ئەگەر تێپەڕوشەکەت نەگۆڕی، وا دیارە کەسێک دەستگەیشتنی بۆ هەژمارەکەت بەدەست بێت. تکایە تێپەڕوسيکەت بگۆڕە دەستبەجێ یان پەیوەندی بکە بە بەڕێوەبەری ڕاژە ئەگەر تۆ Ù„Û• هەژمارەکەت داخرایت. + subject: 'ماستۆدۆن: تێپەڕوشە گۆڕدرا' + title: تێپەڕوشە گۆڕدرا + reconfirmation_instructions: + explanation: دڵنیابوون Ù„Û• ناونیشانی نوێ بۆ گۆڕینی ئیمەیڵەکەت. + extra: ئەگەر ئەم گۆڕانکاریە لەلایەن تۆوە دەست پێنەکراوە، تکایە ئەم ئیمەیڵە Ùەرامۆش بکە. ناونیشانی ئیمەیڵ بۆ هەژمێری ماستۆدۆن ناگۆڕێ هەتا ئەو کاتەی دەستپێگەیشتنی ئەم لینکەت Ù„Û• سەرەوە نیە. + subject: 'ماستۆدۆن: دووپاتی ئیمەیل بۆ %{instance}' + title: ناونیشانی ئیمەیڵ ساخ بکەرەوە + reset_password_instructions: + action: گۆڕینی تێپەڕوشە + explanation: تۆ تیپەڕوشەی نوێت داوا کرد بۆ هەژمارەکەت. + extra: ئەگەر ئەم داواکاریەت نەکرد، تکایە ئەم ئیمەیڵە Ùەرامۆش بکە. تێپەڕوشەکەت ناگۆڕێ هەتا نەچیتە ناو لینکی سەرەوە Ùˆ دانەیەکی نوێ دروست بکەیت. + subject: 'ماستۆدۆن: رێکردنەوەی رێنماییەکانی تێپەڕوشە' + title: گەڕانەوەی تێپەڕوشە + two_factor_disabled: + explanation: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر بۆ هەژمارەکەت Ú©Û• Ù„Û• کارخراوە. چوونەژوورەوە ئێستا دەکرێت تەنها ناونیشانی ئیمەیڵ Ùˆ تێپەڕوشەکەت بەکاربهێنی. + subject: 'ماستۆدۆن: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ری ناچالاک کراوە' + title: 2FA ناچالاک کرا + two_factor_enabled: + explanation: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر بۆ هەژمارەکەت چالاک کراوە. ئاماژەیەک Ú©Û• لەلایەن نەرمەکالایTOTP جووتکراو دروست کراوە پێویستە بە چوونە ژوورەوە. + subject: 'ماستۆدۆن: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ری چالاک کراوە' + title: 2FA چالاک کرا + two_factor_recovery_codes_changed: + explanation: کۆدەکانی چاککردنەوەی پێشوو هەڵوەشێنرانەوە و، نوێکان دروست بوون. + subject: 'ماستۆدۆن: کۆدەکانی گەڕانەوەی دوو ÙØ§Ú©ØªÛ•ر، دووبارە دروست دەکرێتەوە' + title: 2FA کۆدی چاککردنەوە گۆڕا + unlock_instructions: + subject: 'ماستۆدۆن: رێنماییەکان بکەرەوە' + webauthn_credential: + added: + explanation: کلیلی ئاسایشی خوارەوە زیادکرا بۆ هەژمارەکەت + subject: 'ماستۆدۆن: کلیلی ئاسایشی نوێ' + title: کلیلی پاراستنی نوێ زیادکرا + deleted: + explanation: کلیلی ئاسایشی خوارەوە Ù„Û• هەژمارەکەت سڕایەوە + subject: 'ماستۆدۆن: کلیلی پاراستن سڕایەوە' + title: کلیلە کانی پاراستنی یەکێک Ù„Û• ئێوە سڕایەوە + webauthn_disabled: + explanation: سەلماندن بە کلیلەپارێزراوەکان Ù„Û• کارخراوە بۆ هەژمارەکەت. چوونەژوورەوە ئێستا دەکرێت تەنها ئەو نیشانەیە بەکاربێنیت Ú©Û• لەلایەن نەرمەکالایTOTP دروست کراوە. + subject: 'ماستۆدۆن: سەلماندن Ù„Û•Ú¯Û•Úµ کلیلە پاسایشی ناچالاک کراوە' + title: کلیلە پارستنەکان ناچالاک کراون + webauthn_enabled: + explanation: سەلماندنی کلیلی ئاسایش چالاک کراوە بۆ هەژمارەکەت. ئێستا کلیلی پاراستن دەتوانرێت بۆ چوونە ژوورەوە بەکار بێت. + subject: 'ماستۆدۆن: سەلماندنی کلیلی پاراستن چالاک کراوە' + title: کلیلە کانی پاراستن چالاک کرا + omniauth_callbacks: + failure: نەیتوانی ڕەسەنایە تی %{kind} بتەوبکات لەبەرئەوەی "%{reason}". + success: سەرکەوتووانە Ù„Û• هەژماری %{kind} سەلمێنرا. + passwords: + no_token: ناتوانیت دەستگەیشتنت هەبێت بەم لاپەڕەیە بەبێ ئەوەی Ù„Û• ئیمەیڵێکی گەڕانەوەی تێپەڕوشەت بێت. ئەگەر Ù„Û• ئیمەیڵێکیگەڕانەوەی تێپەڕوشە هاتوویت، تکایە دڵنیابە Ù„Û•ÙˆÛ•ÛŒ Ú©Û• URLÛŒ تەواوت بەکارهێناوە Ú©Û• دابینکراوە. + send_instructions: ئەگەر ناونیشانی ئیمەیڵەکەت Ù„Û• بنکەی زانیارێکانماندا هەبێت، Ù„Û• چەند خولەکێکی کەمدا لینکی هێنانەوەی تێپەڕوشە Ù„Û• ناونیشانی ئیمەیلەکەت Ù¾ÛŽ دەگات. تکایە بوخچەی سپامەکەت بکەرەوە، ئەگەر ئەم ئیمەیڵەت پێنەدرا. + send_paranoid_instructions: ئەگەر ناونیشانی ئیمەیڵەکەت Ù„Û• بنکەی زانیارێکانماندا هەبێت، Ù„Û• چەند خولەکێکی کەمدا لینکی هێنانەوەی تێپەڕوشە Ù„Û• ناونیشانی ئیمەیلەکەت Ù¾ÛŽ دەگات. تکایە بوخچەی سپامەکەت بکەرەوە، ئەگەر ئەم ئیمەیڵەت پێنەدرا. + updated: تێپەڕوشەکەت بە سەرکەوتوویی گۆڕدرا. تۆ ئێستاچوویتە ژوورەوە. + updated_not_active: تێپەڕوشەکەت بە سەرکەوتوویی گۆڕدرا. + registrations: + destroyed: خوات Ù„Û•Ú¯Û•Úµ! ئەژمێرەکەت بە سەرکەوتوویی هەڵوەشێنرایەوە. هیوادارین بەزوویی بتبینینەوە. + signed_up: بەخێربێیت! تۆ بە سەرکەوتوویی تۆمار کرای. + signed_up_but_inactive: تۆ بە سەرکەوتوویی تۆمارکرای. هەرچۆنێک بێت، نەمانتوانی چوونە ژوورەوەت بۆ بکەین لەبەرئەوەی هێشتا هەژمارەکەت کارا نەکراوە. + signed_up_but_locked: تۆ بە سەرکەوتوویی تۆمارکرای. هەرچۆنێک بێت، نەمانتوانی چوونە ژوورەوەت بۆ بکەین لەبەرئەوەی هێشتا هەژمارەکەت قوÙÚµ کراوە. + signed_up_but_pending: نامەیەک بە لینکی دووپاتکردنەوە نێردراوە بۆ ناونیشانی ئیمەیڵەکەت. دوای ئەوەی تۆ کرتە لەسەر لینکەکە دەکەیت، ئێمە پێداچوونەوە دەکەین بە بەرنامەکەتدا. ئاگادار دەکرێیت ئەگەر پەسەند کرا. + signed_up_but_unconfirmed: نامەیەک بە لینکی دووپاتکردنەوە نێردراوە بۆ ناونیشانی ئیمەیڵەکەت. تکایە دوای لینکەکە بکەوە بۆ کاراکردنی هەژمارەکەت. تکایە بوخچەی سپامەکەت بکەرەوە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + update_needs_confirmation: تۆ ئەژمێرەکەت بە سەرکەوتوویی نوێکردەوە، بەڵام پێویستە ئیمەیڵە نوێکەت بسەلمێنین. تکایە ئیمەیڵەکەت بپشکنە Ùˆ دوای بەستەری دڵنیابوونەوە بکەوە بۆ دڵنیابوون Ù„Û• ناونیشانی ئیمەیڵە نوێکەت. تکایە بوخچەی سپامەکەت بکەرەوە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + updated: هەژمارەکەت بە سەرکەوتوویی نوێکرایەوە. + sessions: + already_signed_out: چوونە دەرەوە بە سەرکەوتوویی ئەنجام بوو. + signed_in: بە سەرکەوتوویی چوونە ژوورەوە. + signed_out: چوونە دەرەوە بە سەرکەوتوویی ئەنجام بوو. + unlocks: + send_instructions: ئیمەیڵێکت بۆ دەنێردرێت Ù„Û•Ú¯Û•Úµ ڕێنمایی بۆ چۆنیەتی کردنەوەی هەژمارەکەت Ù„Û• چەند خولەکێکدا. تکایە بوخچەی سپامەکەت بپشکنە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + send_paranoid_instructions: ئەگەر هەژمارەکەت بوونی هەبێت، ئیمەیڵێکت پێدەگات Ù„Û•Ú¯Û•Úµ ڕێنمایی چۆنیەتی کردنەوەی Ù„Û• چەند خولەکێکدا. تکایە بوخچەی سپامەکەت بپشکنە ئەگەر ئەم ئیمەیڵەت پێنەدرا. + unlocked: هەژمارەکەت بە سەرکەوتوویی Ù„Û• قوÙÚµ لاچوو. تکایە بچۆ ژوورەوە بۆ بەردەوام بوون. + errors: + messages: + already_confirmed: پێشتر پشتڕاست کرایەوە، تکایە Ù‡Û•ÙˆÚµ دەدە بچۆ ژوورەوە + confirmation_period_expired: پێویستە Ù„Û• Ù†ÛŽÙˆ %{period} دا پشتڕاست بکرێتەوە، تکایە داوای دانەیەکی نوێ بکە + expired: بەسەرچووە، تکایە داوایەکی نوێ بکە + not_found: نەدۆزرایەوە + not_locked: دانەخرابوو + not_saved: + one: 'Ù¡ Ù‡Û•ÚµÛ• قەدەغەکرا ئەم %{resource} Ù„Û• تۆمارکردن:' + other: "%{count} Ù‡Û•ÚµÛ•ÛŒ قەدەغەکرد Ú©Û• %{resource} Ù„Û• پاشکەوتکردن:" diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index 3ab4d9f11711f8a90d20637b9ecef9d269dab6e2..fadc481262b574941c0f5aa1ad64273d9c67b711 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -60,6 +60,23 @@ nl: title: Herstelcodes tweestapsverificatie veranderd unlock_instructions: subject: 'Mastodon: Instructies om opschorten account ongedaan te maken' + webauthn_credential: + added: + explanation: De volgende beveiligingssleutel is aan uw account toegevoegd + subject: 'Mastodon: Nieuwe beveiligingssleutel' + title: Een nieuwe beveiligingssleutel is toegevoegd + deleted: + explanation: De volgende beveiligingssleutel is uit jouw account verwijderd + subject: 'Mastodon: Beveiligingssleutel verwijderd' + title: Een van jouw beveiligingssleutels is verwijderd + webauthn_disabled: + explanation: Verificatie met beveiligingssleutels is uitgeschakeld voor jouw account. Inloggen is nu alleen mogelijk met het gebruik van een door een gepaarde TOTP-app genereerde sleutel. + subject: 'Mastodon: Verificatie met beveiligingssleutels is uitgeschakeld' + title: Beveiligingssleutels uitgeschakeld + webauthn_enabled: + explanation: Verificatie met beveiligingssleutels is ingeschakeld voor jouw account. Jouw beveiligingssleutel kan nu gebruikt worden om in te loggen. + subject: 'Mastodon: Verificatie met beveiligingssleutels is ingeschakeld' + title: Beveiligingssleutels ingeschakeld omniauth_callbacks: failure: Kon je niet inloggen met jouw %{kind} account, omdat "%{reason}". success: Succesvol met jouw %{kind} account ingelogd. diff --git a/config/locales/devise.nn.yml b/config/locales/devise.nn.yml index 42eb0690aabe9e0402f1043fb17408a9d5a3e812..88d8458f7bd5a26d123ba054bae62e95d52cdbcd 100644 --- a/config/locales/devise.nn.yml +++ b/config/locales/devise.nn.yml @@ -60,6 +60,21 @@ nn: title: 2FA-gjenopprettingskodane er endra unlock_instructions: subject: 'Mastodon: Instruksjonar for Ã¥ opne kontoen igjen' + webauthn_credential: + added: + explanation: Følgende sikkerhetsnøkkel har blitt lagt til i kontoen din + subject: 'Mastodon: Ny sikkerhetsnøkkel' + title: En ny sikkerhetsnøkkel har blitt lagt til + deleted: + explanation: Følgende sikkerhetsnøkkel har blitt slettet fra kontoen din + subject: 'Mastodon: Sikkerhetsnøkkel slettet' + title: En av sikkerhetsnøklene dine har blitt slettet + webauthn_disabled: + subject: 'Mastodon: Autentisering med sikkerhetsnøkler ble skrudd av' + title: Sikkerhetsnøkler deaktivert + webauthn_enabled: + subject: 'Mastodon: Sikkerhetsnøkkelsautentisering ble skrudd pÃ¥' + title: Sikkerhetsnøkler aktivert omniauth_callbacks: failure: Du kunne ikkje verte autentisert frÃ¥ %{kind} av di "%{reason}". success: Autentisert frÃ¥ %{kind}-konto. diff --git a/config/locales/devise.no.yml b/config/locales/devise.no.yml index de651f6ca4efbc073ba0e28001bebf9840203144..4fdc1276b55cb3fa8293bf4735a02ba53520993a 100644 --- a/config/locales/devise.no.yml +++ b/config/locales/devise.no.yml @@ -60,6 +60,21 @@ title: 2FA-gjenopprettingskodene ble endret unlock_instructions: subject: 'Mastodon: Instruksjoner for Ã¥ gjenÃ¥pne konto' + webauthn_credential: + added: + explanation: Følgende sikkerhetsnøkkel har blitt lagt til i kontoen din + subject: 'Mastodon: Ny sikkerhetsnøkkel' + title: En ny sikkerhetsnøkkel har blitt lagt til + deleted: + explanation: Følgende sikkerhetsnøkkel har blitt slettet fra kontoen din + subject: 'Mastodon: Sikkerhetsnøkkel slettet' + title: En av sikkerhetsnøklene dine har blitt slettet + webauthn_disabled: + subject: 'Mastodon: Autentisering med sikkerhetsnøkler ble skrudd av' + title: Sikkerhetsnøkler deaktivert + webauthn_enabled: + subject: 'Mastodon: Sikkerhetsnøkkelsautentisering ble skrudd pÃ¥' + title: Sikkerhetsnøkler aktivert omniauth_callbacks: failure: Kunne ikke autentisere deg fra %{kind} fordi "%{reason}". success: Vellykket autentisering fra %{kind}. diff --git a/config/locales/devise.oc.yml b/config/locales/devise.oc.yml index 0fb259429a23bcc7fc6b2bba70a983f81f867ceb..16419cd1e343434b2b11ca352f01a24d13e93dd2 100644 --- a/config/locales/devise.oc.yml +++ b/config/locales/devise.oc.yml @@ -60,6 +60,23 @@ oc: title: Còdis 2FA de recuperacion cambiats unlock_instructions: subject: Mastodon : consignas de desblocatge + webauthn_credential: + added: + explanation: La clau de seguretat seguenta foguèt ajustada a vòstre compte + subject: 'Mastodon : nòva clau de seguretat' + title: Una nòva clau de seguretat es estada ajustada + deleted: + explanation: La clau de seguretat seguenta foguèt suprimida a vòstre compte + subject: 'Mastodon : clau de seguretat suprimida' + title: Una de vòstras claus de seguretats es estada suprimida + webauthn_disabled: + explanation: L’autentificacion amb de claus de seguretat foguèt estada desactivada per vòstre compte. L’identificacion es ara possible en utilizan un geton generat per una aplicacion TOTP associada. + subject: 'Mastodon : autentificacion amb claus de seguretat desactivada' + title: Claus de seguretat desactivadas + webauthn_enabled: + explanation: L’autentificacion amb de claus de seguretat foguèt estada activada per vòstre compte. Vòstra clau de seguretat pòt ara èsser utilizada per l’identificacion. + subject: 'Mastodon : autentificacion via clau de seguretat activada' + title: Claus de seguretat activadas omniauth_callbacks: failure: Fracà s al moment de vos autentificar de %{kind} perque "%{reason}". success: Sètz ben autentificat dempuèi lo compte %{kind}. diff --git a/config/locales/devise.pl.yml b/config/locales/devise.pl.yml index 6336a579435c9acf470fb012bcb43c4821eb0c60..cc1b670bb88c21b81c6966c358e16bcaa9eb34aa 100644 --- a/config/locales/devise.pl.yml +++ b/config/locales/devise.pl.yml @@ -60,6 +60,23 @@ pl: title: Zmieniono kody odzyskiwania 2FA unlock_instructions: subject: 'Mastodon: Instrukcje odblokowania konta' + webauthn_credential: + added: + explanation: NastÄ™pujÄ…cy klucz bezpieczeÅ„stwa zostaÅ‚ dodany do twojego konta + subject: 'Mastodon: Nowy klucz bezpieczeÅ„stwa' + title: Dodano nowy klucz bezpieczeÅ„stwa + deleted: + explanation: NastÄ™pujÄ…cy klucz bezpieczeÅ„stwa zostaÅ‚ usuniÄ™ty z Twojego konta + subject: 'Mastodon: Klucz bezpieczeÅ„stwa usuniÄ™ty' + title: UsuniÄ™to jeden z twoich kluczy bezpieczeÅ„stwa + webauthn_disabled: + explanation: Uwierzytelnianie kluczem bezpieczeÅ„stwa zostaÅ‚o wyłączone dla Twojego konta. Logowanie jest teraz możliwe tylko przy użyciu tokenu generowanego przez sparowanÄ… aplikacjÄ™ TOTP. + subject: 'Mastodon: Wyłączono uwierzytelnianie z kluczami bezpieczeÅ„stwa' + title: Wyłączono klucze bezpieczeÅ„stwa + webauthn_enabled: + explanation: Uwierzytelnianie klucza bezpieczeÅ„stwa zostaÅ‚o włączone dla Twojego konta. Klucz bezpieczeÅ„stwa może być teraz wykorzystywany do logowania. + subject: 'Mastodon: Włączono uwierzytelnianie z kluczami bezpieczeÅ„stwa' + title: Włączono klucze bezpieczeÅ„stwa omniauth_callbacks: failure: 'Uwierzytelnienie przez %{kind} nie powiodÅ‚o siÄ™, ponieważ: "%{reason}".' success: Uwierzytelnienie przez %{kind} powiodÅ‚o siÄ™. diff --git a/config/locales/devise.pt-BR.yml b/config/locales/devise.pt-BR.yml index bb5d5d34b6728f6f58f11584c8422ba498c1fc42..6fecaecdf5baef7629299e5408fa064f5740d8b4 100644 --- a/config/locales/devise.pt-BR.yml +++ b/config/locales/devise.pt-BR.yml @@ -60,6 +60,23 @@ pt-BR: title: Códigos de recuperação de dois fatores alterados unlock_instructions: subject: 'Mastodon: Instruções de desbloqueio' + webauthn_credential: + added: + explanation: A seguinte chave de segurança foi adicionada à sua conta + subject: 'Mastodon: Nova chave de segurança' + title: Uma nova chave de segurança foi adicionada + deleted: + explanation: A seguinte chave de segurança foi excluÃda da sua conta + subject: 'Mastodon: Chave de segurança excluÃda' + title: Uma das suas chaves de segurança foi excluÃda + webauthn_disabled: + explanation: A autenticação por chaves de segurança foi desabilitada para a sua conta. O login agora é possÃvel usando apenas o token gerado pelo aplicativo TOTP pareado. + subject: 'Mastodon: Autenticação por chaves de segurança desabilitada' + title: Chaves de segurança desabilitadas + webauthn_enabled: + explanation: A autenticação por chave de segurança foi habilitada para a sua conta. Sua chave de segurança agora pode ser usada para fazer login. + subject: 'Mastodon: Autenticação por chave de segurança habilitada' + title: Chaves de segurança habilitadas omniauth_callbacks: failure: Não foi possÃvel entrar como %{kind} porque "%{reason}". success: Entrou como %{kind}. diff --git a/config/locales/devise.pt-PT.yml b/config/locales/devise.pt-PT.yml index 935189a16791a92e9ee7438b3dd2e7d206a34a1d..496ce7b1ddb7cd133216068526c1bd9e8985e39f 100644 --- a/config/locales/devise.pt-PT.yml +++ b/config/locales/devise.pt-PT.yml @@ -60,6 +60,23 @@ pt-PT: title: Códigos de recuperação 2FA alterados unlock_instructions: subject: 'Mastodon: Instruções para desbloquear a tua conta' + webauthn_credential: + added: + explanation: A seguinte chave de segurança foi adicionada à sua conta + subject: 'Mastodon: Nova chave de segurança' + title: Foi adicionada uma nova chave de segurança + deleted: + explanation: A seguinte chave de segurança foi removida da sua conta + subject: 'Mastodon: Chave de segurança removida' + title: Uma das suas chaves de segurança foi removida + webauthn_disabled: + explanation: A autenticação com chave de segurança foi desativada para sua conta. É agora possÃvel aceder à sua conta utilizando apenas o token gerado pelo aplicativo TOTP pareado. + subject: 'Mastodon: Autenticação com chave de segurança desativada' + title: Chaves de segurança desativadas + webauthn_enabled: + explanation: A autenticação com chave de segurança foi ativada para sua conta. A sua chave de segurança pode agora ser utilizada para aceder à sua conta. + subject: 'Mastodon: Autenticação com chave de segurança ativada' + title: Chaves de segurança ativadas omniauth_callbacks: failure: Não foi possÃvel autenticar %{kind} porque "%{reason}". success: Autenticado com sucesso na conta %{kind}. diff --git a/config/locales/devise.ru.yml b/config/locales/devise.ru.yml index f1f6cb365c14a395db005e5a284362ac93432e71..ada7867f2daee3b7235e8af60a5c527c15b6f6fa 100644 --- a/config/locales/devise.ru.yml +++ b/config/locales/devise.ru.yml @@ -60,6 +60,23 @@ ru: title: Резервные коды 2ФРизменены unlock_instructions: subject: 'Mastodon: ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ Ð¿Ð¾ разблокировке' + webauthn_credential: + added: + explanation: Следующий ключ безопаÑноÑти был добавлен в вашу учётную запиÑÑŒ + subject: 'МаÑтодон: Ðовый ключ безопаÑноÑти' + title: Был добавлен новый ключ безопаÑноÑти + deleted: + explanation: Следующий ключ безопаÑноÑти был удален из вашей учётной запиÑи + subject: 'МаÑтодон: Ключ БезопаÑноÑти удален' + title: Один из ваших защитных ключей был удален + webauthn_disabled: + explanation: ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключей безопаÑноÑти отключена Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учётной запиÑи. Теперь вход возможен Ñ Ð¸Ñпользованием только токена, Ñгенерированного в приложении TOTP. + subject: 'МаÑтодон: ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ ÐºÐ»ÑŽÑ‡Ð°Ð¼Ð¸ безопаÑноÑти отключена' + title: Ключи безопаÑноÑти отключены + webauthn_enabled: + explanation: Ð”Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учётной запиÑи включена Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ ключу безопаÑноÑти. Теперь ваш ключ безопаÑноÑти может быть иÑпользован Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°. + subject: 'МаÑтодон: Включена Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ ключу безопаÑноÑти' + title: Ключи безопаÑноÑти включены omniauth_callbacks: failure: Ðе получилоÑÑŒ аутентифицировать Ð²Ð°Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %{kind} по Ñледующей причине - "%{reason}". success: ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ учётной запиÑи %{kind} прошла уÑпешно. diff --git a/config/locales/devise.sa.yml b/config/locales/devise.sa.yml new file mode 100644 index 0000000000000000000000000000000000000000..07ea4372a3a109674214ba80f2070c9f99fb872d --- /dev/null +++ b/config/locales/devise.sa.yml @@ -0,0 +1 @@ +sa: diff --git a/config/locales/devise.sc.yml b/config/locales/devise.sc.yml index 91bd6d92f04580bfea64f85ac0291ed4a4c1fb7c..0256c4674b2ed8d22469b4d3f67283be927fdda9 100644 --- a/config/locales/devise.sc.yml +++ b/config/locales/devise.sc.yml @@ -1 +1,115 @@ +--- sc: + devise: + confirmations: + confirmed: S'indiritzu tuo de posta eletrònica est istadu cunfirmadu. + send_instructions: As a retzire unu messà giu de posta eletrònica cun is istrutziones pro sa cunfirma de s'indiritzu de posta eletrònica tra pagos minutos. Controlla sa cartella de s'arga si no as retzidu custu messà giu de posta eletrònica. + send_paranoid_instructions: Si s'indiritzu de posta eletrònica tuo esistit in sa base de datos nostra, as a retzire unu messà giu de posta eletrònica cun is istrutziones pro sa cunfirma de s'indiritzu de posta eletrònica tra pagos minutos. Controlla sa cartella de s'à liga si no as retzidu custu messà giu de posta eletrònica. + failure: + already_authenticated: Ses giai intradu. + inactive: Su contu tuo no est ancora ativadu. + invalid: "%{authentication_keys} o crae de intrada non và lida." + last_attempt: Tenes ancora un'à teru tentativu, in antis chi su contu tuo bèngiat blocadu. + locked: Su contu tuo est blocadu. + not_found_in_database: "%{authentication_keys} o crae de intrada non và lida." + pending: Su contu tuo est ancora in revisione. + timeout: Sa sessione tua est iscadida. Torra·bi a intrare pro sighire. + unauthenticated: Tocat a ti autenticare o ti registrare prima de sighire. + unconfirmed: Deves cunfirmare s'indiritzu tuo de posta eletrònica prima de sighire. + mailer: + confirmation_instructions: + action: Verìfica s'indiritzu de posta eletrònica + action_with_app: Cunfirma e torra a %{app} + explanation: As creadu unu contu in %{host} cun custu indiritzu de posta eletrònica. T'ammancat unu clic pro s'ativatzione. Si non fias tue, non cà rcules custu messà giu de posta eletrònica. + explanation_when_pending: As pedidu un'invitu a %{host} cun custu indiritzu de posta eletrònica. Cunfirmadu s'indiritzu de posta eletrònica, amus a revisionare sa dimanda tua. Podes intrare pro cambiare is detà llios o cantzellare su contu tuo, ma non podes atzèdere a sa majoria de is funtziones finas a chi su contu tuo siat aprovadu. Si sa dimanda tua est refudada, is datos ant a èssere bogados, duncas no t'ant a pedire prus peruna atzione. Si non fias tue, non cà rcules custu messà giu de posta eletrònica. + extra_html: Verìfica puru <a href="%{terms_path}">is règulas de su server</a> e <a href="%{policy_path}">is cunditziones de servìtziu nostras</a>. + subject: 'Mastodon: Istrutziones de cunfirma pro %{instance}' + title: Verìfica s'indiritzu de posta eletrònica + email_changed: + explanation: 'Custu indiritzu de posta eletrònica pro su contu tuo est istadu mudadu a:' + extra: Si no as mudadu indiritzu de posta, forsis un'à tera persone at otentu s'atzessu de su contu tuo. Muda sa crae tua a sa lestra o chistiona cun s'amministratzione de su server si ses blocadu a foras dae su contu tuo. + subject: 'Mastodon: Indiritzu de posta mudadu' + title: Indiritzu de posta eletrònica nou + password_change: + explanation: Sa crae de su contu tuo est istada mudada. + extra: Si no as mudadu sa crae tua, forsis un'à tera persone at otentu s'atzessu de su contu tuo. Muda sa crae tua a sa lestra o chistiona cun s'amministratzione de su server si ses blocadu a foras dae su contu tuo. + subject: 'Mastodon: Crae mudada' + title: Crae mudada + reconfirmation_instructions: + explanation: Cunfirma s'indiritzu nou pro mudare s'indiritzu de posta eletrònica. + extra: Si custa muda no dd'as pedida tue, non cà rcules custu messà giu de posta eletrònica. Custu indiritzu de posta eletrònica pro su contu de Mastodon no at a mudare finas a s'atzessu tuo a su ligà mene in subra. + subject: 'Mastodon: Cunfirma indiritzu de posta eletrònica pro %{instance}' + title: Verìfica s'indiritzu de posta eletrònica + reset_password_instructions: + action: Muda sa crae + explanation: As pedidu una crae noa pro su contu tuo. + extra: Si no dd'as pedida tue, non cà rcules custu messà giu de posta eletrònica. Custa crae no at a mudare finas a s'atzessu tuo a su ligà mene in subra pro sa creatzione de una noa. + subject: 'Mastodon: Istrutziones pro resetare sa crae' + title: Crae resetada + two_factor_disabled: + explanation: S'autenticatzione a duos fatores est istada disativada pro su contu tuo. Immoe podes intrare impreende isceti indiritzu de posta eletrònica e crae. + subject: 'Mastodon: Autenticatzione a duos fatores disativada' + title: 2FA disativada + two_factor_enabled: + explanation: S'autenticatzione a duos fatores est istada ativada pro su contu tuo. Pro s'atzessu at èssere rechèdidu unu còdighe de autorizatzione generadu dae s'aplicatzione TOTP. + subject: 'Mastodon: Autenticatzione a duos fatores ativada' + title: 2FA ativada + two_factor_recovery_codes_changed: + explanation: Is còdighes de recùperu betzos sunt istados disativados e à teros noos generados. + subject: 'Mastodon: Còdighes de recùperu a duos fatores re-generados' + title: còdighes de recùperu 2FA mudados + unlock_instructions: + subject: 'Mastodon: Istrutziones pro s''isblocu' + webauthn_credential: + added: + explanation: Sa crae de seguresa chi sighit est istada agiunta a su contu tuo + subject: 'Mastodon: Crae de seguresa noa' + title: Est istada agiunta una crae de seguresa noa + deleted: + explanation: Sa crae de seguresa chi sighit est istada cantzellada dae su contu tuo + subject: 'Mastodon: Crae de seguresa cantzellada' + title: Una de is craes de seguresa tuas est istada cantzellada + webauthn_disabled: + explanation: S'autenticatzione cun craes de seguresa est istada disabilitada pro su contu tuo. S'intrada como est possìbile impreende isceti su getone ingendradu dae s'aplicatzione TOTP ligada. + subject: 'Mastodon: Autenticatzione cun craes de seguresa disabilitada' + title: Craes de seguresa disabilitadas + webauthn_enabled: + explanation: S'autenticatzione cun crae de seguresa est istada abilitada pro su contu tuo. Sa crae de seguresa tua como si podet èssere impreare pro intrare. + subject: 'Mastodon: Autenticatzione cun sa crae de seguresa ativada' + title: Craes de seguresa abilitadas + omniauth_callbacks: + failure: Autenticatzione dae %{kind} fallida, ca "%{reason}". + success: Autenticadu dae su contu de %{kind}. + passwords: + no_token: No podes intrare a custa pà gina chene passare dae unu messà giu de posta eletrònica pro resetare sa crae. Si benes dae su messà giu de posta pro resetare sa crae, faghe in modu de impreare s'URL intreu chi t'ant donadu. + send_instructions: Si s'indiritzu de posta eletrònica tuo esistit in sa base de datos nostra, as a retzire una unu ligà mene de recùperu de sa crae a s'indiritzu tuo de posta eletrònica tra pagos minutos. Controlla sa cartella de s'à liga si no as retzidu custu messà giu de posta eletrònica. + send_paranoid_instructions: Si s'indiritzu de posta eletrònica tuo esistit in sa base de datos nostra, as a retzire una unu ligà mene de recùperu de sa crae a s'indiritzu tuo de posta eletrònica tra pagos minutos. Controlla sa cartella de s'à liga si no as retzidu custu messà giu de posta eletrònica. + updated: Sa crae tua est istada mudada. Immoe ses intradu. + updated_not_active: Sa crae tua est istada mudada. + registrations: + destroyed: A si bìdere! Su contu tuo est istadu cantzelladu. Isperamus de ti torrare a bìdere chitzi. + signed_up: Registratzione curreta. Ti donamus sa benebènnida! + signed_up_but_inactive: Registratzione curreta. Mancari de aici, si no ti faghimus intrare est ca su contu tuo no est ancora ativu. + signed_up_but_locked: Registratzione curreta. Mancari de aici, si no ti faghimus intrare est ca su contu tuo est blocadu. + signed_up_but_pending: Unu ligà mene de cunfirma est istadu imbiadu a s'indiritzu tuo de posta eletrònica. A pustis chi incarcas in su ligà mene, amus a revisionare sa dimanda tua. Si aprovada, t'at a arribare una notìfica. + signed_up_but_unconfirmed: Unu ligà mene de cunfirma est istadu imbiadu a s'indiritzu tuo de posta eletrònica. Sighi su ligà mene pro ativare su contu tuo. Controlla sa cartella de s'arga si no as retzidu custu messà giu de posta eletrònica. + update_needs_confirmation: Su contu tuo est istadu atualizadu, ma devimus verificare s'indiritzu tuo de posta eletrònica nou. Controlla sa posta eletrònica e sighi su ligà mene pro cunfirmare s'indiritzu nou de posta eletrònica. Controlla sa cartella de s'à liga si no as retzidu custu messà giu de posta eletrònica. + updated: Su contu tuo est istadu atualizadu. + sessions: + already_signed_out: Sessione serrada. + signed_in: Atzessu curretu. + signed_out: Sessione serrada. + unlocks: + send_instructions: As a retzire unu messà giu de posta eletrònica cun is istrutziones pro isblocare su contu tuo tra pagos minutos. Controlla sa cartella de s'arga si no as retzidu custu messà giu de posta eletrònica. + send_paranoid_instructions: Si su contu tuo esistit, as a retzire unu messà giu de posta eletrònica cun istrutziones pro ddu isblocare tra pagos minutos. Controlla sa cartella de s'arga si no as retzidu custu messà giu de posta eletrònica. + unlocked: Su contu tuo est istadu isblocadu. Intra pro sighire. + errors: + messages: + already_confirmed: fiat giai cunfirmadu, proa a intrare + confirmation_period_expired: tocat a ddu cunfirmare intro %{period}, pedi·nde unu nou + expired: est iscadidu, pedi·nde unu nou + not_found: no agatadu + not_locked: no fiat blocadu + not_saved: + one: '1 faddina at proibidu de sarvare custu %{resource}:' + other: "%{count} faddinas ant proibidu de sarvare %{resource}:" diff --git a/config/locales/devise.sq.yml b/config/locales/devise.sq.yml index 5dc8aa04305f6e2220c243b6006dabac014123da..97b97ce481f904d51a0f1583a6bc48aa90c3d09a 100644 --- a/config/locales/devise.sq.yml +++ b/config/locales/devise.sq.yml @@ -60,6 +60,23 @@ sq: title: Kodet e rikthimit 2FA u ndryshuan unlock_instructions: subject: 'Mastodon: Udhëzime shkyçjeje' + webauthn_credential: + added: + explanation: Kyçi vijues i sigurisë është shtuar te llogaria juaj + subject: 'Mastodon: Kyç i ri sigurie' + title: U shtua një kyç i ri sigurie + deleted: + explanation: Kyçi vijues i sigurisë është fshirë prej llogarisë tuaj + subject: 'Mastodon: Fshirje kyçi sigurie' + title: Një nga kyçet tuaj të sigurisë është fshirë + webauthn_disabled: + explanation: Mirëfilltësimi me kyçe sigurie është çaktivizuar për llogarinë tuaj. Hyrja tani është e mundshme vetëm duke përdorur token-in e prodhuar nga aplikacioni TOTP i çiftuar. + subject: 'Mastodon: U çaktivizua mirëfilltësimi me kyçe sigurie' + title: U çaktivizuan kyçe sigurie + webauthn_enabled: + explanation: Mirëfilltësimi përmes kyçesh sigurie është aktivizuar për llogarinë tuaj. Tani, për hyrje mund të përdoren kyçet tuaj të sigurisë. + subject: 'Mastodon: U aktivizua mirëfilltësim me kyçe sigurie' + title: U aktivizuan kyçe sigurie omniauth_callbacks: failure: S’u bë dot mirëfilltësimi juaj nga %{kind}, sepse "%{reason}". success: Mirëfilltësimi nga llogaria %{kind} u bë me sukses. diff --git a/config/locales/devise.sv.yml b/config/locales/devise.sv.yml index 9dfdde8e5610388aef3005376dccf2559fa8103e..071f00878c93c72d3923b208cc4fc57d93461eb8 100644 --- a/config/locales/devise.sv.yml +++ b/config/locales/devise.sv.yml @@ -21,6 +21,7 @@ sv: action: Verifiera e-postadress action_with_app: Bekräfta och Ã¥tergÃ¥ till %{app} explanation: Du har skapat ett konto pÃ¥ %{host} med den här e-postadressen. Du är ett klick bort frÃ¥n att aktivera det. Om det inte var du ignorerar det här e-postmeddelandet. + explanation_when_pending: Du ansökte om en inbjudan till %{host} med denna e-postadress. När du har bekräftat din e-postadress kommer vi att granska din ansökan. Du kan logga in för att ändra dina uppgifter eller ta bort ditt konto, men du kan inte komma Ã¥t de flesta funktionerna förrän ditt konto har godkänts. Om din ansökan avvisas kommer dina uppgifter att tas bort, sÃ¥ ingen ytterligare Ã¥tgärd kommer att krävas av dig. Om detta inte var du, vänligen ignorera detta mail. extra_html: Kolla gärna ocksÃ¥ <a href="%{terms_path}">instansens regler</a> och <a href="%{policy_path}">vÃ¥ra användarvillkor</a>. subject: 'Mastodon: Bekräftelsesinstruktioner för %{instance}' title: Verifiera e-postadress @@ -59,6 +60,18 @@ sv: title: 2FA-Ã¥terställningskoder ändrades unlock_instructions: subject: 'Mastodon: LÃ¥s upp instruktioner' + webauthn_credential: + added: + subject: 'Mastodon: Ny säkerhetsnyckel' + title: En ny säkerhetsnyckel har lagts till + deleted: + explanation: Följande säkerhetsnyckel har tagits bort frÃ¥n ditt konto + subject: 'Mastodon: Säkerhetsnyckeln borttagen' + title: En av dina säkerhetsnycklar har tagits bort + webauthn_disabled: + title: Säkerhetsnycklar inaktiverade + webauthn_enabled: + title: Säkerhetsnycklar aktiverade omniauth_callbacks: failure: Det gick inte att autentisera dig frÃ¥n %{kind} för "%{reason}". success: Autentiserad frÃ¥n %{kind} konto. @@ -73,6 +86,7 @@ sv: signed_up: Välkommen! Du har nu registrerat dig. signed_up_but_inactive: Du har nu registrerat dig. Vi kunde dock inte logga in dig eftersom ditt konto ännu inte är aktiverat. signed_up_but_locked: Du har nu registrerat dig. Vi kunde dock inte logga in eftersom ditt konto är lÃ¥st. + signed_up_but_pending: Ett meddelande med en bekräftelselänk har skickats till din e-postadress. När du klickar pÃ¥ länken kommer vi att granska din ansökan. Du kommer att meddelas om den godkänns. signed_up_but_unconfirmed: Ett meddelande med en bekräftelselänk har skickats till din e-postadress. Vänligen följ länken för att aktivera ditt konto. Kontrollera din skräppostmapp om du inte fick det här e-postmeddelandet. update_needs_confirmation: Du har uppdaterat ditt konto med framgÃ¥ng, men vi mÃ¥ste verifiera din nya e-postadress. Vänligen kolla din email och följ bekräfta länken för att bekräfta din nya e-postadress. Kontrollera din spammapp om du inte fick det här e-postmeddelandet. updated: Ditt konto har uppdaterats utan problem. diff --git a/config/locales/devise.th.yml b/config/locales/devise.th.yml index c88577a9703c2559a385b097cfde4c3cd5b197a2..371a497ad6713b71e05e553b4baa3839be375130 100644 --- a/config/locales/devise.th.yml +++ b/config/locales/devise.th.yml @@ -60,6 +60,20 @@ th: title: เปลี่ยนรหัสà¸à¸¹à¹‰à¸„ืน 2FA à¹à¸¥à¹‰à¸§ unlock_instructions: subject: 'Mastodon: คำà¹à¸™à¸°à¸™à¸³à¸à¸²à¸£à¸›à¸¥à¸”ล็à¸à¸„' + webauthn_credential: + added: + explanation: เพิ่มà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยดังต่à¸à¹„ปนี้ไปยังบัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณà¹à¸¥à¹‰à¸§ + subject: 'Mastodon: à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยใหม่' + title: เพิ่มà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยใหม่à¹à¸¥à¹‰à¸§ + deleted: + explanation: ลบà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยดังต่à¸à¹„ปนี้à¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณà¹à¸¥à¹‰à¸§ + subject: 'Mastodon: ลบà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยà¹à¸¥à¹‰à¸§' + webauthn_disabled: + subject: 'Mastodon: ปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยà¹à¸¥à¹‰à¸§' + title: ปิดใช้งานà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยà¹à¸¥à¹‰à¸§ + webauthn_enabled: + subject: 'Mastodon: เปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยà¹à¸¥à¹‰à¸§' + title: เปิดใช้งานà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยà¹à¸¥à¹‰à¸§ omniauth_callbacks: failure: ไม่สามารถรับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸‚à¸à¸‡à¸„ุณจาภ%{kind} เนื่à¸à¸‡à¸ˆà¸²à¸ "%{reason}" success: รับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µ %{kind} สำเร็จ @@ -88,7 +102,7 @@ th: unlocked: ปลดล็à¸à¸„บัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณสำเร็จ โปรดลงชื่à¸à¹€à¸‚้าเพื่à¸à¸”ำเนินà¸à¸²à¸£à¸•่ภerrors: messages: - already_confirmed: ยืนยันà¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ โปรดลà¸à¸‡à¸¥à¸‡à¸Šà¸·à¹ˆà¸à¹€à¸‚้า + already_confirmed: ได้รับà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¹„ปà¹à¸¥à¹‰à¸§ โปรดลà¸à¸‡à¸¥à¸‡à¸Šà¸·à¹ˆà¸à¹€à¸‚้า confirmation_period_expired: ต้à¸à¸‡à¹„ด้รับà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸ ายใน %{period} โปรดขà¸à¸à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¸¡à¹ˆ expired: หมดà¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ โปรดขà¸à¸à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¸¡à¹ˆ not_found: ไม่พบ diff --git a/config/locales/devise.tr.yml b/config/locales/devise.tr.yml index 30cedc1fc92f3514f1efa5854d8cf51c54e8b105..a0bc7deaed5ab1e4f9407f0e56bfd0bdc000e029 100644 --- a/config/locales/devise.tr.yml +++ b/config/locales/devise.tr.yml @@ -10,7 +10,7 @@ tr: inactive: Hesabınız henüz etkinleÅŸtirilmedi. invalid: Geçersiz %{authentication_keys} ya da ÅŸifre. last_attempt: Hesabınız kilitlenmeden önce bir kez daha denemeniz gerekir. - locked: Hesabınız kilitli. + locked: Hesabınız kilitlendi. not_found_in_database: Geçersiz %{authentication_keys} ya da ÅŸifre. pending: Hesabınız hala inceleniyor. timeout: Oturum süreniz sona erdi. Lütfen devam etmek için tekrar giriÅŸ yapınız. @@ -19,7 +19,7 @@ tr: mailer: confirmation_instructions: action: E-posta adresinizi doÄŸrulayın - action_with_app: Onayla ve %{app}'a dön + action_with_app: Onayla ve %{app} uygulamasına geri dön explanation: Bu e-posta adresiyle %{host} bir hesap oluÅŸturdunuz. EtkinleÅŸtirmekten bir tık uzaktasınız. Bu siz deÄŸilseniz, lütfen bu e-postayı dikkate almayın. explanation_when_pending: Bu e-posta adresiyle %{host} adresine bir davetiye için baÅŸvuru yaptınız. E-posta adresinizi onayladıktan sonra baÅŸvurunuzu inceleyeceÄŸiz. O zamana kadar giriÅŸ yapamazsınız. BaÅŸvurunuz reddedilirse, verileriniz silinecek, baÅŸka bir iÅŸlem yapmanız gerekmeyecek. Bu siz deÄŸilseniz, lütfen bu e-postayı dikkate almayın. extra_html: Lütfen ayrıca <a href="%{terms_path}">sunucu kurallarını</a> ve <a href="%{policy_path}">hizmet ÅŸartlarımızı</a> inceleyin. @@ -28,38 +28,55 @@ tr: email_changed: explanation: 'Hesabınızın e-posta adresi ÅŸu ÅŸekilde deÄŸiÅŸtirildi:' extra: E-posta adresinizi deÄŸiÅŸtirmediyseniz, büyük olasılıkla birileri hesabınıza eriÅŸti. Lütfen derhal parolanızı deÄŸiÅŸtirin veya hesabınız kilitlendiyse sunucu yöneticisine baÅŸvurun. - subject: 'Mastodon: E-posta deÄŸiÅŸti' + subject: 'Mastodon: E-posta adresi deÄŸiÅŸti' title: Yeni e-posta adresi password_change: - explanation: Hesabınızın parolası deÄŸiÅŸtirildi. + explanation: Hesabınızın ÅŸifresi deÄŸiÅŸtirildi. extra: Parolanızı deÄŸiÅŸtirmediyseniz, büyük olasılıkla birileri hesabınıza eriÅŸmiÅŸ olabilir. Lütfen derhal parolanızı deÄŸiÅŸtirin veya hesabınız kilitlendiyse sunucu yöneticisine baÅŸvurun. - subject: 'Mastodon: Parola deÄŸiÅŸtirildi' - title: Parola deÄŸiÅŸtirildi + subject: 'Mastodon: Åžifre deÄŸiÅŸtirildi' + title: Åžifre deÄŸiÅŸtirildi reconfirmation_instructions: explanation: E-postanızı deÄŸiÅŸtirmek için yeni adresi onaylayın. extra: Bu deÄŸiÅŸiklik sizin tarafınızdan baÅŸlatılmadıysa, lütfen bu e-postayı dikkate almayın. Mastodon hesabının e-posta adresi, yukarıdaki baÄŸlantıya eriÅŸene kadar deÄŸiÅŸmez. subject: 'Mastodon: %{instance} için e-postayı onayla' title: E-posta adresinizi doÄŸrulayın reset_password_instructions: - action: Parolayı deÄŸiÅŸtir - explanation: Hesabınız için yeni bir parola istediniz. + action: Åžifreyi deÄŸiÅŸtir + explanation: Hesabınız için yeni bir ÅŸifre istediniz. extra: Bunu siz yapmadıysanız, lütfen bu e-postayı dikkate almayın. Parolanız yukarıdaki baÄŸlantıya eriÅŸene ve yeni bir tane oluÅŸturuncaya kadar deÄŸiÅŸmez. - subject: 'Mastodon: Parola sıfırlama talimatları' - title: Parola sıfırlama + subject: 'Mastodon: Åžifre sıfırlama talimatları' + title: Åžifre sıfırlama two_factor_disabled: explanation: Hesabınız için iki-adımlı kimlik doÄŸrulama devre dışı bırakıldı. Åžimdi sadece e-posta adresi ve parola kullanarak giriÅŸ yapabilirsiniz. subject: 'Mastodon: İki-adımlı kimlik doÄŸrulama devre dışı bırakıldı' title: 2FA devre dışı bırakıldı two_factor_enabled: explanation: Hesabınız için iki-adımlı kimlik doÄŸrulama etkinleÅŸtirildi. GiriÅŸ yapmak için eÅŸleÅŸtirilmiÅŸ TOTP uygulaması tarafından oluÅŸturulan bir belirteç gereklidir. - subject: 'Mastodon: İki-adımlı kimlik doÄŸrulama etkinleÅŸtirildi' + subject: 'Mastodon: İki adımlı kimlik doÄŸrulama etkinleÅŸtirildi' title: 2FA etkinleÅŸtirildi two_factor_recovery_codes_changed: explanation: Önceki kurtarma kodları geçersiz kılındı ve yenileri oluÅŸturuldu. - subject: 'Mastodon: İki-adımlı kurtarma kodları yeniden oluÅŸturuldu' + subject: 'Mastodon: İki adımlı kurtarma kodları yeniden oluÅŸturuldu' title: 2FA kurtarma kodları deÄŸiÅŸtirildi unlock_instructions: - subject: 'Mastodon: Engel kaldırma talimatları' + subject: 'Mastodon: Kilit açma talimatları' + webauthn_credential: + added: + explanation: AÅŸağıdaki güvenlik anahtarı hesabınıza eklendi + subject: 'Mastodon: Yeni güvenlik anahtarı' + title: Yeni bir güvenlik anahtarı eklendi + deleted: + explanation: AÅŸağıdaki güvenlik anahtarı hesabınızdan silindi + subject: 'Mastodon: Güvenlik anahtarı silindi' + title: Güvenlik anahtarlarınızdan biri silindi + webauthn_disabled: + explanation: Hesabınız için güvenlik anahtarlarıyla kimlik doÄŸrulama devre dışı bırakıldı. Artık yalnızca eÅŸleÅŸtirilmiÅŸ TOTP uygulaması tarafından oluÅŸturulan kodu kullanarak giriÅŸ yapmak mümkündür. + subject: 'Mastodon: Güvenlik anahtarlarıyla kimlik doÄŸrulama devre dışı' + title: Güvenlik anahtarları devre dışı + webauthn_enabled: + explanation: Hesabınız için güvenlik anahtarı doÄŸrulaması etkinleÅŸtirildi. Güvenlik anahtarınız artık giriÅŸ yapmak için kullanılabilir. + subject: 'Mastodon: Güvenlik anahtarı doÄŸrulaması etkinleÅŸtirildi' + title: Güvenlik anahtarları etkin omniauth_callbacks: failure: '%{kind}''den kimliÄŸiniz doÄŸrulanamadı çünkü "%{reason}".' success: "%{kind} hesabından baÅŸarıyla kimlik doÄŸrulaması yapıldı." @@ -67,8 +84,8 @@ tr: no_token: Bu sayfaya ÅŸifre sıfırlama e-postasından gelmeden eriÅŸemezsiniz. Åžifre sıfırlama e-postasından geliyorsanız lütfen saÄŸlanan tam URL'yi kullandığınızdan emin olun. send_instructions: E-posta adresiniz veritabanımızda varsa, e-posta adresinize birkaç dakika içinde bir parola kurtarma baÄŸlantısı gönderilir. Bu e-postayı almadıysanız, lütfen spam klasörünüzü kontrol edin. send_paranoid_instructions: E-posta adresiniz veritabanımızda varsa, e-posta adresinize birkaç dakika içinde bir parola kurtarma baÄŸlantısı gönderilir. Bu e-postayı almadıysanız, lütfen spam klasörünüzü kontrol edin. - updated: Parolanız baÅŸarıyla deÄŸiÅŸtirildi. Åžuan oturumunuz açıldı. - updated_not_active: Parolanız baÅŸarıyla deÄŸiÅŸtirildi. + updated: Åžifreniz baÅŸarılı bir ÅŸekilde deÄŸiÅŸtirildi. Åžu an oturum açtınız. + updated_not_active: Åžifreniz baÅŸarıyla deÄŸiÅŸtirildi. registrations: destroyed: Görüşürüz! hesabın baÅŸarıyla iptal edildi. Umarız seni sonra tekrar görürüz. signed_up: HoÅŸ geldiniz! BaÅŸarılı bir ÅŸekilde oturum açtınız. @@ -79,9 +96,9 @@ tr: update_needs_confirmation: Hesabınızı baÅŸarıyla güncellediniz, ancak yeni e-posta adresinizi doÄŸrulamamız gerekiyor. Lütfen e-postanızı kontrol edin ve yeni e-posta adresinizi onaylamak için onay baÄŸlantısını izleyin. Bu e-postayı almadıysanız, lütfen spam klasörünüzü kontrol edin. updated: Hesabınız baÅŸarıyla güncellendi. sessions: - already_signed_out: BaÅŸarıyla çıkış yapıldı. - signed_in: BaÅŸarıyla giriÅŸ yapıldı. - signed_out: BaÅŸarıyla çıkış yapıldı. + already_signed_out: BaÅŸarılı bir ÅŸekilde oturum kapatıldı. + signed_in: BaÅŸarılı bir ÅŸekilde oturum açıldı. + signed_out: BaÅŸarılı bir ÅŸekilde oturum kapatıldı. unlocks: send_instructions: Hesabınızı birkaç dakika içinde nasıl açacağınıza iliÅŸkin talimatları içeren bir e-posta alacaksınız. Bu e-postayı almadıysanız, lütfen spam klasörünüzü kontrol edin. send_paranoid_instructions: Hesabınız varsa, birkaç dakika içinde nasıl kilidini açacağınıza iliÅŸkin talimatları içeren bir e-posta alacaksınız. Bu e-postayı almadıysanız, lütfen spam klasörünüzü kontrol edin. diff --git a/config/locales/devise.tt.yml b/config/locales/devise.tt.yml new file mode 100644 index 0000000000000000000000000000000000000000..5eab4abff95e2119202e91e8d75bd785c9ccbdc9 --- /dev/null +++ b/config/locales/devise.tt.yml @@ -0,0 +1 @@ +tt: diff --git a/config/locales/devise.uk.yml b/config/locales/devise.uk.yml index eebeb106cd4461f35730e1222d4c527fe91cdec0..afd83861cddeca890c608114c3ba84b0d891d9f2 100644 --- a/config/locales/devise.uk.yml +++ b/config/locales/devise.uk.yml @@ -60,6 +60,23 @@ uk: title: Коди двофакторного Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ unlock_instructions: subject: 'Mastodon: ІнÑтрукції Ð´Ð»Ñ Ñ€Ð¾Ð·Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ' + webauthn_credential: + added: + explanation: ÐаÑтупний ключ безпеки був доданий до вашого облікового запиÑу + subject: 'Mastodon: Ðовий ключ безпеки' + title: Ðовий ключ безпеки додано + deleted: + explanation: ÐаÑтупний ключ безпеки було видалено з вашого облікового запиÑу + subject: 'Mastodon: Ключ безпеки видалено' + title: Один з ваших ключів безпеки було видалено + webauthn_disabled: + explanation: Ðвторизацію з ключами безпеки було відключено Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ облікового запиÑу. Вхід тепер можливий лише через токен, згенерований додатком TOTP. + subject: 'Mastodon: ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð·Ð° допомогою ключів безпеки вимкнена' + title: Ключі безпеки вимкнуто + webauthn_enabled: + explanation: ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ ÐºÐ»ÑŽÑ‡Ð° безпеки була увімкнена Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ облікового запиÑу. Ваш ключ безпеки тепер можна викориÑтовувати Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ. + subject: 'Mastodon: ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ ÐºÐ»ÑŽÑ‡Ð° безпеки увімкнена' + title: Ключі безпеки увімкнено omniauth_callbacks: failure: Ðам не вдалоÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ð’Ð°Ñ Ð· %{kind} через те, що "%{reason}". success: УÑпішно аутентифіковано з облікового запиÑу %{kind}. diff --git a/config/locales/devise.vi.yml b/config/locales/devise.vi.yml index 9a156be9dd0f6ad8cce84df4bfd41f41a351f06f..b0a240bf8e942c99d0964828003b7e7a37956fcc 100644 --- a/config/locales/devise.vi.yml +++ b/config/locales/devise.vi.yml @@ -8,7 +8,7 @@ vi: failure: already_authenticated: Bạn đã đăng nháºp rồi. inactive: Tà i khoản cá»§a bạn chưa được kich hoạt. - invalid: Nháºp sai %{authentication_keys} hoặc máºt khẩu. + invalid: "%{authentication_keys} hoặc máºt khẩu không khá»›p." last_attempt: Nếu thá» sai lần nữa, tà i khoản cá»§a bạn sẽ bị khóa. locked: Tà i khoản cá»§a bạn bị khóa. not_found_in_database: "%{authentication_keys} không có trong dữ liệu." @@ -21,8 +21,8 @@ vi: action: Xác thá»±c địa chỉ email action_with_app: Xác nháºn và quay lại %{app} explanation: Bạn đã tạo má»™t tà i khoản trên %{host} vá»›i địa chỉ email nà y. Chỉ cần má»™t cú nhấp chuá»™t nữa để kÃch hoạt nó. Nếu đây không phải là bạn, xin vui lòng bá» qua email nà y. - explanation_when_pending: Bạn đã đăng ký %{host} vá»›i địa chỉ email nà y. Chúng tôi chỉ xem xét đơn đăng ký sau khi bạn xác thá»±c địa chỉ email. Bạn có thể đăng nháºp để thay đổi chi tiết hoặc xóa tà i khoản cá»§a mình, nhưng bạn không thể truy cáºp hầu hết các chức năng cho đến khi tà i khoản cá»§a bạn được chấp thuáºn. Nếu bạn bị từ chối, dữ liệu cá»§a bạn sẽ bị xóa, do đó bạn sẽ không cần phải thá»±c hiện thêm hà nh động nà o nữa. Nếu đây không phải là bạn, xin vui lòng bá» qua email nà y. - extra_html: Xin Ä‘á»c kỹ <a href="%{terms_path}">ná»™i quy máy chá»§</a> và <a href="%{policy_path}">Ä‘iá»u khoản dịch vụ</a> cá»§a chúng tôi. + explanation_when_pending: Bạn vừa đăng ký %{host} vá»›i địa chỉ email nà y. Chúng tôi chỉ xem xét đơn đăng ký sau khi bạn xác thá»±c địa chỉ email. Bạn có thể đăng nháºp để thay đổi chi tiết hoặc xóa tà i khoản cá»§a mình, nhưng bạn không thể sá» dụng đầy đủ tÃnh năng cho đến khi tà i khoản được xác thá»±c. Nếu bạn bị từ chối, dữ liệu cá»§a bạn sẽ bị xóa, do đó bạn sẽ không cần phải là m gì thêm nữa. Nếu không phải do bạn đăng ký, xin vui lòng bá» qua email nà y. + extra_html: Xin Ä‘á»c kỹ <a href="%{terms_path}">quy tắc máy chá»§</a> và <a href="%{policy_path}">chÃnh sách riêng tư</a> cá»§a chúng tôi. subject: 'Mastodon: Xác thá»±c email cho %{instance}' title: Xác thá»±c địa chỉ email email_changed: @@ -60,28 +60,45 @@ vi: title: Mã khôi phục xác thá»±c hai yếu tố đã thay đổi unlock_instructions: subject: 'Mastodon: Hướng dẫn mở khóa' + webauthn_credential: + added: + explanation: Khóa bảo máºt nà y đã được thêm và o tà i khoản cá»§a bạn + subject: 'Mastodon: Khóa bảo máºt má»›i' + title: Vừa thêm má»™t khóa bảo máºt má»›i + deleted: + explanation: Khóa bảo máºt nà y đã bị xóa khá»i tà i khoản cá»§a bạn + subject: 'Mastodon: Xóa khóa bảo máºt' + title: Má»™t trong những khóa bảo máºt cá»§a bạn vừa bị xóa + webauthn_disabled: + explanation: Bạn vừa vô hiệu hóa xác thá»±c tà i khoản bằng khóa bảo máºt. Từ bây giá», bạn sẽ dùng ứng dụng TOTP để tạo token đăng nháºp. + subject: 'Mastodon: Vô hiệu hóa xác thá»±c bằng khóa bảo máºt' + title: Äã vô hiệu hóa khóa bảo máºt + webauthn_enabled: + explanation: Bạn vừa kÃch hoạt xác thá»±c tà i khoản bằng khóa bảo máºt. Từ bây giá», khóa bảo máºt cá»§a bạn sẽ được dùng để đăng nháºp. + subject: 'Mastodon: KÃch hoạt xác thá»±c bằng khóa bảo máºt' + title: Äã kÃch hoạt khóa bảo máºt omniauth_callbacks: failure: Không thể xác thá»±c bạn từ %{kind} bởi vì "%{reason}". - success: Xác thá»±c thà nh công từ tà i khoản %{kind}. + success: Xác thá»±c tà i khoản %{kind} thà nh công. passwords: - no_token: Bạn chỉ có thể truy cáºp trang nà y khi chuyển tiếp từ email phục hồi máºt khẩu. Nếu vẫn không được, vui lòng chắc chắn rằng bạn đã sá» dụng chÃnh xác URL được cung cấp. + no_token: Bạn chỉ có thể truy cáºp trang nà y khi nháºn được email phục hồi máºt khẩu. Nếu vẫn không được, vui lòng chắc chắn rằng bạn đã dùng chÃnh xác URL được cung cấp. send_instructions: Nếu địa chỉ email cá»§a bạn tồn tại trong cÆ¡ sở dữ liệu cá»§a chúng tôi, bạn sẽ nháºn được liên kết khôi phục máºt khẩu tại địa chỉ email cá»§a bạn sau và i phút. Xin kiểm tra thư mục thư rác nếu như bạn không thấy email nà y. send_paranoid_instructions: Nếu địa chỉ email cá»§a bạn tồn tại trong cÆ¡ sở dữ liệu cá»§a chúng tôi, bạn sẽ nháºn được liên kết khôi phục máºt khẩu tại địa chỉ email cá»§a bạn sau và i phút. Xin kiểm tra thư mục thư rác nếu như bạn không thấy email nà y. updated: Máºt khẩu cá»§a bạn đã được thay đổi thà nh công. Hiện tại bạn đã đăng nháºp. updated_not_active: Máºt khẩu cá»§a bạn đã được thay đổi thà nh công. registrations: - destroyed: Tạm biệt! Tà i khoản cá»§a bạn đã há»§y thà nh công. Hi vá»ng chúng tôi sẽ sá»›m gặp lại bạn. + destroyed: Tạm biệt! Tà i khoản cá»§a bạn đã bị há»§y. Hi vá»ng chúng tôi sẽ sá»›m gặp lại bạn. signed_up: Chúc mừng! Bạn đã đăng ký thà nh công. - signed_up_but_inactive: Bạn đã đăng ký thà nh công. Tuy nhiên, chúng tôi không thể đăng nháºp cho bạn vì tà i khoản cá»§a bạn chưa được kÃch hoạt. + signed_up_but_inactive: Bạn đã đăng ký thà nh công. Tuy nhiên, bạn cần phải kÃch hoạt tà i khoản má»›i có thể đăng nháºp. signed_up_but_locked: Bạn đã đăng ký thà nh công. Tuy nhiên, chúng tôi không thể đăng nháºp cho bạn vì tà i khoản cá»§a bạn bị khóa. signed_up_but_pending: Má»™t email xác thá»±c đã được gá»i đến địa chỉ email cá»§a bạn. Sau khi bạn nhấp và o liên kết, chúng tôi sẽ xem xét đơn đăng ký cá»§a bạn và thông báo nếu đơn được chấp thuáºn. signed_up_but_unconfirmed: Má»™t email xác thá»±c đã được gá»i đến địa chỉ email cá»§a bạn. Hãy nhấp và o liên kết trong email để kÃch hoạt tà i khoản cá»§a bạn. Nếu không thấy, hãy kiểm tra mục thư rác. update_needs_confirmation: Bạn đã cáºp nháºt tà i khoản thà nh công, nhưng chúng tôi cần xác thá»±c địa chỉ email má»›i cá»§a bạn. Vui lòng kiểm tra email và nhấp và o liên kết xác thá»±c. Nếu bạn không thấy email, hãy kiểm tra trong thư rác. updated: Tà i khoản cá»§a bạn đã được cáºp nháºt thà nh công. sessions: - already_signed_out: Hoà n tất đăng xuất. + already_signed_out: Äã đăng xuất. signed_in: Äã đăng nháºp thà nh công. - signed_out: Hoà n tất đăng xuất. + signed_out: Äã đăng xuất. unlocks: send_instructions: Bạn sẽ nháºn được má»™t email hướng dẫn vá» cách mở khóa tà i khoản cá»§a bạn trong và i phút tá»›i. Xin kiểm tra thư mục thư rác nếu như bạn không thấy email nà y. send_paranoid_instructions: Nếu tà i khoản cá»§a bạn tồn tại, bạn sẽ nháºn được email hướng dẫn cách mở khóa trong và i phút tá»›i. Xin kiểm tra thư mục thư rác nếu như bạn không thấy email nà y. diff --git a/config/locales/devise.zgh.yml b/config/locales/devise.zgh.yml new file mode 100644 index 0000000000000000000000000000000000000000..4d376ba8ca82f2ebbc2d310604ffcad97433001f --- /dev/null +++ b/config/locales/devise.zgh.yml @@ -0,0 +1,8 @@ +--- +zgh: + devise: + failure: + locked: ⵉⵜⵜⵓⵔⴳⵠⵓⵎⵉⴹⴰⵠâµâµâ´½. + mailer: + reset_password_instructions: + action: âµ™âµâ´¼âµ ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml index b7887dfa8392e54e6302cc751666df2a0c3cdad8..a830708938decba31a77a5ba911d1589d074b2d4 100644 --- a/config/locales/devise.zh-CN.yml +++ b/config/locales/devise.zh-CN.yml @@ -9,7 +9,7 @@ zh-CN: already_authenticated: ä½ å·²ç»ç™»å½•。 inactive: ä½ è¿˜æ²¡æœ‰æ¿€æ´»å¸æˆ·ã€‚ invalid: "%{authentication_keys} æ— æ•ˆæˆ–å¯†ç 错误。" - last_attempt: ä½ è¿˜æœ‰æœ€åŽä¸€æ¬¡å°è¯•æœºä¼šï¼Œå†æ¬¡å¤±è´¥ä½ çš„å¸æˆ·å°†è¢«é”定。 + last_attempt: 这是最åŽä¸€æ¬¡å°è¯•机会,失败åŽä½ çš„å¸æˆ·å°†è¢«é”定。 locked: ä½ çš„å¸æˆ·å·²è¢«é”定。 not_found_in_database: "%{authentication_keys}或密ç 错误。" pending: ä½ çš„å¸å·ä»åœ¨å®¡æ ¸ä¸ã€‚ @@ -31,7 +31,7 @@ zh-CN: subject: Mastodon:电å邮件地å€å·²è¢«æ›´æ”¹ title: 新电åé‚®ä»¶åœ°å€ password_change: - explanation: ä½ çš„å¸æˆ·çš„密ç 已被更改。 + explanation: ä½ çš„å¸æˆ·å¯†ç 已更改。 extra: å¦‚æžœä½ å¹¶æ²¡æœ‰è¯·æ±‚æ›´æ”¹ä½ çš„å¯†ç ,则他人很有å¯èƒ½å·²ç»å…¥ä¾µä½ çš„å¸æˆ·ã€‚è¯·ç«‹å³æ›´æ”¹ä½ 的密ç ï¼›å¦‚æžœä½ å·²ç»æ— æ³•è®¿é—®ä½ çš„å¸æˆ·ï¼Œè¯·è”ç³»æœåŠ¡å™¨çš„ç®¡ç†å‘˜è¯·æ±‚å助。 subject: Mastodon:密ç 已被更改 title: 密ç 已被é‡ç½® @@ -60,6 +60,23 @@ zh-CN: title: åŒé‡éªŒè¯çš„æ¢å¤ç 已更改 unlock_instructions: subject: Mastodonï¼šå¸æˆ·è§£é”ä¿¡æ¯ + webauthn_credential: + added: + explanation: ä»¥ä¸‹å®‰å…¨å¯†é’¥å·²æ·»åŠ åˆ°æ‚¨çš„å¸æˆ· + subject: Mastodon:新的安全密钥 + title: å·²æ·»åŠ ä¸€ä¸ªæ–°çš„å®‰å…¨å¯†é’¥ + deleted: + explanation: 以下安全密钥已从您的账户ä¸åˆ 除 + subject: Mastodonï¼šå®‰å…¨å¯†é’¥å·²åˆ é™¤ + title: æ‚¨çš„å®‰å…¨å¯†é’¥ä¹‹ä¸€å·²è¢«åˆ é™¤ + webauthn_disabled: + explanation: æ‚¨çš„å¸æˆ·å·²ç¦ç”¨å®‰å…¨å¯†é’¥è®¤è¯ã€‚现在åªèƒ½ä½¿ç”¨é…对的 TOTP 应用程åºç”Ÿæˆçš„令牌登录。 + subject: Mastodon:安全密钥认è¯å·²ç¦ç”¨ + title: 安全密钥已ç¦ç”¨ + webauthn_enabled: + explanation: æ‚¨çš„å¸æˆ·å·²å¯ç”¨å®‰å…¨å¯†é’¥èº«ä»½éªŒè¯ã€‚您的安全密钥现在å¯ä»¥ç”¨äºŽç™»å½•。 + subject: Mastodon:安全密钥认è¯å·²å¯ç”¨ + title: å·²å¯ç”¨å®‰å…¨å¯†é’¥ omniauth_callbacks: failure: 由于%{reason}ï¼Œæ— æ³•ä»Ž%{kind}获得授æƒã€‚ success: æˆåŠŸåœ°ä»Ž%{kind}获得授æƒã€‚ @@ -70,13 +87,13 @@ zh-CN: updated: ä½ çš„å¯†ç 已修改æˆåŠŸï¼Œä½ çŽ°åœ¨å·²ç™»å½•ã€‚ updated_not_active: ä½ çš„å¯†ç 已修改æˆåŠŸã€‚ registrations: - destroyed: å†è§ï¼ä½ çš„å¸æˆ·å·²æˆåŠŸé”€æ¯ã€‚我们希望很快å¯ä»¥å†è§åˆ°ä½ 。 + destroyed: å†è§ï¼ä½ çš„å¸æˆ·å·²æˆåŠŸæ³¨é”€ã€‚æˆ‘ä»¬å¸Œæœ›å¾ˆå¿«å¯ä»¥å†è§åˆ°ä½ 。 signed_up: 欢迎ï¼ä½ 已注册æˆåŠŸã€‚ - signed_up_but_inactive: ä½ å·²æ³¨å†Œï¼Œä½†å°šæœªæ¿€æ´»å¸æˆ·ã€‚ - signed_up_but_locked: ä½ å·²æ³¨å†Œï¼Œä½†å¸æˆ·è¢«é”定了。 - signed_up_but_pending: 一å°å¸¦æœ‰ç¡®è®¤é“¾æŽ¥çš„邮件已ç»å‘é€åˆ°äº†æ‚¨çš„邮箱。 在您点击确认链接åŽï¼Œæˆ‘ä»¬å°†ä¼šå®¡æ ¸æ‚¨çš„ç”³è¯·ã€‚å®¡æ ¸é€šè¿‡åŽï¼Œæˆ‘们将会通知您。 + signed_up_but_inactive: ä½ å·²æˆåŠŸæ³¨å†Œï¼Œä½†å› å°šæœªæ¿€æ´»å¸æˆ·æ‰€ä»¥æ— 法登陆。 + signed_up_but_locked: ä½ å·²æˆåŠŸæ³¨å†Œï¼Œä½†å› å¸æˆ·è¢«é”å®šæ‰€ä»¥æ— æ³•ç™»é™†ã€‚ + signed_up_but_pending: 一å°å¸¦æœ‰ç¡®è®¤é“¾æŽ¥çš„邮件已ç»å‘é€åˆ°äº†ä½ 的邮箱。 åœ¨ä½ ç‚¹å‡»ç¡®è®¤é“¾æŽ¥åŽï¼Œæˆ‘ä»¬å°†ä¼šå®¡æ ¸ä½ çš„ç”³è¯·ã€‚å®¡æ ¸é€šè¿‡åŽï¼Œæˆ‘ä»¬å°†ä¼šé€šçŸ¥ä½ ã€‚ signed_up_but_unconfirmed: 一å°å¸¦æœ‰ç¡®è®¤é“¾æŽ¥çš„邮件已ç»å‘é€è‡³ä½ 的邮箱,请点击邮件ä¸çš„é“¾æŽ¥ä»¥æ¿€æ´»ä½ çš„å¸æˆ·ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ä»¶ã€‚ - update_needs_confirmation: ä¿¡æ¯æ›´æ–°æˆåŠŸï¼Œä½†æˆ‘ä»¬éœ€è¦éªŒè¯ä½ 的新电å邮件地å€ï¼Œè¯·ç‚¹å‡»é‚®ä»¶ä¸çš„é“¾æŽ¥ä»¥ç¡®è®¤ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ç®±ã€‚ + update_needs_confirmation: å¸å·ä¿¡æ¯æ›´æ–°æˆåŠŸï¼Œä½†æˆ‘ä»¬éœ€è¦éªŒè¯ä½ 的新电å邮件地å€ï¼Œè¯·ç‚¹å‡»é‚®ä»¶ä¸çš„é“¾æŽ¥ä»¥ç¡®è®¤ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ç®±ã€‚ updated: 叿ˆ·èµ„料更新æˆåŠŸã€‚ sessions: already_signed_out: å·²æˆåŠŸç™»å‡ºã€‚ @@ -84,12 +101,12 @@ zh-CN: signed_out: å·²æˆåŠŸç™»å‡ºã€‚ unlocks: send_instructions: å‡ åˆ†é’ŸåŽï¼Œä½ 将收到一å°è§£é”叿ˆ·çš„é‚®ä»¶ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ç®±ã€‚ - send_paranoid_instructions: å¦‚æžœä½ çš„é‚®ç®±å˜åœ¨äºŽæˆ‘们的数æ®åº“ä¸ï¼Œä½ 将收到一å°è§£é”叿ˆ·çš„é‚®ä»¶ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ç®±ã€‚ + send_paranoid_instructions: å¦‚æžœä½ çš„å¸å·å˜åœ¨äºŽæ•°æ®åº“ä¸ï¼Œä½ å°†æ”¶åˆ°ä¸€å°æŒ‡å¼•ä½ è§£é”叿ˆ·çš„é‚®ä»¶ã€‚å¦‚æžœæ²¡æœ‰ï¼Œè¯·æ£€æŸ¥ä½ çš„åžƒåœ¾é‚®ç®±ã€‚ unlocked: ä½ çš„å¸æˆ·å·²æˆåŠŸè§£é”。登录以继ç»ã€‚ errors: messages: already_confirmed: å·²ç»ç¡®è®¤æˆåŠŸï¼Œè¯·å°è¯•登录 - confirmation_period_expired: 必须在 %{period}ä»¥å†…ç¡®è®¤ã€‚è¯·é‡æ–°å‘起请求 + confirmation_period_expired: 必须在 %{period} ä»¥å†…ç¡®è®¤ã€‚è¯·é‡æ–°å‘起请求 expired: å·²è¿‡æœŸã€‚è¯·é‡æ–°å‘起请求 not_found: 未找到 not_locked: 未被é”定 diff --git a/config/locales/devise.zh-HK.yml b/config/locales/devise.zh-HK.yml index f72fd55a3ce53d4be8f5fddb104ed254a8edd1ce..2d9e8ddeada10c6c0ea53185ce3764a6e4e50844 100644 --- a/config/locales/devise.zh-HK.yml +++ b/config/locales/devise.zh-HK.yml @@ -2,90 +2,107 @@ zh-HK: devise: confirmations: - confirmed: ä½ çš„é›»éƒµåœ°å€æˆåŠŸç¢ºèªã€‚ - send_instructions: ä½ å°‡æœƒåœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°ç¢ºèªæŒ‡ç¤ºé›»éƒµï¼Œä¸Šé¢æœ‰ç¢ºèªä½ 電郵地å€çš„æŒ‡ç¤ºã€‚ - send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµåœ°å€å·²ç¶“å˜åœ¨æ–¼æˆ‘å€‘çš„è³‡æ–™åº«ï¼Œä½ å°‡æœƒåœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°é›»éƒµï¼Œç¢ºèªä½ 電郵地å€çš„æŒ‡ç¤ºã€‚ + confirmed: 已確èªä½ 的電郵地å€ã€‚ + send_instructions: ä½ å°‡æœƒåœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°ç¢ºèªæŒ‡ç¤ºé›»éƒµï¼Œä¸Šé¢æœ‰ç¢ºèªä½ 電郵地å€çš„æŒ‡ç¤ºã€‚如果它沒有出ç¾åœ¨ä½ çš„æ”¶ä»¶ç®±ï¼Œè«‹æª¢æŸ¥ä¸€ä¸‹ä½ çš„åžƒåœ¾éƒµä»¶ç®±ã€‚ + send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµåœ°å€å·²ç¶“å˜åœ¨æ–¼æˆ‘å€‘çš„è³‡æ–™åº«ï¼Œä½ å°‡æœƒåœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°é›»éƒµï¼Œç¢ºèªä½ 電郵地å€çš„æŒ‡ç¤ºã€‚如果它沒有出ç¾åœ¨ä½ çš„æ”¶ä»¶ç®±ï¼Œè«‹æª¢æŸ¥ä¸€ä¸‹ä½ çš„åžƒåœ¾éƒµä»¶ç®±ã€‚ failure: already_authenticated: ä½ ä¹‹å‰å·²ç¶“登入了。 - inactive: 您的帳號尚未啟用。 - invalid: 䏿£ç¢ºçš„ %{authentication_keys} 或密碼。 + inactive: ä½ çš„å¸³è™Ÿå°šæœªè¢«å•Ÿç”¨ã€‚ + invalid: 䏿£ç¢ºçš„%{authentication_keys}或密碼。 last_attempt: è‹¥ä½ å†ä¸€æ¬¡å˜—è©¦å¤±æ•—ï¼Œæˆ‘å€‘å°‡éŽ–å®šä½ çš„å¸³è™Ÿï¼Œä»¥ç–安全。 locked: ä½ çš„å¸³è™Ÿå·²è¢«éŽ–å®šã€‚ - not_found_in_database: 䏿£ç¢ºçš„ %{authentication_keys} 或密碼。 - pending: 您的帳戶ä»åœ¨å¯©æ ¸ä¸ã€‚ + not_found_in_database: 䏿£ç¢ºçš„%{authentication_keys}或密碼。 + pending: ä½ çš„å¸³è™Ÿä»åœ¨å¯©æ ¸ä¸ timeout: ä½ çš„ç™»å…¥éšŽæ®µå·²ç¶“éŽæœŸï¼Œè«‹é‡æ–°ç™»å…¥ä»¥ç¹¼çºŒä½¿ç”¨ã€‚ unauthenticated: ä½ å¿…é ˆå…ˆç™»å…¥æˆ–ç™»è¨˜ï¼Œä»¥ç¹¼çºŒä½¿ç”¨ã€‚ unconfirmed: ä½ å¿…é ˆå…ˆç¢ºèªé›»éƒµåœ°å€ï¼Œç¹¼çºŒä½¿ç”¨ã€‚ mailer: confirmation_instructions: action: é©—è‰é›»åéƒµä»¶åœ°å€ - action_with_app: 確èªä¸¦è¿”回 %{app} - explanation: ä½ åœ¨ %{host} 上使用這個電å郵件地å€å»ºç«‹äº†ä¸€å€‹å¸³æˆ¶ã€‚åªéœ€é»žæ“Šä¸‹é¢çš„連çµï¼Œå³å¯å•Ÿç”¨å¸³æˆ¶ã€‚å¦‚æžœä½ ä¸¦æ²’æœ‰å»ºç«‹éŽå¸³æˆ¶ï¼Œè«‹å¿½ç•¥æ¤éƒµä»¶ã€‚ - explanation_when_pending: 您使用æ¤é›»åä¿¡ç®±ä½å€ç”³è«‹äº† %{host} 的邀請。當您確èªé›»åä¿¡ç®±å¾Œæˆ‘å€‘å°‡å¯©æ ¸æ‚¨çš„ç”³è«‹ï¼Œè€Œç›´åˆ°æ ¸å‡†å‰æ‚¨éƒ½ç„¡æ³•ç™»å…¥ã€‚ç•¶æ‚¨çš„ç”³è«‹éæ‹’絕,您的資料將被移除而ä¸å¿…åšå¾ŒçºŒå‹•ä½œã€‚å¦‚æžœé€™ä¸æ˜¯æ‚¨ï¼Œè«‹å¿½ç•¥æ¤ä¿¡ä»¶ã€‚ - extra_html: 請記得閱讀本æœå‹™ç«™çš„<a href="%{terms_path}">相關è¦å®š</a>å’Œ<a href="%{policy_path}">ä½¿ç”¨æ¢æ¬¾</a>。 + action_with_app: 確èªä¸¦å›žåˆ°%{app} + explanation: ä½ å·²æˆåŠŸç”¨é€™å€‹é›»éƒµåœ¨ %{host} 上建立了帳號。åªéœ€é»žæ“Šä¸‹é¢çš„連çµï¼Œå³å¯å•Ÿç”¨å¸³æˆ¶ã€‚å¦‚æžœä½ ä¸¦æ²’æœ‰å»ºç«‹éŽå¸³æˆ¶ï¼Œè«‹å¿½ç•¥æ¤éƒµä»¶ã€‚ + explanation_when_pending: ä½ ä½¿ç”¨æ¤é›»éƒµåœ°å€ç”³è«‹äº†%{host} 帳戶。確èªé›»éƒµåœ°å€å¾Œï¼Œæˆ‘å€‘å°‡å¯©æ ¸ä½ çš„ç”³è«‹ã€‚ä½ å¯åœ¨ç™»å…¥å¾Œæ›´æ”¹è©³ç´°ä¿¡æ¯ï¼Œæˆ–刪除帳戶,但在帳戶ç²å¾—批准之å‰ï¼Œä½ å°‡ç„¡æ³•ä½¿ç”¨å¤§éƒ¨ä»½åŠŸèƒ½ã€‚å¦‚æžœä½ çš„ç”³è«‹è¢«æ‹’çµ•ï¼Œä½ çš„è³‡æ–™æœƒè¢«ç›´æŽ¥åˆªé™¤ï¼Œè€Œç„¡éœ€ä½ æŽ¡å–ä»»ä½•å‹•ä½œã€‚å¦‚æžœç”³è«‹äººä¸æ˜¯ä½ ,請忽略æ¤é›»éƒµã€‚ + extra_html: 請閱讀<a href="%{terms_path}">ç«™è¦</a>å’Œ<a href="%{policy_path}">æˆ‘å€‘çš„ä½¿ç”¨æ¢æ¬¾</a>。 subject: 'Mastodon: 確èªé›»éƒµåœ°å€ %{instance}' title: é©—è‰é›»åéƒµä»¶åœ°å€ email_changed: - explanation: ä½ çš„å¸³æˆ¶çš„é›»å郵件地å€å³å°‡è®Šæ›´ç‚ºï¼š - extra: å¦‚æžœä½ æ²’æœ‰è«‹æ±‚æ›´æ”¹ä½ çš„é›»å郵件地å€ï¼Œå‰‡ä»–人很有å¯èƒ½å·²ç¶“å…¥ä¾µä½ çš„å¸³æˆ¶ã€‚è«‹ç«‹å³æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼›å¦‚æžœä½ å·²ç¶“ç„¡æ³•è¨ªå•ä½ çš„å¸³æˆ¶ï¼Œè«‹è¯ç¹«æœå‹™ç«™çš„管ç†å“¡è«‹æ±‚å”助。 - subject: Mastodon:電å郵件地å€å·²è¢«æ›´æ”¹ - title: æ–°é›»åéƒµä»¶åœ°å€ + explanation: ä½ çš„å¸³è™Ÿçš„é›»éƒµåœ°å€å³å°‡è®Šæ›´ç‚ºï¼š + extra: å¦‚æžœä½ æ²’æœ‰æ›´æ”¹ä½ çš„é›»éƒµåœ°å€ï¼Œé‚£å¾ˆæœ‰å¯èƒ½å·²ç¶“æœ‰å…¶ä»–äººå…¥ä¾µä½ çš„å¸³è™Ÿã€‚è«‹ç«‹å³æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼›å¦‚æžœä½ å·²ç¶“ç„¡æ³•è¨ªå•ä½ çš„å¸³æˆ¶ï¼Œè«‹è¯ç¹«æœå‹™ç«™çš„管ç†å“¡è«‹æ±‚å”助。 + subject: Mastodon:電郵地å€å·²è¢«æ›´æ”¹ + title: æ–°é›»éƒµåœ°å€ password_change: - explanation: ä½ çš„å¸³æˆ¶çš„å¯†ç¢¼å·²è¢«æ›´æ”¹ã€‚ - extra: å¦‚æžœä½ æ²’æœ‰è«‹æ±‚æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼Œå‰‡ä»–äººå¾ˆæœ‰å¯èƒ½å·²ç¶“å…¥ä¾µä½ çš„å¸³æˆ¶ã€‚è«‹ç«‹å³æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼›å¦‚æžœä½ å·²ç¶“ç„¡æ³•è¨ªå•ä½ çš„å¸³æˆ¶ï¼Œè«‹è¯ç¹«æœå‹™ç«™çš„管ç†å“¡è«‹æ±‚å”助。 - subject: 'Mastodon: 更改密碼' - title: 密碼已被é‡è¨ + explanation: ä½ çš„å¸³è™Ÿçš„å¯†ç¢¼å·²è¢«æ›´æ”¹ã€‚ + extra: å¦‚æžœä½ æ²’æœ‰æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼Œé‚£å¾ˆæœ‰å¯èƒ½å·²ç¶“æœ‰å…¶ä»–äººå…¥ä¾µä½ çš„å¸³è™Ÿã€‚è«‹ç«‹å³æ›´æ”¹ä½ çš„å¯†ç¢¼ï¼›å¦‚æžœä½ å·²ç¶“ç„¡æ³•è¨ªå•ä½ çš„å¸³æˆ¶ï¼Œè«‹è¯ç¹«æœå‹™ç«™çš„管ç†å“¡è«‹æ±‚å”助。 + subject: 'Mastodon: 密碼已被更改' + title: 密碼已被更改 reconfirmation_instructions: - explanation: 點擊下é¢çš„連çµä¾†ç¢ºèªä½ 的新電å郵件地å€ã€‚ + explanation: 點擊下é¢çš„連çµä¾†ç¢ºèªä½ 的新電郵地å€ã€‚ extra: å¦‚æžœä½ æ²’æœ‰è«‹æ±‚æœ¬æ¬¡è®Šæ›´ï¼Œè«‹å¿½ç•¥æ¤éƒµä»¶ã€‚ Mastodon 帳戶的電å郵件地å€åªæœ‰åœ¨ä½ 點擊上é¢çš„連çµå¾Œæ‰æœƒæ›´æ”¹ã€‚ - subject: Mastodonï¼šç¢ºèª %{instance} é›»åéƒµä»¶åœ°å€ - title: é©—è‰é›»åéƒµä»¶åœ°å€ + subject: Mastodonï¼šç¢ºèª %{instance} é›»éƒµåœ°å€ + title: é©—è‰é›»éƒµåœ°å€ reset_password_instructions: action: 更改密碼 - explanation: 點擊下é¢çš„連çµä¾†æ›´æ”¹å¸³æˆ¶çš„密碼。 - extra: å¦‚æžœä½ æ²’æœ‰è«‹æ±‚æœ¬æ¬¡è®Šæ›´ï¼Œè«‹å¿½ç•¥æ¤éƒµä»¶ã€‚ä½ çš„å¯†ç¢¼åªæœ‰åœ¨ä½ 點擊上é¢çš„連çµä¸¦è¼¸å…¥æ–°å¯†ç¢¼å¾Œæ‰æœƒæ›´æ”¹ã€‚ + explanation: 點擊下é¢çš„連çµä¾†æ›´æ”¹å¸³è™Ÿçš„密碼。 + extra: å¦‚æžœä½ æ²’æœ‰è«‹æ±‚ä¿®æ”¹å¸³è™Ÿï¼Œè«‹å¿½ç•¥æ¤éƒµä»¶ã€‚åœ¨ä½ é»žæ“Šé€²ä¸Šé¢é€£çµä¸¦è¨å®šæ–°å¯†ç¢¼å‰ï¼Œå¸³è™Ÿå¯†ç¢¼æœƒç¶æŒä¸è®Šã€‚ subject: 'Mastodon: é‡è¨å¯†ç¢¼' title: é‡è¨å¯†ç¢¼ two_factor_disabled: - explanation: 您帳戶的兩æ¥é©Ÿé©—è‰å·²åœç”¨ã€‚ç¾åœ¨åªèƒ½ä½¿ç”¨é›»åä¿¡ç®±åŠå¯†ç¢¼ç™»å…¥ã€‚ - subject: Mastodon:已åœç”¨å…©æ¥é©Ÿé©—è‰ - title: å·²åœç”¨ 2FA + explanation: 帳號的雙é‡èªè‰å·²è¢«åœç”¨ã€‚ç¾åœ¨åªéœ€ä½¿ç”¨é›»éƒµåœ°å€å’Œå¯†ç¢¼ï¼Œå³å¯ç™»å…¥ã€‚ + subject: Mastodon:已關閉雙é‡èªè‰ + title: 已關閉雙é‡èªè‰ two_factor_enabled: - explanation: 已尿‚¨çš„帳戶啟用兩æ¥é©Ÿé©—è‰ã€‚登入時將需è¦é…å°ä¹‹ TOTP æ‡‰ç”¨ç¨‹å¼æ‰€ç”¢ç”Ÿçš„ Token。 - subject: Mastodon:已啟用兩æ¥é©Ÿé©—è‰ - title: 已啟用 2FA + explanation: 賬號的雙é‡èªè‰å·²è¢«å•Ÿç”¨ã€‚登錄時,將需è¦å·²é…å° TOTP 應用程å¼ç”Ÿæˆçš„é©—è‰ç¢¼ã€‚ + subject: Mastodon:已啟用雙é‡èªè‰ + title: 已啟用雙é‡èªè‰ two_factor_recovery_codes_changed: - explanation: 上一次的復原碼已經失效,且已產生新的。 - subject: Mastodon:兩æ¥é©Ÿé©—è‰å¾©åŽŸç¢¼å·²ç¶“é‡æ–°ç”¢ç”Ÿ - title: 2FA 復原碼已變更 + explanation: 之å‰çš„æ¢å¾©ç¢¼å¤±æ•ˆäº†ï¼Œæ–°çš„å·²ç”Ÿæˆã€‚ + subject: Mastodon:已產生新的雙é‡èªè‰æ¢å¾©ç¢¼ + title: é›™é‡èªè‰æ¢å¾©ç¢¼å·²æ›´æ”¹ unlock_instructions: - subject: 'Mastodon: 解除用戶鎖定' + subject: 'Mastodon: 解除帳號鎖定' + webauthn_credential: + added: + explanation: ä»¥ä¸‹çš„å®‰å…¨é‘°åŒ™å·²ç¶“åŠ é€²ä½ çš„å¸³è™Ÿ + subject: 'Mastodon: 新的安全鑰匙' + title: å·²ç¶“åŠ å…¥ä¸€å€‹æ–°çš„å®‰å…¨é‘°åŒ™ + deleted: + explanation: ä»¥ä¸‹çš„å®‰å…¨é‘°åŒ™å·²ç¶“å¾žä½ çš„å¸³è™Ÿä¸ç§»é™¤äº† + subject: 'Mastodon: 安全鑰匙已移除' + title: ä½ å…¶ä¸çš„一個安全鑰匙已經被移除了 + webauthn_disabled: + explanation: ä½ çš„å¸³è™Ÿçš„å®‰å…¨é‘°åŒ™èº«ä»½é©—è‰å·²ç¶“åœç”¨ã€‚ä½ åªå¯ä»¥ç”¨éŽåŽ»å·²ç¶“é…å°å¥½çš„基於時間一次性密碼程å¼ç”Ÿæˆçš„密碼來登錄。 + subject: 'Mastodon: 安全鑰匙身份驗è‰å·²ç¶“åœç”¨' + title: å·²åœç”¨å®‰å…¨é‘°åŒ™ + webauthn_enabled: + explanation: 安全鑰匙身份驗è‰å·²å•Ÿç”¨ã€‚ä½ çš„å®‰å…¨é‘°åŒ™ç¾åœ¨å¯ä»¥ç”¨ä¾†ç™»éŒ„。 + subject: 'Mastodon: 安全鑰匙身份驗è‰å·²å•Ÿç”¨' + title: 已啟用安全鑰匙 omniauth_callbacks: - failure: 無法以 %{kind} ç™»å…¥ä½ çš„ç”¨æˆ¶ï¼ŒåŽŸå› æ˜¯ï¸°ã€Œ%{reason}ã€ã€‚ + failure: 無法以 %{kind} ç™»å…¥ä½ çš„å¸³è™Ÿï¼ŒåŽŸå› æ˜¯ï¸°ã€Œ%{reason}ã€ã€‚ success: æˆåŠŸä»¥ %{kind} ç™»å…¥ä½ çš„ç”¨æˆ¶ã€‚ passwords: no_token: ä½ å¿…é ˆä½¿ç”¨é‡è¨å¯†ç¢¼é›»éƒµå…§çš„ç¶²å€é€²å…¥æœ¬é ã€‚å¦‚æžœä½ ç¢ºæ˜¯ä½¿ç”¨é›»éƒµå…§çš„ç¶²å€ï¼Œè«‹ç¢ºèªä½ 用了完整的網å€ã€‚ - send_instructions: ä½ å°‡åœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°é‡è¨å¯†ç¢¼çš„電郵指示。 - send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµåœ°å€å·²ç¶“å˜åœ¨æ–¼æˆ‘å€‘çš„è³‡æ–™åº«ï¼Œä½ å°‡æœƒåœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°é‡è¨å¯†ç¢¼çš„電郵指示。 + send_instructions: å¦‚æžœä½ çš„é›»éƒµå˜åœ¨æ–¼æˆ‘們的資料庫ä¸ï¼Œä½ 將在幾分é˜å…§æ”¶åˆ°é‡è¨å¯†ç¢¼çš„é›»éƒµæŒ‡ç¤ºã€‚å¦‚æžœä½ æœªèƒ½åœ¨æ”¶ä»¶ç®±æ‰¾åˆ°è©²é›»éƒµï¼Œè«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶ç®±ã€‚ + send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµå˜åœ¨æ–¼æˆ‘們的資料庫ä¸ï¼Œä½ 將在幾分é˜å…§æ”¶åˆ°é‡è¨å¯†ç¢¼çš„é›»éƒµæŒ‡ç¤ºã€‚å¦‚æžœä½ æœªèƒ½åœ¨æ”¶ä»¶ç®±æ‰¾åˆ°è©²é›»éƒµï¼Œè«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶ç®±ã€‚ updated: ä½ çš„å¯†ç¢¼å·²ç¶“æ›´æ–°ï¼Œä½ ç¾åœ¨æ£ç™»å…¥æœ¬ç«™ã€‚ updated_not_active: ä½ çš„å¯†ç¢¼å·²ç¶“æ›´æ–°ã€‚ registrations: - destroyed: å†è¦‹äº†ï¼ä½ çš„ç”¨æˆ¶å·²è¢«å–æ¶ˆï¼Œå¸Œæœ›æˆ‘們相有相見的機會å§ã€‚ - signed_up: æ¡è¿Žä½ ï¼ä½ 的登記已經æˆåŠŸã€‚ - signed_up_but_inactive: ä½ çš„ç™»è¨˜å·²ç¶“æˆåŠŸï¼Œå¯æ˜¯ç”±æ–¼ä½ 的用戶還被被啟用,暫時還ä¸èƒ½è®“ä½ ç™»å…¥ã€‚ - signed_up_but_locked: ä½ çš„ç™»è¨˜å·²ç¶“æˆåŠŸï¼Œå¯æ˜¯ç”±æ–¼ä½ çš„ç”¨æˆ¶å·²è¢«éŽ–å®šï¼Œæˆ‘å€‘ç„¡æ³•è®“ä½ ç™»å…¥ã€‚ - signed_up_but_pending: 包å«ç¢ºèªé€£çµçš„訊æ¯å·²å¯„到您的電å信箱。按下æ¤é€£çµå¾Œæˆ‘å€‘å°‡å¯©æ ¸æ‚¨çš„ç”³è«‹ã€‚æ ¸å‡†å¾Œå°‡é€šçŸ¥æ‚¨ã€‚ - signed_up_but_unconfirmed: 一æ¢ç¢ºèªé€£çµå·²ç¶“é›»éƒµåˆ°ä½ çš„éƒµå€ã€‚請使用讓連çµå•Ÿç”¨ä½ 的用戶。 - update_needs_confirmation: ä½ çš„ç”¨æˆ¶å·²ç¶“æ›´æ–°ï¼Œä½†æˆ‘å€‘éœ€è¦ç¢ºèªä½ 的電郵地å€ã€‚è«‹æ‰“é–‹ä½ çš„éƒµç®±ï¼Œä½¿ç”¨ç¢ºèªé›»éƒµçš„連çµä¾†ç¢ºèªçš„地郵å€ã€‚ - updated: ä½ çš„ç”¨æˆ¶å·²ç¶“æˆåŠŸæ›´æ–°ã€‚ + destroyed: å†è¦‹ï¼ä½ çš„å¸³è™Ÿå·²è¢«å–æ¶ˆï¼Œå¸Œæœ›æ—¥å¾Œèƒ½å†è¦‹åˆ°ä½ 。 + signed_up: æ¡è¿Žä½ ï¼ä½ 已經æˆåŠŸç™»è¨˜ã€‚ + signed_up_but_inactive: ä½ çš„ç™»è¨˜å·²ç¶“æˆåŠŸï¼Œå¯æ˜¯ç”±æ–¼ä½ 的帳號還未被啟用,暫時還ä¸èƒ½è®“ä½ ç™»å…¥ã€‚ + signed_up_but_locked: ä½ çš„ç™»è¨˜å·²ç¶“æˆåŠŸï¼Œå¯æ˜¯ç”±æ–¼ä½ çš„å¸³è™Ÿå·²è¢«éŽ–å®šï¼Œæˆ‘å€‘ç„¡æ³•è®“ä½ ç™»å…¥ã€‚ + signed_up_but_pending: 確èªé€£çµå·²ç™¼é€åˆ°ä½ 的電郵地å€ã€‚åœ¨ä½ é»žæ“Šé€£çµå¾Œï¼Œæˆ‘å€‘æœƒå¯©æ ¸ä½ çš„ç”³è«‹ã€‚ä¸€æ—¦é€šéŽå¯©æ ¸ï¼Œä½ 將會收到進一æ¥é€šçŸ¥ã€‚ + signed_up_but_unconfirmed: 一æ¢ç¢ºèªé€£çµå·²ç¶“é›»éƒµåˆ°ä½ çš„éƒµå€ã€‚請使用讓連çµå•Ÿç”¨ä½ 的帳號。 + update_needs_confirmation: ä½ çš„å¸³è™Ÿå·²ç¶“æ›´æ–°ï¼Œä½†æˆ‘å€‘éœ€è¦ç¢ºèªä½ 的電郵地å€ã€‚è«‹æ‰“é–‹ä½ çš„éƒµç®±ï¼Œä½¿ç”¨ç¢ºèªé›»éƒµçš„連çµä¾†ç¢ºèªçš„地郵å€ã€‚如果未能在收件箱找相關電郵指示,請檢查垃圾郵件箱。 + updated: ä½ çš„å¸³è™Ÿå·²ç¶“æˆåŠŸæ›´æ–°ã€‚ sessions: already_signed_out: æˆåŠŸç™»å‡ºã€‚ signed_in: æˆåŠŸç™»å…¥ã€‚ signed_out: æˆåŠŸç™»å‡ºã€‚ unlocks: - send_instructions: ä½ å°‡åœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°è§£é™¤ç”¨æˆ¶éŽ–å®šçš„é›»éƒµæŒ‡ç¤ºã€‚ - send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµåœ°å€å·²ç¶“å˜åœ¨æ–¼æˆ‘å€‘çš„è³‡æ–™åº«ï¼Œä½ å°‡åœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°è§£é™¤ç”¨æˆ¶éŽ–å®šçš„é›»éƒµæŒ‡ç¤ºã€‚ - unlocked: ä½ çš„ç”¨æˆ¶å·²ç¶“è§£éŽ–ï¼Œè«‹ç™»å…¥ä»¥ç¹¼çºŒã€‚ + send_instructions: ä½ å°‡åœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°è§£é™¤ç”¨æˆ¶éŽ–å®šçš„é›»éƒµæŒ‡ç¤ºã€‚å¦‚æžœæœªèƒ½åœ¨æ”¶ä»¶ç®±æ‰¾åˆ°é›»éƒµæŒ‡ç¤ºï¼Œè«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶ç®±ã€‚ + send_paranoid_instructions: å¦‚æžœä½ çš„é›»éƒµåœ°å€å·²ç¶“å˜åœ¨æ–¼æˆ‘å€‘çš„è³‡æ–™åº«ï¼Œä½ å°‡åœ¨å¹¾åˆ†é˜å…§æ”¶åˆ°è§£é™¤ç”¨æˆ¶éŽ–å®šçš„é›»éƒµæŒ‡ç¤ºã€‚å¦‚æžœæœªèƒ½åœ¨æ”¶ä»¶ç®±æ‰¾åˆ°é›»éƒµæŒ‡ç¤ºï¼Œè«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶ç®±ã€‚ + unlocked: ä½ çš„å¸³è™Ÿå·²ç¶“è§£éŽ–ï¼Œè«‹ç™»å…¥ä»¥ç¹¼çºŒã€‚ errors: messages: already_confirmed: å…ˆå‰å·²ç¶“確èªï¼Œè«‹å˜—試登入 diff --git a/config/locales/devise.zh-TW.yml b/config/locales/devise.zh-TW.yml index ef0da1a9cfbfd367675012deaa4b3fa61019257f..f7b087824fb7d950ca30c3dadd13445e04cb44b9 100644 --- a/config/locales/devise.zh-TW.yml +++ b/config/locales/devise.zh-TW.yml @@ -21,18 +21,18 @@ zh-TW: action: é©—è‰é›»åä¿¡ç®±ä½å€ action_with_app: 確èªä¸¦è¿”回 %{app} explanation: 您已經在 %{host} 上以æ¤é›»åä¿¡ç®±ä½å€å»ºç«‹äº†ä¸€æ”¯å¸³æˆ¶ã€‚您è·é›¢å•Ÿç”¨å®ƒåªå‰©ä¸€é»žä¹‹é™äº†ã€‚è‹¥é€™ä¸æ˜¯æ‚¨ï¼Œè«‹å¿½ç•¥æ¤ä¿¡ä»¶ã€‚ - explanation_when_pending: 您使用æ¤é›»åä¿¡ç®±ä½å€ç”³è«‹äº† %{host} 的邀請。當您確èªé›»åä¿¡ç®±å¾Œæˆ‘å€‘å°‡å¯©æ ¸æ‚¨çš„ç”³è«‹ï¼Œè€Œç›´åˆ°æ ¸å‡†å‰æ‚¨éƒ½ç„¡æ³•ç™»å…¥ã€‚ç•¶æ‚¨çš„ç”³è«‹éæ‹’絕,您的資料將被移除而ä¸å¿…åšå¾ŒçºŒå‹•ä½œã€‚å¦‚æžœé€™ä¸æ˜¯æ‚¨ï¼Œè«‹å¿½ç•¥æ¤ä¿¡ä»¶ã€‚ + explanation_when_pending: 您使用æ¤é›»åä¿¡ç®±ä½å€ç”³è«‹äº† %{host} 的邀請。當您確èªé›»åä¿¡ç®±å¾Œæˆ‘å€‘å°‡å¯©æ ¸æ‚¨çš„ç”³è«‹ã€‚æ‚¨å¯ä»¥ç™»å…¥ä»¥æ”¹è®Šæ‚¨çš„ç´°ç¯€æˆ–åˆªé™¤æ‚¨çš„å¸³è™Ÿï¼Œä½†ç›´åˆ°æ‚¨çš„å¸³è™Ÿè¢«æ ¸å‡†ä¹‹å‰ï¼Œæ‚¨ç„¡æ³•æ“ä½œå¤§éƒ¨åˆ†çš„åŠŸèƒ½ã€‚è‹¥æ‚¨çš„ç”³è«‹éæ‹’絕,您的資料將被移除而ä¸å¿…åšå¾ŒçºŒå‹•ä½œã€‚å¦‚æžœé€™ä¸æ˜¯æ‚¨ï¼Œè«‹å¿½ç•¥æ¤ä¿¡ä»¶ã€‚ extra_html: åŒæ™‚也請看看<a href="%{terms_path}">伺æœå™¨è¦å‰‡</a>與<a href="%{policy_path}">æœå‹™æ¢æ¬¾</a>。 subject: Mastodon:%{instance} 確èªèªªæ˜Ž title: é©—è‰é›»åä¿¡ç®±ä½å€ email_changed: explanation: 您帳戶的電åä¿¡ç®±ä½å€å°‡è®Šæ›´ç‚ºï¼š - extra: 若您未變更電å信箱,那麼很有å¯èƒ½æ˜¯æŸäººå–å¾—äº†ä½ å¸³æˆ¶çš„å˜å–權é™ã€‚請立刻變更密碼,或當帳戶被鎖定時,請è¯çµ¡ä¼ºæœå™¨çš„管ç†å“¡ã€‚ + extra: 若您未變更電å信箱,那麼很有å¯èƒ½æ˜¯æŸäººå–得了您帳戶的å˜å–權é™ã€‚請立刻變更密碼,或當帳戶被鎖定時,請è¯çµ¡ä¼ºæœå™¨çš„管ç†å“¡ã€‚ subject: Mastodon:已變更電åä¿¡ç®± title: æ–°é›»åä¿¡ç®±ä½å€ password_change: explanation: 您帳戶的密碼已變更。 - extra: 如果您未變更密碼,那麼很有å¯èƒ½æ˜¯æŸäººå–得了帳戶的å˜å–權é™ã€‚請立刻變更密碼,或若帳戶被鎖定時,請è¯çµ¡ä¼ºæœå™¨çš„管ç†å“¡ã€‚ + extra: 若您未變更密碼,那麼很有å¯èƒ½æ˜¯æŸäººå–得了您帳戶的å˜å–權é™ã€‚請立刻變更密碼,或若帳戶被鎖定時,請è¯çµ¡ä¼ºæœå™¨çš„管ç†å“¡ã€‚ subject: Mastodon:已變更密碼 title: 密碼已變更 reconfirmation_instructions: @@ -43,7 +43,7 @@ zh-TW: reset_password_instructions: action: 變更密碼 explanation: 您已請求帳戶的新密碼。 - extra: 若您並未請求,請忽略æ¤ä¿¡ä»¶ã€‚您的密碼在å˜å–上方連çµä¸¦å»ºç«‹æ–°é€£çµå‰ä¸æœƒè®Šæ›´ã€‚ + extra: 若您並未請求,請忽略æ¤ä¿¡ä»¶ã€‚您的密碼在å˜å–上方連çµä¸¦å»ºç«‹æ–°å¯†ç¢¼å‰ä¸æœƒè®Šæ›´ã€‚ subject: Mastodon:é‡è¨å¯†ç¢¼æŒ‡å¼• title: é‡è¨å¯†ç¢¼ two_factor_disabled: @@ -60,13 +60,30 @@ zh-TW: title: 2FA 復原碼已變更 unlock_instructions: subject: Mastodon:解鎖指引 + webauthn_credential: + added: + explanation: 下é¢çš„安全密鑰已經新增至您的帳戶 + subject: Mastodon:新安全密鑰 + title: 已新增新安全密鑰 + deleted: + explanation: 以下的安全密鑰已經從您的帳戶ä¸ç§»é™¤ + subject: Mastodon:安全密鑰已移除 + title: 您的一支安全密鑰已經被移除 + webauthn_disabled: + explanation: 您的帳戶並沒有啟用安全密鑰èªè‰æ–¹å¼ã€‚åªèƒ½ä»¥ TOTP app 產生地æˆå° token 登入。 + subject: Mastodon:安全密鑰èªè‰æ–¹å¼å·²é—œé–‰ + title: 已關閉安全密鑰 + webauthn_enabled: + explanation: 您的帳戶已啟用安全密鑰èªè‰ã€‚您å¯ä»¥ä½¿ç”¨å®‰å…¨å¯†é‘°ç™»å…¥äº†ã€‚ + subject: Mastodon:已啟用安全密鑰èªè‰ + title: 已啟用安全密鑰 omniauth_callbacks: failure: 無法é€éŽ %{kind} èªè‰æ˜¯å¦ç‚ºæ‚¨ï¼Œå› 為「%{reason}ã€ã€‚ success: æˆåŠŸé€éŽ %{kind} 帳戶登入。 passwords: no_token: æ‚¨å¿…é ˆé€éŽå¯†ç¢¼é‡è¨ä¿¡ä»¶æ‰èƒ½å˜å–æ¤é é¢ã€‚若確實如æ¤ï¼Œè«‹ç¢ºå®šè¼¸å…¥çš„ç¶²å€æ˜¯å®Œæ•´çš„。 - send_instructions: 若電åä¿¡ç®±ä½å€å˜åœ¨æ–¼è³‡æ–™åº«ï¼Œå¹¾åˆ†é˜å¾Œæ‚¨å°‡åœ¨ä¿¡ç®±ä¸æ”¶åˆ°å¯†ç¢¼å¾©åŽŸé€£çµã€‚若未收到請檢查垃圾郵件資料夾。 - send_paranoid_instructions: 若電åä¿¡ç®±ä½å€å˜åœ¨æ–¼è³‡æ–™åº«ï¼Œå¹¾åˆ†é˜å¾Œæ‚¨å°‡åœ¨ä¿¡ç®±ä¸æ”¶åˆ°å¯†ç¢¼å¾©åŽŸé€£çµã€‚若未收到請檢查垃圾郵件資料夾。 + send_instructions: 若電åä¿¡ç®±ä½å€å˜åœ¨æ–¼æˆ‘們的資料庫,幾分é˜å¾Œæ‚¨å°‡åœ¨ä¿¡ç®±ä¸æ”¶åˆ°å¯†ç¢¼å¾©åŽŸé€£çµã€‚若未收到請檢查垃圾郵件資料夾。 + send_paranoid_instructions: 若電åä¿¡ç®±ä½å€å˜åœ¨æ–¼æˆ‘們的資料庫,幾分é˜å¾Œæ‚¨å°‡åœ¨ä¿¡ç®±ä¸æ”¶åˆ°å¯†ç¢¼å¾©åŽŸé€£çµã€‚若未收到請檢查垃圾郵件資料夾。 updated: 您的密碼已æˆåŠŸè®Šæ›´ï¼Œç¾åœ¨å·²ç¶“登入。 updated_not_active: 您的密碼已æˆåŠŸè®Šæ›´ã€‚ registrations: @@ -76,14 +93,14 @@ zh-TW: signed_up_but_locked: 您已註冊æˆåŠŸï¼Œä½†ç”±æ–¼æ‚¨çš„å¸³æˆ¶å·²è¢«éŽ–å®šï¼Œæˆ‘å€‘ç„¡æ³•è®“æ‚¨ç™»å…¥ã€‚ signed_up_but_pending: 包å«ç¢ºèªé€£çµçš„訊æ¯å·²å¯„到您的電å信箱。按下æ¤é€£çµå¾Œæˆ‘å€‘å°‡å¯©æ ¸æ‚¨çš„ç”³è«‹ã€‚æ ¸å‡†å¾Œå°‡é€šçŸ¥æ‚¨ã€‚ signed_up_but_unconfirmed: 包å«ç¢ºèªé€£çµçš„訊æ¯å·²å¯„到您的電å信箱。請å‰å¾€é€£çµä»¥å•Ÿç”¨å¸³è™Ÿã€‚若未收到請檢查垃圾郵件資料夾。 - update_needs_confirmation: 已更新您的帳號,但ä»éœ€é©—è‰æ‚¨çš„æ–°ä¿¡ç®±ã€‚請檢查電å信箱並å‰å¾€ç¢ºèªé€£çµä¾†ç¢ºèªæ–°ä¿¡ç®±ä½å€ã€‚若未收到請檢查垃圾郵件資料夾。 + update_needs_confirmation: å·²æˆåŠŸæ›´æ–°æ‚¨çš„å¸³è™Ÿï¼Œä½†ä»éœ€é©—è‰æ‚¨çš„æ–°ä¿¡ç®±ã€‚請檢查電å信箱並å‰å¾€ç¢ºèªé€£çµä¾†ç¢ºèªæ–°ä¿¡ç®±ä½å€ã€‚若未收到請檢查垃圾郵件資料夾。 updated: 您的帳戶已æˆåŠŸæ›´æ–°ã€‚ sessions: already_signed_out: å·²æˆåŠŸç™»å‡ºã€‚ signed_in: å·²æˆåŠŸç™»å…¥ã€‚ signed_out: å·²æˆåŠŸç™»å‡ºã€‚ unlocks: - send_instructions: 幾分é˜å¾Œæ‚¨å°‡æ”¶åˆ°ç¢ºèªä¿¡ä»¶ã€‚若未收到æ¤ä¿¡ä»¶ï¼Œè«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶è³‡æ–™å¤¾ã€‚ + send_instructions: 幾分é˜å¾Œæ‚¨å°‡æ”¶åˆ°è§£éŽ–å¸³è™Ÿçš„æŒ‡å¼•ä¿¡ä»¶ã€‚è‹¥æœªæ”¶åˆ°è«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶è³‡æ–™å¤¾ã€‚ send_paranoid_instructions: è‹¥æ¤å¸³è™Ÿå˜åœ¨ï¼Œæ‚¨å°‡åœ¨å¹¾åˆ†é˜å¾Œæ”¶åˆ°è§£éŽ–æŒ‡å¼•ä¿¡ä»¶ã€‚è‹¥æœªæ”¶åˆ°è«‹æª¢æŸ¥åžƒåœ¾éƒµä»¶è³‡æ–™å¤¾ã€‚ unlocked: 已解鎖您的帳戶,請登入繼續。 errors: diff --git a/config/locales/doorkeeper.co.yml b/config/locales/doorkeeper.co.yml index 4f03c0c3238bcdd222c8f1037c9ca1d3be75362a..a4c8cd4fc60a8a9263959fe2314f8da830b13421 100644 --- a/config/locales/doorkeeper.co.yml +++ b/config/locales/doorkeeper.co.yml @@ -121,10 +121,10 @@ co: admin:write: mudificà tutti i dati nant'à u servore admin:write:accounts: realizà azzione di muderazione nant'à i conti admin:write:reports: realizà azzione di muderazione nant'à i rapporti - follow: Mudificà rilazione trà i conti - push: Riceve e vostre nutificazione push + follow: mudificà rilazione trà i conti + push: riceve e vostre nutificazione push read: leghje tutte l’infurmazioni di u vostru contu - read:accounts: Vede l'infurmazione di i conti + read:accounts: vede l'infurmazione di i conti read:blocks: vede i vostri blucchimi read:bookmarks: vede i vostri segnalibri read:favourites: vede i vostri favuriti diff --git a/config/locales/doorkeeper.eo.yml b/config/locales/doorkeeper.eo.yml index 89a579ae9afef1b30273a98435044fb7cef300d8..65066cd8e8e66d96b531fec07bf99678025c80ef 100644 --- a/config/locales/doorkeeper.eo.yml +++ b/config/locales/doorkeeper.eo.yml @@ -116,22 +116,22 @@ eo: title: OAuth-a rajtigo bezonata scopes: admin:read: legu ĉiujn datumojn en la servilo - admin:read:accounts: legas senteman informacion de ĉiuj kontoj - admin:read:reports: legas konfidencajn informojn de ĉiuj signaloj kaj signalitaj kontoj - admin:write: modifu ĉiujn datumojn en la servilo + admin:read:accounts: legi konfidencajn informojn de ĉiuj kontoj + admin:read:reports: legi konfidencajn informojn de ĉiuj signaloj kaj signalitaj kontoj + admin:write: modifi ĉiujn datumojn en la servilo admin:write:accounts: plenumi agojn de kontrolo sur kontoj admin:write:reports: plenumi agojn de kontrolo sur signaloj follow: ÅanÄi rilatojn al aliaj kontoj push: ricevi viajn puÅ-sciigojn read: legi ĉiujn datumojn de via konto - read:accounts: vidi la informojn de la konto - read:blocks: vidi viajn blokojn + read:accounts: vidi la informojn de la kontoj + read:blocks: vidi viajn blokadojn read:bookmarks: vidi viajn legosignojn read:favourites: vidi viajn stelumojn read:filters: vidi viajn filtrilojn read:follows: vidi viajn sekvatojn read:lists: vidi viajn listojn - read:mutes: vidi viajn silentigojn + read:mutes: vidi viajn silentigadojn read:notifications: vidi viajn sciigojn read:reports: vidi viajn signalojn read:search: serĉi vianome @@ -140,7 +140,7 @@ eo: write:accounts: ÅanÄi vian profilon write:blocks: bloki kontojn kaj domajnojn write:bookmarks: aldoni mesaÄojn al la legosignoj - write:favourites: stelumitaj mesaÄoj + write:favourites: stelumi mesaÄojn write:filters: krei filtrilojn write:follows: sekvi homojn write:lists: krei listojn diff --git a/config/locales/doorkeeper.es-AR.yml b/config/locales/doorkeeper.es-AR.yml index 85ab7729dea57b3211a2cbf464adccd4f67d5ec7..29ce9b4c18c71fe81adfaf170ec9803aac5792f9 100644 --- a/config/locales/doorkeeper.es-AR.yml +++ b/config/locales/doorkeeper.es-AR.yml @@ -79,12 +79,12 @@ es-AR: errors: messages: access_denied: El propietario del recurso o servidor de autorización denegó la petición. - credential_flow_not_configured: Las credenciales de contraseña del propietario del recurso falló debido a que Doorkeeper.configure.resource_owner_from_credentials está sin configurar. + credential_flow_not_configured: Las credenciales de contraseña del propietario del recurso fallaron debido a que "Doorkeeper.configure.resource_owner_from_credentials" está sin configurar. invalid_client: La autenticación del cliente falló debido a que es un cliente desconocido, o no está incluÃda la autenticación del cliente, o el método de autenticación no está soportado. invalid_grant: La concesión de autorización ofrecida no es válida, venció, se revocó, no coincide con la dirección web de redireccionamiento usada en la petición de autorización, o fue emitida para otro cliente. invalid_redirect_uri: La dirección web de redireccionamiento incluida no es válida. invalid_request: En la solicitud falta un parámetro requerido, o incluye un valor de parámetro no soportado, o está corrompida. - invalid_resource_owner: Las credenciales proporcionadas del propietario del recurso no son válidas, o no se puede encontrar al propietario del recurso. + invalid_resource_owner: Las credenciales proporcionadas del propietario del recurso no son válidas, o no se puede encontrar al propietario del recurso invalid_scope: El ámbito solicitado no es válido, o conocido, o está corrompido. invalid_token: expired: Venció la clave de acceso @@ -122,30 +122,30 @@ es-AR: admin:write:accounts: ejecutar acciones de moderación en cuentas admin:write:reports: ejecutar acciones de moderación en informes follow: modificar relaciones de cuenta - push: recibir tus notificaciones PuSH + push: recibir tus notificaciones push read: leer todos los datos de tu cuenta read:accounts: ver información de cuentas read:blocks: ver qué cuentas bloqueaste - read:bookmarks: mirá tus marcadores + read:bookmarks: ver tus marcadores read:favourites: ver tus favoritos read:filters: ver tus filtros read:follows: ver qué cuentas seguÃs read:lists: ver tus listas read:mutes: ver qué cuentas silenciaste read:notifications: ver tus notificaciones - read:reports: ver tus informes + read:reports: ver tus denuncias read:search: buscar en tu nombre - read:statuses: ver todos los estados + read:statuses: ver todos los toots write: modificar todos los datos de tu cuenta write:accounts: modificar tu perfil write:blocks: bloquear cuentas y dominios - write:bookmarks: estados del marcador - write:favourites: toots favoritos + write:bookmarks: marcar toots + write:favourites: marcar toots como favoritos write:filters: crear filtros write:follows: seguir cuentas write:lists: crear listas write:media: subir archivos de medios write:mutes: silenciar usuarios y conversaciones - write:notifications: limpiá tus notificaciones + write:notifications: limpiar tus notificaciones write:reports: denunciar otras cuentas - write:statuses: publicar estados + write:statuses: publicar toots diff --git a/config/locales/doorkeeper.hi.yml b/config/locales/doorkeeper.hi.yml index d758a5b5357d76effdf363eeb2c8e0dfb231c4aa..d7a933d1480714d106b279142200d9b917419574 100644 --- a/config/locales/doorkeeper.hi.yml +++ b/config/locales/doorkeeper.hi.yml @@ -1 +1,30 @@ +--- hi: + activerecord: + attributes: + doorkeeper/application: + name: आवेदन का नाम + redirect_uri: अनà¥à¤ªà¥à¤°à¥‡à¤·à¤¿à¤¤ URI + scopes: कारà¥à¤¯à¤•à¥à¤·à¥‡à¤¤à¥à¤° + website: आवेदन वेबसाइट + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: à¤à¤• टà¥à¤•ड़ा नहीं हो सकता। + invalid_uri: à¤à¤• वैध यूआरआई होना चाहिà¤à¥¤ + relative_uri: à¤à¤• पूरà¥à¤£ URI होना चाहिà¤à¥¤ + secured_uri: hTTPS/SSL URI होना चाहिà¤à¥¤ + doorkeeper: + applications: + buttons: + authorize: अधिकार दें + cancel: रदà¥à¤¦ करें + destroy: हटाà¤à¤‚ + edit: संपादित करें + submit: सबमिट करें + confirmations: + destroy: कà¥à¤¯à¤¾ आप सà¥à¤¨à¤¿à¤¶à¥à¤šà¤¿à¤¤ हैं? + edit: + title: आवेदन संपादित करें diff --git a/config/locales/doorkeeper.hr.yml b/config/locales/doorkeeper.hr.yml index 221ec27e94284d0d3191a5e24f9a1718e75c3ddf..d2cde038b88cce1597eb516385bbd3a2166dc407 100644 --- a/config/locales/doorkeeper.hr.yml +++ b/config/locales/doorkeeper.hr.yml @@ -3,7 +3,9 @@ hr: activerecord: attributes: doorkeeper/application: - name: Ime + name: Ime aplikacije + scopes: Opsezi + website: Web-stranica aplikacije errors: models: doorkeeper/application: @@ -22,26 +24,27 @@ hr: edit: Uredi submit: PoÅ¡alji confirmations: - destroy: Jesi li siguran? + destroy: Jeste li sigurni? edit: title: Uredi aplikaciju form: - error: Ups! Provjeri svoju formu za moguće greÅ¡ke + error: Ups! Provjerite svoj obrazac za moguće greÅ¡ke help: native_redirect_uri: Koristi %{native_redirect_uri} za lokalne testove - redirect_uri: Koristi jednu liniju po URI - scopes: Odvoji scopes sa razmacima. Ostavi prazninu kako bi koristio zadane scopes. + redirect_uri: Koristi jednu liniju po URI-u + scopes: Odvojite opsege razmacima. Za koriÅ¡tenje zadanih opsega, ostavite prazno. index: + application: Aplikacija name: Ime - new: Nova Aplikacija - title: Tvoje aplikacije + new: Nova aplikacija + title: VaÅ¡e aplikacije new: - title: Nova Aplikacija + title: Nova aplikacija show: - actions: Akcije - application_id: Id Aplikacije - callback_urls: Callback urls - secret: Tajna + actions: Radnje + application_id: KljuÄ klijenta + callback_urls: URL-ovi povratnih poziva + secret: Tajna klijenta title: 'Aplikacija: %{name}' authorizations: buttons: @@ -51,34 +54,34 @@ hr: title: DoÅ¡lo je do greÅ¡ke new: able_to: Moći će - prompt: Aplikacija %{client_name} je zatražila pristup tvom raÄunu - title: Traži se autorizacija + prompt: Aplikacija %{client_name} zatražila je pristup VaÅ¡em raÄunu + title: Potrebna je autorizacija authorized_applications: buttons: revoke: Odbij confirmations: - revoke: Jesi li siguran? + revoke: Jeste li sigurni? index: application: Aplikacija created_at: OvlaÅ¡eno - title: Tvoje autorizirane aplikacije + title: VaÅ¡e autorizirane aplikacije errors: messages: - access_denied: Vlasnik resursa / autorizacijski server je odbio zahtjev. - invalid_client: Autentifikacija klijenta nije uspjela zbog nepoznatog klijenta, neukljuÄene autentifikacije od strane klijenta, ili nepodržane metode autentifikacije. - invalid_redirect_uri: The redirect uri included nije valjan. - invalid_request: Zahtjevu nedostaje traženi parametar, ukljuÄuje nepodržanu vrijednost parametra, ili je na neki drugi naÄin neispravno formiran. - invalid_resource_owner: The provided resource owner credentials nisu valjani, ili vlasnik resursa ne može biti naÄ‘en - invalid_scope: Traženi scope nije valjan, znan, ili je neispravno oblikovan. + access_denied: Vlasnik resursa ili autorizacijski poslužitelj odbili su zahtjev. + invalid_client: Autentifikacija klijenta nije uspjela zbog nepoznatog klijenta, nedostatka autentifikacije klijenta ili nepodržane metode autentifikacije. + invalid_redirect_uri: Sadržani uri preusmjerenja nije valjan. + invalid_request: Zahtjevu nedostaje traženi parametar, ukljuÄuje nepodržanu vrijednost parametra ili je na neki drugi naÄin neispravno formatiran. + invalid_resource_owner: Pružene vjerodajnice vlasnika resursa nisu valjane ili nije moguće pronaći vlasnika resursa + invalid_scope: Traženi opseg nije valjan, znan ili je neispravno oblikovan. invalid_token: expired: Pristupni token je istekao - revoked: Pristupni token je odbijen + revoked: Pristupni token je opozvan unknown: Pristupni token nije valjan - server_error: Autorizacijski server naiÅ¡ao je na neoÄekivani uvjet, Å¡to ga je onemogućilo da ispuni zahtjev. - temporarily_unavailable: Autorizacijski server trenutno nije u mogućnosti izvesti zahtjev zbog privremenog preopterećenja ili održavanja servera. + server_error: Autorizacijski poslužitelj naiÅ¡ao je na neoÄekivani uvjet koji sprjeÄava provoÄ‘enje zahtjeva. + temporarily_unavailable: Autorizacijski poslužitelj trenutno nije u mogućnosti obraditi zahtjev zbog privremenog preopterećenja ili njegovog održavanja. unauthorized_client: Klijent nije ovlaÅ¡ten izvesti zahtjev koristeći ovu metodu. - unsupported_grant_type: The authorization grant tip nije podržan od autorizacijskog servera. - unsupported_response_type: Autorizacijski server ne podržava ovaj tip odgovora. + unsupported_grant_type: Autorizacijski poslužitelj ne podržava ovu vrstu autorizacijskog odobrenja. + unsupported_response_type: Autorizacijski poslužitelj ne podržava ovu vrstu odgovora. flash: applications: create: @@ -89,7 +92,7 @@ hr: notice: Aplikacija je ažurirana. authorized_applications: destroy: - notice: Aplikacija je odbijena. + notice: Aplikacija je opozvana. layouts: admin: nav: @@ -97,6 +100,6 @@ hr: application: title: Traži se OAuth autorizacija scopes: - follow: slijediti, blokirati, deblokirati i prestati slijediti raÄune - read: Äitati podatke tvog raÄuna - write: slati poruke u tvoje ime + follow: mijenjati odnose izmeÄ‘u raÄuna + read: Äitati sve podatke VaÅ¡eg raÄuna + write: mijenjati sve podatke VaÅ¡eg raÄuna diff --git a/config/locales/doorkeeper.hy.yml b/config/locales/doorkeeper.hy.yml index 0a39ce30f6220f5cab4c13aa8765fb35cc511b35..ba3f4e124d6a5d38ac51609eaaa91cd0a0a3ce56 100644 --- a/config/locales/doorkeeper.hy.yml +++ b/config/locales/doorkeeper.hy.yml @@ -1,16 +1,157 @@ --- hy: + activerecord: + attributes: + doorkeeper/application: + name: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ« Õ¡Õ¶Õ¸Ö‚Õ¶ + redirect_uri: Õ¾Õ¥Ö€Õ¡Õ²ÕµÕ¥Õ¬ URI + scopes: Ô´Õ¡Õ·Õ¿Õ¥Ö€ + website: 'Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ« Õ¾Õ§Õ¢Õ¯Õ¡ÕµÖ„ + +' + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ´Õ¡Õ½ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬ + invalid_uri: ÕºÕ§Õ¿Ö„ Õ§ Õ¬Õ«Õ¶Õ« Õ¾Õ¡Ö‚Õ§Ö€ URIÖ‰ + relative_uri: ÕºÕ§Õ¿Ö„ Õ§ Õ¬Õ«Õ¶Õ« Õ¢Õ¡ÖÕ¡Ö€Õ±Õ¡Õ¯ URIÖ‰ + secured_uri: ÕºÕ§Õ¿Ö„ Õ§ Õ¬Õ«Õ¶Õ« HTTPS/SSL URIÖ‰ doorkeeper: applications: buttons: + authorize: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ cancel: Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ + destroy: ÕŽÕ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬ edit: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ + submit: ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ + confirmations: + destroy: ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½ + edit: + title: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ + form: + error: Վա՜յ․ ÕÕ¿Õ¸Ö‚Õ£Õ«Ö€ Õ±Õ¥Ö‚Õ¡Õ¶Õ´Õ¸Ö‚Õ·Õ¸Ö‚Õ´ Õ¥Õ²Õ¡Õ® Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ½ÕÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ + help: + native_redirect_uri: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ %{native_redirect_uri} Õ¬Õ¸Õ¯Õ¡Õ¬ ÖƒÕ¸Ö€Õ±Õ¡Ö€Õ¯Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ + redirect_uri: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ Õ´Õ§Õ¯ Õ¿Õ¸Õ² Õ«Ö‚Ö€Õ¡Ö„Õ¡Õ¶Õ¹Õ«Ö‚Ö€ URI Õ°Õ¡Õ´Õ¡Ö€ + scopes: Ô²Õ¡ÕªÕ¡Õ¶Õ«Ö€ Õ¤Õ¡Õ·Õ¿Õ¥Ö€Õ¨ Õ¢Õ¡ÖÕ¡Õ¿Õ¶Õ¥Ö€Õ¸Õ¾Ö‰ Ô´Õ¡Õ¿Õ¡Ö€Õ¯ Õ©Õ¸Õ²Õ Õ¬Õ¼Õ¥Õ¬Õ¥Õ¡ÕµÕ¶ Õ¤Õ¡Õ·Õ¿Õ¥Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ index: + application: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ® + callback_url: URL Õ¥Õ¿Õ¯Õ¡Õ¶Õ¹ delete: Õ‹Õ¶Õ»Õ¥Õ¬ + empty: Ô´Õ¸Ö‚ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€Ö‰ name: Ô±Õ¶Õ¸Ö‚Õ¶ + new: Õ†Õ¸Ö€ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ® + scopes: Ô´Õ¡Õ·Õ¿Õ¥Ö€ show: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ + title: Õ”Õ¸ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€Õ¨ + new: + title: Õ†Õ¸Ö€ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ® show: - actions: Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ + actions: Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ + application_id: 'Ô¿Õ¬Õ«Õ¥Õ¶Õ¿Õ« Õ¢Õ¡Õ¶Õ¡Õ¬Õ« + +' + callback_urls: URLÖŠÕ¶Õ¥Ö€Õ« Õ¥Õ¿Õ¯Õ¡Õ¶Õ¹ + scopes: Ô´Õ¡Õ·Õ¿Õ¥Ö€ + secret: Ô¿Õ¬Õ«Õ¥Õ¶Õ¿Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ«Ö„ + title: Յաւելուած․ %{name} + authorizations: + buttons: + authorize: Ô¼Õ«Õ¡Õ¦Ö…Ö€Õ¥Õ¬ + deny: Õ„Õ¥Ö€ÕªÕ¥Õ¬ + error: + title: Ô±Õ¼Õ¡Õ»Õ¡ÖÕ¥Õ¬ Õ§ Õ½ÕÕ¡Õ¬Ö‰ + new: + able_to: Õ†Õ¡ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ§ + prompt: "%{client_name} ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ§ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¶" + title: Ô±Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´ + show: + title: ÕŠÕ¡Õ¿Õ³Õ§Õ¶Õ«Ö€ Õ¡ÕµÕ½ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¨ Õ¥Ö‚ ÖƒÕ¡Õ¯ÖÖ€Õ¸Ö‚ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¸Ö‚Õ´Ö‰ authorized_applications: + buttons: + revoke: Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ + confirmations: + revoke: ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½ index: + application: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ® + created_at: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÖ€Õ¡Õ® date_format: "%Y-%m-%d %H:%M:%S" + scopes: Ô´Õ¡Õ·Õ¿Õ¥Ö€ + title: Õ”Õ¸ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÖ€Õ¡Õ® Õ®Ö€Õ¡Õ£Ö€Õ¥Ö€Õ¨ + errors: + messages: + access_denied: Ռեսուրսի Õ¿Õ§Ö€Õ¨ Õ¯Õ¡Õ´ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¸Õ² Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¨ Õ´Õ¥Ö€ÕªÕ¥Õ¬ Õ§ Õ¤Õ«Õ´Õ¸Ö‚Õ´Õ¨Ö‰ + credential_flow_not_configured: Ռեսուրսի Õ¿Õ§Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¬Õ«Õ¡Õ¦Ö…Ö€Õ¡Õ£Ö€Õ¥Ö€Õ¨ Õ±Õ¡ÕÕ¸Õ²Õ¸Ö‚Õ¥ÖÕ«Õ¶ Doorkeeper.configure.resource_owner_from_credentialsÖŠÕ« Õ¹Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ + invalid_client: Ô¿Õ¬Õ«Õ¥Õ¶Õ¿Õ« Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ±Õ¡ÕÕ¸Õ²Õ¸Ö‚Õ¥Ö Õ¡Õ¶ÕµÕ¡ÕµÕ¿ Õ¯Õ¬Õ«Õ¥Õ¶Õ¿Õ«, Õ¯Õ¬Õ«Õ¥Õ¶Õ¿Õ« Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶, Õ¯Õ¡Õ´ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ¹Õ¡Õ»Õ¡Õ¯ÖÕ¸Ö‚Õ¸Õ² Õ±Õ¥Ö‚Õ« ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ + invalid_grant: ÕÖ€Õ¡Õ´Õ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ§, Õ½ÕºÕ¡Õ¼Õ¸Ö‚Õ¡Õ®, Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ®, Õ¹Õ« Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¸Ö‚Õ´ Õ¾Õ¥Ö€Õ¡ÕµÕ²Õ¸Ö‚Õ¡Õ® URIÖŠÕ« Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ ÕµÕ¡ÕµÕ¿Õ«Õ¶, Õ¯Õ¡Õ´ ÕµÕ²Õ¸Ö‚Õ¥Õ¬ Õ§ Õ¡ÕµÕ¬ Õ¯Õ¬Õ«Õ¥Õ¶Õ¿Õ«Ö‰ + invalid_redirect_uri: ÕŽÕ¥Ö€Õ¡ÕµÕ²Õ¸Ö‚Õ¡Õ® uriÖŠÕ« Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ§Ö‰ + invalid_request: Õ…Õ¡ÕµÕ¿Õ«Ö Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´ Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ¸Õ² ÕºÕ¡Ö€Õ¡Õ´Õ¥Õ¿Ö€Õ¨, Õ¶Õ¥Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ§ Õ¹Õ¡Õ»Õ¡Õ¯ÖÕ¸Ö‚Õ¸Õ² Õ¡Ö€ÕªÕ§Ö„ Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ Õ¡Õ¶Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ©Õ«Ö‚Õ¶Ö‰ + invalid_resource_owner: ÕÖ€Õ¡Õ´Õ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ« Õ¿Õ«Ö€Õ¸Õ» Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ¥Õ¶ Õ¯Õ¡Õ´ Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ« Õ¿Õ§Ö€Õ¨ Õ¹Õ« Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Õ¬ + invalid_scope: Õ…Õ¡ÕµÕ¿Õ« Õ¤Õ¡Õ·Õ¿Õ¶ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€, Õ¡Õ¶ÕµÕ¡ÕµÕ¿ Õ¯Õ¡Õ´ Õ¡Õ¶Õ½Õ¡Ö€Ö„Ö‰ + invalid_token: + expired: Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ¿Ö€Õ¸Õ¶Õ¨ Õ½ÕºÕ¡Õ¼Õ¸Ö‚Õ¡Õ® Õ§ + revoked: Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ¿Ö€Õ¸Õ¶Õ¨ Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® Õ§ + unknown: Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ¿Ö€Õ¸Õ¶Õ¨ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ§ + resource_owner_authenticator_not_configured: Ռեսուրսի Õ¿Õ§Ö€Õ¨ Õ¹Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Ö Doorkeeper.configure.resource_owner_authenticatorÖŠÕ« Õ¹Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ + server_error: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¨ Õ¢Õ¡ÕÕ¸Ö‚Õ¥Õ¬ Õ§ Õ¹Õ¶Õ¡ÕÕ¡Õ¿Õ¥Õ½Õ¸Ö‚Õ¡Õ® ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ«, Õ¸Ö€Õ¨ ÕÕ¸Õ¹Õ¨Õ¶Õ¤Õ¸Õ¿Õ¸Ö‚Õ´ Õ§ ÕµÕ¡ÕµÕ¿Õ« Õ¬Ö€Õ¡ÖÕ´Õ¡Õ¶Õ¨Ö‰ + temporarily_unavailable: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶ Õ¡ÕµÕªÕ´ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¨Õ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ« ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Ö‚Õ¸Ö€ Õ®Õ¡Õ¶Ö€Õ¡Õ¢Õ¥Õ¼Õ¶Õ´Õ¡Õ¶ Õ¯Õ¡Õ´ ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ + unauthorized_client: Ô¿Õ¬Õ«Õ¥Õ¶Õ¿Õ¨ Õ¬Õ«Õ¡Õ¦Ö…Ö€Õ¸Ö‚Õ¡Õ® Õ¹Õ§ Õ«Ö€Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¶ Õ¡ÕµÕ½ Õ´Õ¥Õ©Õ¸Õ¤Õ¸Õ¾Ö‰ + unsupported_grant_type: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ¬Õ«Õ¡Õ¦Ö…Ö€Õ¸Ö‚Õ´Õ¨ Õ¹Õ« Õ¡Õ»Õ¡Õ¯ÖÕ¸Ö‚Õ¸Ö‚Õ´ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰ + unsupported_response_type: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ½Õ¥Ö€Õ¸Ö‚Õ¥Ö€Õ¨ Õ¹Õ« Õ¡Õ»Õ¡Õ¯ÖÕ¸Ö‚Õ´ Õ¡ÕµÕ½ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¨Ö‰ + flash: + applications: + create: + notice: ÕÕ¿Õ¥Õ²Õ®Õ¸Ö‚Õ¥Õ¬ Õ§ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Ö‰ + destroy: + notice: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ Õ»Õ¶Õ»Õ¸Ö‚Õ¥Õ¬ Õ§Ö‰ + update: + notice: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥Õ¬ Õ§Ö‰ + authorized_applications: + destroy: + notice: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§Ö‰ + layouts: + admin: + nav: + applications: Õ…Õ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€ + oauth2_provider: OAuth2 Õ´Õ¡Õ¿Õ¡Õ¯Õ¡Ö€Õ¡Ö€ + application: + title: Ô±Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ OAuth Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´ + scopes: + admin:read: Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¸Õ²Õ» Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ + admin:read:accounts: Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€Õ« Õ¦Õ£Õ¡ÕµÕ¸Ö‚Õ¶ Õ«Õ¶Ö†Õ¸Ö€Õ´Õ¡ÖÕ«Õ¡Õ¶ + admin:read:reports: Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€Õ« Õ¥Ö‚ ÕµÕ¡Õ²Õ¸Ö€Õ¤Õ¸Ö‚Õ¡Õ® Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€Õ« Õ¦Õ£Õ¡ÕµÕ¸Ö‚Õ¶ Õ«Õ¶Ö†Õ¸Ö€Õ´Õ¡ÖÕ«Õ¡Õ¶ + admin:write: ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¸Õ²Õ» Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ + admin:write:accounts: Õ«Ö€Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€Õ« Õ¾Ö€Õ¡Õµ + admin:write:reports: Õ«Ö€Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€Õ« Õ¾Ö€Õ¡Õµ + follow: ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« ÕµÕ¡Ö€Õ¡Õ¢Õ¥Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ + push: Õ½Õ¿Õ¡Õ¶Õ¡Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + read: Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ + read:accounts: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€Õ« Õ«Õ¶Ö†Õ¸Ö€Õ´Õ¡ÖÕ«Õ¡Õ¶ + read:blocks: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + read:bookmarks: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¶Õ¥Ö€Õ¨ + read:favourites: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ°Õ¡Ö‚Õ¡Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + read:filters: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€Õ¨ + read:follows: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ + read:lists: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¥Ö€Õ¨ + read:mutes: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ®Õ¶Õ¥Ö€Õ«Õ¶ + read:notifications: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + read:reports: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€Õ¨ + read:search: Õ¸Ö€Õ¸Õ¶Õ«Ö€ Ö„Õ¸ Õ¡Õ¶Õ¸Ö‚Õ¶Õ«Ö + read:statuses: Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + write: ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Ö„Õ¸ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ + write:accounts: ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + write:blocks: Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ Õ¤Õ¸Õ´Õ§ÕµÕ¶Õ¶Õ¥Ö€Õ¨ + write:bookmarks: Õ§Õ»Õ¡Õ¶Õ·Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + write:favourites: Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + write:filters: 'Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Ö†Õ«Õ¬Õ¿Ö€Õ¥Ö€ + +' + write:follows: Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ + write:lists: Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ ÖÕ¡Õ¶Õ¯Õ¥Ö€ + write:media: Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡ Ö†Õ¡ÕµÕ¬Õ¥Ö€ + write:mutes: Õ¬Õ¼Õ¥ÖÕ¶Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¥Ö‚ Õ¦Ö€Õ¸ÕµÖÕ¶Õ¥Ö€Õ¨ + write:notifications: Õ´Õ¡Ö„Ö€Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + write:reports: Õ¢Õ¸Õ²Õ¸Ö„Õ¥Õ¬ Õ¡ÕµÕ¬Õ¸ÖÕ«Ö + write:statuses: Õ©Õ©Õ¥Õ¬ diff --git a/config/locales/doorkeeper.it.yml b/config/locales/doorkeeper.it.yml index 68e2b57f3eefd147d27901c86c7a497d0088fef0..607abb2b3465760c19e3b11b583952ed0f6cd624 100644 --- a/config/locales/doorkeeper.it.yml +++ b/config/locales/doorkeeper.it.yml @@ -25,7 +25,7 @@ it: edit: Modifica submit: Invia confirmations: - destroy: Sei sicuro? + destroy: Sei sicur*? edit: title: Modifica applicazione form: @@ -69,7 +69,7 @@ it: buttons: revoke: Disabilita confirmations: - revoke: Sei sicuro? + revoke: Sei sicur*? index: application: Applicazione created_at: Autorizzato diff --git a/config/locales/doorkeeper.ku.yml b/config/locales/doorkeeper.ku.yml index cc251e86ae3fc9c96ba4a32a86e9e41868ac09d9..29d5f40dbe1eca0daef84b9e25b1121d45ef725d 100644 --- a/config/locales/doorkeeper.ku.yml +++ b/config/locales/doorkeeper.ku.yml @@ -1 +1,151 @@ -ckb-IR: +--- +ku: + activerecord: + attributes: + doorkeeper/application: + name: ناوی بەرنامە + redirect_uri: URI گۆڕانی شوێن + scopes: بوارەکان + website: نەرمەکالای ماڵپەڕ + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: ناتوانێت پارچەیەک لەخۆوە بگری. + invalid_uri: پێویستە URI دروست بێت. + relative_uri: پێویستە URI ÛŒ ڕەها بێت. + secured_uri: پێویستە HTTPS/SSL URI بێت. + doorkeeper: + applications: + buttons: + authorize: ڕێگەپێدان + cancel: هەڵوەشاندنەوه + destroy: لەناوبردن + edit: دەستکاری + submit: ناردن + confirmations: + destroy: دڵنیای? + edit: + title: دەستکاری کردنی بەرنامە + form: + error: ØªÛ•ØØ! بزانە شتێکت Ù„Û• Ù†ÛŽÙˆ Ùۆرمەکە بە Ù‡Û•ÚµÛ• نەنووسیوە + help: + native_redirect_uri: بۆ تاقیکردنەوەی ناوخۆیی %{native_redirect_uri} بەکاربەرە، + redirect_uri: بەکارهێنانی یەک Ù‡ÛŽÚµ بۆ هەر URI + scopes: دۆمەینەکان جیاببکەن بە بۆشاییەکان. بۆ بەکارهێنانی دۆمەینی گریمانەیی Ú†Û†ÚµÛŒ بەجێبهێڵە. + index: + application: نەرمەکال + callback_url: Callback نیشانی + delete: سڕینەوە + empty: هیچ بەرنامەیەکت نیە. + name: ناو + new: بەرنامەی نوێ + scopes: دۆمەینەکان + show: نیشاندان + title: بەرنامەی تۆ + new: + title: بەرنامەی نوێ + show: + actions: کارەکان + application_id: کلیلی ڕاژەخواز + callback_urls: Callback نیشانەکانی + scopes: دۆمەینەکان + secret: نهێنی ڕاژەخواز + title: 'بەرنامە: %{name}' + authorizations: + buttons: + authorize: ڕێپێدراو + deny: Ù†Ú©Û†ÚµÛŒ لێبکە + error: + title: هەڵەیەک ڕوویدا + new: + able_to: دەتوانێت + prompt: بەکارهێنانی %{client_name} داوای چوونە ژوورەوە بۆ هەژمارەکەت دەکات + title: ڕێپێدان پێویستە + show: + title: کۆپیکردنی کۆدی ئەم رێپێدانە Ùˆ لکاندنی بە بەرنامەکە. + authorized_applications: + buttons: + revoke: بەتاڵی بکە + confirmations: + revoke: ئایا دڵنیایت? + index: + application: نەرمەکال + created_at: ده‌سه‌ڵاتپێدراو + date_format: "%Y-%m-%d %H:%M:%S" + scopes: بوارەکان + title: بەرنامە ڕێگەپێدراوەکانت + errors: + messages: + access_denied: خاوەنی سەرچاوە یان سێرڤەری ڕێپێدان داواکاریەکەی ڕەت کردەوە. + credential_flow_not_configured: لێشاوی بڕواپێدانی تێپەڕەوشەی خاوەن سەرچاوە شکستی هێنا بەهۆی Doorkeeper.configure.resource_owner_from_credentials شێوەبەندی نەکراو. + invalid_client: سەلماندنی کڕیار سەرکەوتوو نەبوو بەهۆی کڕیاری نەناسراوەوە، هیچ ڕەسەنایەتی سەلماندنێکی کلایەنت لەخۆوە نەدەگرێت، یان شێوازی سەلماندنی پەسەند نەکراو. + invalid_grant: بەخشین مۆڵەتی دابینکراو نایاساییە، بەسەرچووە، هەڵوەشاندنەوەیە، ناگونجێلەگەڵ ئاراستەی URI بەکارهاتوو Ù„Û• داواکاری ڕێپێدان، یان دەرچووە بۆ کڕیارێکی تر. + invalid_redirect_uri: Uri دووبارە ئاڕاستەکردنەوەکە لەخۆدەگرێت دروست نیە. + invalid_request: داواکاریەکە پارامیتەری داواکراوی بزرە، بەهای پارامیتەری پشتگیری نەکراو لەخۆ دەگرێت، یان بە پێچەوانەوە نادروستە. + invalid_resource_owner: بڕواپێدانەکانی خاوەنی سەرچاوەی دابینکراو دروست نیە، یان ناتوانرێت خاوەنی سەرچاوە بدۆزرێتەوە + invalid_scope: بواری داواکراو نادروستە، نەناسراو، یان تێکچووە. + invalid_token: + expired: نیشانەی چوونەژورەوە بەسەرچووە + revoked: کۆدی دەستپێگەیشتن بەتاڵ بووەتەوە + unknown: دەستپێگەیشتن بە کۆدی چوونەژوور باوڕپێنەکراوە + resource_owner_authenticator_not_configured: خاوەنی سەرچاوە بەهۆی Doorkeeper.configure.resource_owner_authenticator Ú©Û†Ù†Ùیگنەکردن سەرکەوتوو نەبوو. + server_error: ڕاژەکاری ڕێپێدان تووشی مەرجێکی چاوەڕوان نەکراو بوو Ú©Û• رێگری دەکا Ù„Û• جێبەجێ کردنی داواکاریەکە. + temporarily_unavailable: ڕاژەکاری ڕێپێدان Ù„Û• ئێستادا ناتوانێت داواکاریەکە چارەسەر بکات لەبەر بارکردنی کاتی یان چاککردنەوەی سێرڤەرەکە. + unauthorized_client: ڕاژەخوازەکە دەسەڵاتی ئەوەی نییە ئەم داواکاریە بە بەکارهێنانی ئەم شێوازە بدات. + unsupported_grant_type: جۆری بەخشینە مۆڵەتپێدانەکە لەلایەن ڕاژەکاری مۆڵەتەوە پەسەند ناکرێت. + unsupported_response_type: ڕاژەکاری ڕێگەپێدان پشتگیری ئەم جۆرە وەڵامە ناکات. + flash: + applications: + create: + notice: بەرنامە دروستکرا. + destroy: + notice: بەرنامە سڕایەوە. + update: + notice: بەرنامە بەڕۆژکرا. + authorized_applications: + destroy: + notice: بەرنامە هەڵوەشێنڕا. + layouts: + admin: + nav: + applications: بەرنامەکان + oauth2_provider: OAuth2 Provider + application: + title: داوای ڕێپێدانی OAuth + scopes: + admin:read: خوێندنەوەی هەموو داتاکان لەسەر ڕاژەکارەکە + admin:read:accounts: زانیاری هەستیاری هەموو هەژمارەکان بخوێنەوە + admin:read:reports: زانیاری هەستیاری هەموو گوزارشت Ùˆ هەژمارە گوزارشتکراوەکان بخوێنەوە + admin:write: دەستکاری هەموو داتاکان بکە لەسەر ڕاژەکار + admin:write:accounts: ئەنجامدانی کاری میانڕەوی لەسەر هەژمارەکان + admin:write:reports: ئەنجامدانی کاری میانڕەوی لەسەر گوزارشتەکان + follow: دەستکاریکردنی پەیوەندییەکانی هەژمارەی بەکارهێنەر + push: وەرگرتنی ئاگانامەکانی پاڵنان + read: هەموو دراوەکانی هەژمارەکەت بخوێنەوە + read:accounts: بینینی زانیاری هەژمارەکان + read:blocks: بینینی بلۆکەکانت + read:bookmarks: نیشانەکان ببینە + read:favourites: بینینی دڵخوازەکانت + read:filters: بینینی Ù¾Ø§ÚµØ§ÙØªÙ†Û•کانت + read:follows: سەیری شوێنکەوتەکانت بکە + read:lists: بینینی لیستەکانت + read:mutes: بێدەنگەکانت ببینە + read:notifications: ئاگانامەکانت ببینە + read:reports: سەیری گوزارشەکانت بکە + read:search: گەڕان Ù„Û• جیاتی تۆ + read:statuses: بینینی هەموو بارودۆخەکان + write: دەستکاری هەموو داتاکانی هەژمارەکەت بکە + write:accounts: دەستکاری Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت بکە + write:blocks: بلۆک کردنی هەژمارەکەی دۆمەینەکان + write:bookmarks: بارەکانی نیشانکەر + write:favourites: دۆخی دڵخوازەکان + write:filters: پاڵێوەر دروست بکە + write:follows: دوای خەڵک بکەوە + write:lists: دروستکردنی لیستەکان + write:media: Ù¾Û•Ú•Ú¯Û•ÛŒ میدیا باربکە + write:mutes: بێدەنگکردنی خەڵک Ùˆ Ú¯ÙØªÙˆÚ¯Û†Ú©Ø§Ù† + write:notifications: ئاگانامەکانت بسڕیەوە + write:reports: گوزارشتکردنی کەسانی تر + write:statuses: بڵاوکردنەوەی بارودۆخەکان diff --git a/config/locales/doorkeeper.ml.yml b/config/locales/doorkeeper.ml.yml index 5dfaa61aec30099be6938d0d24b50e0f03b2b231..21540b9766d90dce18867380de217587cc443ddf 100644 --- a/config/locales/doorkeeper.ml.yml +++ b/config/locales/doorkeeper.ml.yml @@ -4,6 +4,7 @@ ml: attributes: doorkeeper/application: name: à´…à´ªàµà´²à´¿à´•àµà´•േഷനàµà´±àµ† പേരൠ+ redirect_uri: യൠആർ എൽ വഴിതിരിചàµà´šàµ വിടàµà´• website: à´…à´ªàµà´²à´¿à´•àµà´•േഷനàµà´±àµ† വെബàµà´¸àµˆà´±àµà´±àµ errors: models: diff --git a/config/locales/doorkeeper.oc.yml b/config/locales/doorkeeper.oc.yml index f92b7cd22e77da5efaeef08e17d5949b36cfd72a..d84b5e7d9cd6a5dbcff477610da4a8e3b6804e9e 100644 --- a/config/locales/doorkeeper.oc.yml +++ b/config/locales/doorkeeper.oc.yml @@ -142,10 +142,10 @@ oc: write:bookmarks: ajustar als marcadors write:favourites: metre en favorit write:filters: crear de filtres - write:follows: sègre de monde + write:follows: sègre de mond write:lists: crear de listas write:media: mandar de fichièrs mèdias - write:mutes: rescondre de monde e de conversacions + write:mutes: rescondre de mond e de conversacions write:notifications: escafar vòstras notificacions - write:reports: senhalar de monde + write:reports: senhalar de mond write:statuses: publicar d’estatuts diff --git a/config/locales/doorkeeper.sa.yml b/config/locales/doorkeeper.sa.yml new file mode 100644 index 0000000000000000000000000000000000000000..07ea4372a3a109674214ba80f2070c9f99fb872d --- /dev/null +++ b/config/locales/doorkeeper.sa.yml @@ -0,0 +1 @@ +sa: diff --git a/config/locales/doorkeeper.sc.yml b/config/locales/doorkeeper.sc.yml index 91bd6d92f04580bfea64f85ac0291ed4a4c1fb7c..2a6aeb2c158ffaa606e2c53fd79f2385a8b96f55 100644 --- a/config/locales/doorkeeper.sc.yml +++ b/config/locales/doorkeeper.sc.yml @@ -1 +1,151 @@ +--- sc: + activerecord: + attributes: + doorkeeper/application: + name: Nòmine de s'aplicatzione + redirect_uri: URL de re-indiritzamentu + scopes: Àmbitos + website: Situ web de s'aplicatzione + errors: + models: + doorkeeper/application: + attributes: + redirect_uri: + fragment_present: non podet cuntènnere un'ascra. + invalid_uri: depet èssere un'URI và lidu. + relative_uri: devet èssere un'URI assolutu. + secured_uri: depet èssere un'URI HTTPS/SSL. + doorkeeper: + applications: + buttons: + authorize: Autoriza + cancel: Annulla + destroy: Distrue + edit: Modìfica + submit: Imbia + confirmations: + destroy: Seguru? + edit: + title: Modìfica s'aplicatzione + form: + error: Controlla si su formulà riu tuo tenet faddinas + help: + native_redirect_uri: Imprea %{native_redirect_uri} pro is tests locales + redirect_uri: Imprea una lìnia pro ogni URI + scopes: Iscroba is à mbitos cun ispà tzios. Lassa bòidu pro impreare is predefinidos. + index: + application: Aplicatzione + callback_url: URL de torrada + delete: Cantzella + empty: No tenes peruna aplicatzione. + name: Nòmine + new: Aplicatzione noa + scopes: Àmbitos + show: Ammustra + title: Is aplicatziones tuas + new: + title: Aplicatzione noa + show: + actions: Atziones + application_id: ID de s'aplicatzione + callback_urls: URLs de torrada + scopes: Àmbitos + secret: Segretu de cliente + title: 'Aplicatzione: %{name}' + authorizations: + buttons: + authorize: Autoriza + deny: Refuda + error: + title: Faddina + new: + able_to: At a pòdere + prompt: S'aplicatzione %{client_name} est preguntende atzessu a su contu tuo + title: Autorizatzione rechesta + show: + title: Còpia custu còdighe de autorizatzione e incolla·ddu a s'aplicatzione. + authorized_applications: + buttons: + revoke: Rèvoca + confirmations: + revoke: Seguru? + index: + application: Aplicatzione + created_at: Autorizada + date_format: "%Y-%m-%d %H:%M:%S" + scopes: Àmbitos + title: Is aplicatziones autorizadas tuas + errors: + messages: + access_denied: Sa propiedade sa resursa o su serbidore de autorizatziones at refudadu sa rechesta. + credential_flow_not_configured: Su flussu de is credentziales de sa crae de intrada de su mere de sa risursa est fallidu pro neghe de su fatu chi Doorkeeper.configure.resource_owner_from_credentials no est cunfiguradu. + invalid_client: S'autenticatzione de su cliente est fallida ca su cliente est disconnotu, s'atzessu a su cliente no est istadu incluidu, o sa manera de autenticatzione no est suportada. + invalid_grant: Su permissu de autorizatzione est invà lidu, iscadidu, revocadu, non currispondet a s'URI de re-indiritzamentu impreadu in sa rechesta de autorizatzione, o est istadu frunidu a un'à teru cliente. + invalid_redirect_uri: S'URI de re-indiritzamentu no est và lidu. + invalid_request: In sa rechesta mancat unu parà metru netzessà riu, ddoe est unu valore de unu parà metru non suportadu o est fata male in carchi à tera manera. + invalid_resource_owner: Is credentziales de su mere de sa risursa frunidas non sunt và lidas, o su mere de sa risursa non podet èssere agatadu + invalid_scope: S'à mbitu pedidu est invà lidu, disconnotu, o formuladu male. + invalid_token: + expired: Su getone de atzessu est iscadidu + revoked: Su getone de atzessu est istadu revocadu + unknown: Su getone de atzessu no est và lidu + resource_owner_authenticator_not_configured: Su mere de sa risursa no est istadu agatadu pro neghe de su fatu chi Doorkeeper.configure.resource_owner_authenticator no est configuradu. + server_error: Su serbidore de autorizatzione at agatadu una cunditzione no isetada chi dd'at impedidu de esecutare sa rechesta tua. + temporarily_unavailable: Su serbidore de autorizatzione no est, in custu momentu, in gradu de gestire sa rechesta pro neghe de unu subracà ricu temporà neu o de una manutentzione. + unauthorized_client: Su cliente no est autorizadu a esecutare custa rechesta in custa manera. + unsupported_grant_type: Sa casta de modalidade de autorizatzione no est suportada dae su serbidore de atzessu. + unsupported_response_type: Su serbidore de autorizatzione non suportat custa casta de risposta. + flash: + applications: + create: + notice: Aplicatzione creada. + destroy: + notice: Aplicatzione cantzellada. + update: + notice: Aplicatzione atualizada. + authorized_applications: + destroy: + notice: Aplicatzione revocada. + layouts: + admin: + nav: + applications: Aplicatziones + oauth2_provider: Frunidore OAuth2 + application: + title: Autorizatzione OAuth netzessà ria + scopes: + admin:read: lèghere totu is datos de su serbidore + admin:read:accounts: lèghere informatziones sensìbiles de totu is contos + admin:read:reports: lèghere informatziones sensìbiles de totu is sinnalatziones e is contos sinnalados + admin:write: modificare totu is datos in su serbidore + admin:write:accounts: fà ghere atziones de moderatzione in is contos + admin:write:reports: fà ghere atziones de moderatzione in is sinnalatziones + follow: modificare is relatziones intre is contos + push: retzire is notìficas push tuas + read: lèghere totu is datos de su contu tuo + read:accounts: bìdere is informatziones in su contu + read:blocks: bìdere is blocos tuos + read:bookmarks: cà stia is sinnalibros tuos + read:favourites: bìdere is preferidos tuos + read:filters: bìdere is filtros tuos + read:follows: bìdere is sighiduras tuas + read:lists: bìdere is listas tuas + read:mutes: bìdere is utentes chi as postu a sa muda + read:notifications: bìdere is notìficas tuas + read:reports: bìdere is sinnalatziones tuas + read:search: chircare a nùmene tuo + read:statuses: bìdere totu is istados + write: modificare totu is datos de su contu tuo + write:accounts: modificare su profilu tuo + write:blocks: blocare contos e domìnios + write:bookmarks: agiunghe is istados a is sinnalibros + write:favourites: pònnere istados in is preferidos + write:filters: creare filtros + write:follows: sighire persones + write:lists: creare listas + write:media: cà rriga documentos multimediales + write:mutes: impostare persones e arresonadas a sa muda + write:notifications: isboidare is notìficas tuas + write:reports: sinnalare à teras persones + write:statuses: publicare istados diff --git a/config/locales/doorkeeper.sv.yml b/config/locales/doorkeeper.sv.yml index d9367ce5ea577a811cfedc4e6bfd0abed8871f70..015f0702f97cd551b017a8800ed2ac191e22b826 100644 --- a/config/locales/doorkeeper.sv.yml +++ b/config/locales/doorkeeper.sv.yml @@ -73,6 +73,7 @@ sv: index: application: Applikation created_at: Auktoriserad + date_format: "%Y-%m-%d %H:%M:%S" scopes: Omfattning title: Dina behöriga ansökningar errors: @@ -125,6 +126,7 @@ sv: read: läsa dina kontodata read:accounts: se kontoinformation read:blocks: se dina blockeringar + read:bookmarks: se dina bokmärken read:favourites: se dina favoriter read:filters: se dina filter read:follows: se vem du följer @@ -137,6 +139,7 @@ sv: write: posta Ã¥t dig write:accounts: ändra din profil write:blocks: blockera konton och domäner + write:bookmarks: bokmärkesstatusar write:favourites: favoritmarkera statusar write:filters: skapa filter write:follows: följ människor diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml index 672271728df2221960ad21b1fe7b1d8754ca7f90..ba59444be7d46703643e1e1dd565070ff5405be5 100644 --- a/config/locales/doorkeeper.th.yml +++ b/config/locales/doorkeeper.th.yml @@ -81,6 +81,7 @@ th: expired: โทเคนà¸à¸²à¸£à¹€à¸‚้าถึงหมดà¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ revoked: เพิà¸à¸–à¸à¸™à¹‚ทเคนà¸à¸²à¸£à¹€à¸‚้าถึงà¹à¸¥à¹‰à¸§ unknown: โทเคนà¸à¸²à¸£à¹€à¸‚้าถึงไม่ถูà¸à¸•้à¸à¸‡ + unsupported_response_type: เซิร์ฟเวà¸à¸£à¹Œà¸à¸²à¸£à¸à¸™à¸¸à¸à¸²à¸•ไม่รà¸à¸‡à¸£à¸±à¸šà¸Šà¸™à¸´à¸”à¸à¸²à¸£à¸•à¸à¸šà¸ªà¸™à¸à¸‡à¸™à¸µà¹‰ flash: applications: create: @@ -104,6 +105,8 @@ th: admin:read:accounts: à¸à¹ˆà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸—ี่ละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™à¸‚à¸à¸‡à¸šà¸±à¸à¸Šà¸µà¸—ั้งหมด admin:read:reports: à¸à¹ˆà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸—ี่ละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™à¸‚à¸à¸‡à¸£à¸²à¸¢à¸‡à¸²à¸™à¹à¸¥à¸°à¸šà¸±à¸à¸Šà¸µà¸—ี่ได้รับà¸à¸²à¸£à¸£à¸²à¸¢à¸‡à¸²à¸™à¸—ั้งหมด admin:write: ปรับเปลี่ยนข้à¸à¸¡à¸¹à¸¥à¸—ั้งหมดในเซิร์ฟเวà¸à¸£à¹Œ + admin:write:accounts: ทำà¸à¸²à¸£à¸à¸£à¸°à¸—ำà¸à¸²à¸£à¸„วบคุมบัà¸à¸Šà¸µ + admin:write:reports: ทำà¸à¸²à¸£à¸à¸£à¸°à¸—ำà¸à¸²à¸£à¸„วบคุมรายงาน follow: ปรับเปลี่ยนความสัมพันธ์ขà¸à¸‡à¸šà¸±à¸à¸Šà¸µ push: รับà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¹à¸šà¸šà¸œà¸¥à¸±à¸à¸‚à¸à¸‡à¸„ุณ read: à¸à¹ˆà¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸šà¸±à¸à¸Šà¸µà¸—ั้งหมดขà¸à¸‡à¸„ุณ diff --git a/config/locales/doorkeeper.tr.yml b/config/locales/doorkeeper.tr.yml index a218e315759437aa89a435779d016246ea0fb8f4..45a5821e47db518aa39c26fde5df9edfe3a1ca42 100644 --- a/config/locales/doorkeeper.tr.yml +++ b/config/locales/doorkeeper.tr.yml @@ -4,7 +4,7 @@ tr: attributes: doorkeeper/application: name: Uygulama adı - redirect_uri: Yönlendirme URI'si + redirect_uri: Yönlendirme URL'si scopes: Kapsamlar website: Uygulama web sitesi errors: @@ -13,15 +13,15 @@ tr: attributes: redirect_uri: fragment_present: parça içeremez. - invalid_uri: geçerli bir URI olmalıdır. - relative_uri: mutlak bir URI olmalıdır. - secured_uri: HTTPS/SSL URI olması gerekir. + invalid_uri: geçerli bir URL olmalıdır. + relative_uri: mutlaka bir URL olmalıdır. + secured_uri: HTTPS/SSL URL olması gerekir. doorkeeper: applications: buttons: - authorize: Yetki ver - cancel: İptal et - destroy: Yok et + authorize: İzin Ver + cancel: İptal Et + destroy: Yok Et edit: Düzenle submit: Gönder confirmations: @@ -29,14 +29,14 @@ tr: edit: title: Uygulamayı düzenle form: - error: Tüh! Muhtemel hatalar için formunuzu kontrol edin + error: Hata! Olası hatalar için formunuzu kontrol edin help: native_redirect_uri: Yerel testler için %{native_redirect_uri} kullanın - redirect_uri: URl başına bir satır kullanın + redirect_uri: URL başına bir satır kullanın scopes: Kapsamları boÅŸluklarla ayırın. Varsayılan kapsamları kullanmak için boÅŸ bırakın. index: application: Uygulama - callback_url: Geri Dönüş URL + callback_url: Callback URL delete: Sil empty: Hiç uygulamanız yok. name: İsim @@ -48,26 +48,26 @@ tr: title: Yeni uygulama show: actions: Eylemler - application_id: İstemci anahtarı - callback_urls: Callback URL'si + application_id: Client key + callback_urls: Callback URL scopes: Kapsamlar - secret: İstemci anahtarı + secret: Client secret title: 'Uygulama: %{name}' authorizations: buttons: - authorize: Yetkilendir + authorize: İzin Ver deny: Reddet error: title: Bir hata oluÅŸtu new: - able_to: Åžunları yapabilecek + able_to: 'Åžunları yapabilecek:' prompt: "%{client_name} uygulaması hesabınıza eriÅŸim istiyor" - title: Yetkilendirme gerekli + title: İzin gerekli show: - title: Bu yetki kodunu kopyalayın ve uygulamaya yapıştırın. + title: Bu yetkilendirme kodunu kopyalayın ve uygulamaya yapıştırın. authorized_applications: buttons: - revoke: İptal + revoke: İptal Et confirmations: revoke: Emin misiniz? index: @@ -79,19 +79,19 @@ tr: errors: messages: access_denied: Kaynak sahibi veya yetkilendirme sunucusu isteÄŸi reddetti. - credential_flow_not_configured: Kaynak Sahibi Åžifresinin Bilgi akışı Doorkeeper.configure.resource_owner_from_credentials bilgilerinin yapılandırılmamış olması nedeniyle baÅŸarısız oldu. + credential_flow_not_configured: Kaynak Sahibi Åžifresi Kimlik Bilgileri akışı Doorkeeper.configure.resource_owner_from_credentials 'ın yapılandırılmamış olması nedeniyle baÅŸarısız oldu. invalid_client: İstemcinin kimlik doÄŸrulaması bilinmeyen istemci, istemci kimlik doÄŸrulamasının dahil olmaması veya desteklenmeyen kimlik doÄŸrulama yöntemi nedeniyle baÅŸarısız oldu. - invalid_grant: SaÄŸlanan yetkilendirme izni geçersiz, süresi dolmuÅŸ, iptal edilmiÅŸ, yetkilendirme isteÄŸinde kullanılan yönlendirme URI'siyle eÅŸleÅŸmiyor veya baÅŸka bir müşteriye verilmiÅŸ. - invalid_redirect_uri: Dahil edilmiÅŸ yönlendirme Uri'si geçersiz. + invalid_grant: SaÄŸlanan yetkilendirme izni geçersiz, süresi dolmuÅŸ, iptal edilmiÅŸ, yetkilendirme isteÄŸinde kullanılan yönlendirme URL'siyle eÅŸleÅŸmiyor veya baÅŸka bir istemciye verilmiÅŸ. + invalid_redirect_uri: Dahil edilmiÅŸ yönlendirme URL'si geçersiz. invalid_request: İstekte gerekli bir parametre eksik, desteklenmeyen bir parametre deÄŸeri içeriyor veya baÅŸka türlü hatalı biçimlendirilmiÅŸ. invalid_resource_owner: SaÄŸlanan kaynak sahibi kimlik bilgileri geçerli deÄŸil veya kaynak sahibi bulunamıyor invalid_scope: İstenen kapsam geçersiz, bilinmeyen veya hatalı biçimlendirilmiÅŸ olabilir. invalid_token: - expired: EriÅŸim belirtecinin süresi dolmuÅŸ + expired: EriÅŸim belirtecinin süresi doldu revoked: EriÅŸim belirteci iptal edildi unknown: EriÅŸim belirteci geçersiz resource_owner_authenticator_not_configured: Kaynak Sahibi yapılandırılmamış Doorkeeper.configure.resource_owner_authenticator nedeniyle baÅŸarısız oldu. - server_error: Yetkilendirme sunucusu, isteÄŸi yerine getirmesini engelleyen beklenmeyen bir koÅŸulla karşılaÅŸtı. + server_error: Yetkilendirme sunucunun isteÄŸi yerine getirmesini engelleyen beklenmeyen bir koÅŸulla karşılaÅŸtı. temporarily_unavailable: Yetkilendirme sunucusu ÅŸu anda sunucunun geçici bir aşırı yüklenmesi veya bakımı nedeniyle isteÄŸi yerine getiremiyor. unauthorized_client: İstemci bu yöntemi kullanarak bu isteÄŸi gerçekleÅŸtirmek için yetkili deÄŸil. unsupported_grant_type: Yetkilendirme izni türü, yetkilendirme sunucusu tarafından desteklenmiyor. @@ -115,37 +115,37 @@ tr: application: title: OAuth yetkilendirme gerekli scopes: - admin:read: sunucudaki tüm verileri oku - admin:read:accounts: tüm hesapların hassas bilgilerini oku - admin:read:reports: tüm raporların ve raporlanan hesapların hassas bilgilerini oku + admin:read: sunucudaki tüm verileri okuma + admin:read:accounts: tüm hesapların hassas bilgilerini okuma + admin:read:reports: tüm raporların ve raporlanan hesapların hassas bilgilerini okuma admin:write: sunucudaki tüm verileri deÄŸiÅŸtirin - admin:write:accounts: hesaplar üzerinde denetleme eylemleri gerçekleÅŸtirin - admin:write:reports: raporlar üzerinde denetleme eylemleri gerçekleÅŸtirin + admin:write:accounts: hesaplarda denetleme eylemleri gerçekleÅŸtirin + admin:write:reports: raporlarda denetleme eylemleri gerçekleÅŸtirin follow: hesap iliÅŸkilerini deÄŸiÅŸtirin push: anlık bildirimlerizi alın read: hesabınızın tüm verilerini okuyun - read:accounts: hesap bilgilerini gör + read:accounts: hesap bilgilerini görün read:blocks: engellemelerinizi görün read:bookmarks: yer imlerinizi görün - read:favourites: favorilerini gör + read:favourites: beÄŸenilerinizi görün read:filters: filtrelerinizi görün - read:follows: izlerini gör + read:follows: takip ettiklerinizi görün read:lists: listelerinizi görün read:mutes: sessize aldıklarınızı görün read:notifications: bildirimlerinizi görün - read:reports: ÅŸikayetlerinizi görün - read:search: kendi adınıza arayın + read:reports: raporlarınızı görün + read:search: kendi adınıza arama yapın read:statuses: tüm durumları görün write: hesabınızın tüm verilerini deÄŸiÅŸtirin - write:accounts: profilini deÄŸiÅŸtir + write:accounts: profilinizi deÄŸiÅŸtirin write:blocks: hesapları ve alan adlarını engelleyin - write:bookmarks: durumları yer imlerine ekle - write:favourites: favori durumlar - write:filters: filtre oluÅŸtur - write:follows: insanları takip et - write:lists: liste oluÅŸtur - write:media: medya dosyalarını yükle - write:mutes: insanları ve konuÅŸmaları sustur + write:bookmarks: durumları yer imleyin + write:favourites: durumları beÄŸenin + write:filters: filtreler oluÅŸturun + write:follows: insanları takip edin + write:lists: listeler oluÅŸturun + write:media: medya dosyaları yükleyin + write:mutes: insanları ve sohbetleri sessize al write:notifications: bildirimlerinizi temizleyin - write:reports: diÄŸer insanları bildir + write:reports: diÄŸer insanları raporlayın write:statuses: durumları yayınlayın diff --git a/config/locales/doorkeeper.tt.yml b/config/locales/doorkeeper.tt.yml new file mode 100644 index 0000000000000000000000000000000000000000..5eab4abff95e2119202e91e8d75bd785c9ccbdc9 --- /dev/null +++ b/config/locales/doorkeeper.tt.yml @@ -0,0 +1 @@ +tt: diff --git a/config/locales/doorkeeper.vi.yml b/config/locales/doorkeeper.vi.yml index 12592c0f46f95c4883f85f202b278a200cdb450b..a51891fd01ea2bcd1a97a66e2b7ca1096b332a0b 100644 --- a/config/locales/doorkeeper.vi.yml +++ b/config/locales/doorkeeper.vi.yml @@ -4,8 +4,8 @@ vi: attributes: doorkeeper/application: name: Tên ứng dụng - redirect_uri: Chuyển hướng URI - scopes: Phạm vi + redirect_uri: URL chuyển hướng + scopes: Quyá»n hạn website: Trang web ứng dụng errors: models: @@ -15,7 +15,7 @@ vi: fragment_present: không thể chứa má»™t mảnh. invalid_uri: phải là má»™t URI hợp lệ. relative_uri: phải là má»™t URI tuyệt đối. - secured_uri: phải sá» dụng giao thức HTTPS / SSL. + secured_uri: phải là giao thức HTTPS/SSL. doorkeeper: applications: buttons: @@ -31,9 +31,9 @@ vi: form: error: Rất tiếc! Hãy kiểm tra thông tin cá»§a bạn bởi vì nó có lá»—i help: - native_redirect_uri: Sá» dụng %{native_redirect_uri} khi kiểm tra ná»™i bá»™ - redirect_uri: Sá» dụng má»™t dòng trên má»—i URI - scopes: Phạm vi riêng biệt vá»›i không gian. Äể trống để sá» dụng phạm vi mặc định. + native_redirect_uri: Dùng %{native_redirect_uri} khi kiểm tra ná»™i bá»™ + redirect_uri: Má»—i dòng chỉ má»™t URL + scopes: Tách phạm vi ra bằng dấu cách. Bá» trống để dùng phạm vi mặc định. index: application: Ứng dụng callback_url: Gá»i lại URL @@ -41,7 +41,7 @@ vi: empty: Bạn không có ứng dụng nà o. name: Tên new: Ứng dụng má»›i - scopes: Phạm vi + scopes: Quyá»n hạn show: Xem title: Ứng dụng cá»§a bạn new: @@ -50,7 +50,7 @@ vi: actions: Hà nh động application_id: Mã Client callback_urls: Gá»i lại URLs - scopes: Phạm vi + scopes: Quyá»n hạn secret: Bà ẩn cá»§a Client title: 'Ứng dụng: %{name}' authorizations: @@ -67,28 +67,28 @@ vi: title: Sao chép mã nà y và dán nó và o ứng dụng. authorized_applications: buttons: - revoke: Thu hồi + revoke: Gỡ confirmations: revoke: Bạn có chắc không? index: application: Ứng dụng created_at: Äã cho phép date_format: "%Y-%m-%d %H:%M:%S" - scopes: Phạm vi + scopes: Quyá»n hạn title: Các ứng dụng mà bạn cho phép errors: messages: access_denied: Chá»§ sở hữu tà i nguyên hoặc máy chá»§ đã từ chối yêu cầu. credential_flow_not_configured: Resource Owner Password Credentials không thà nh công do Doorkeeper.configure.resource_owner_from_credentials không được định cấu hình. invalid_client: Xác thá»±c ứng dụng khách không thà nh công do máy khách mÆ¡ hồ, không bao gồm xác thá»±c ứng dụng khách hoặc phương thức xác thá»±c không được há»— trợ. - invalid_grant: Yêu cầu không hợp lệ, hết hạn, bị thu hồi hoặc không khá»›p vá»›i tà i khoản đã cung cấp. - invalid_redirect_uri: Uri chuyển hướng bao gồm không hợp lệ. + invalid_grant: Yêu cầu không hợp lệ, hết hạn, bị gỡ hoặc không khá»›p vá»›i tà i khoản đã cấp phép. Hoặc xung đột vá»›i ứng dụng khác. + invalid_redirect_uri: URL chuyển hướng không hợp lệ. invalid_request: Yêu cầu thiếu tham số bắt buá»™c, bao gồm giá trị tham số không được há»— trợ hoặc không đúng định dạng. invalid_resource_owner: Thông tin xác thá»±c chá»§ sở hữu tà i nguyên được cung cấp không hợp lệ hoặc không thể tìm thấy chá»§ sở hữu tà i nguyên - invalid_scope: Phạm vi yêu cầu không hợp lệ, không xác định hoặc không đúng định dạng. + invalid_scope: Quyá»n yêu cầu không hợp lệ, không có tháºt hoặc sai định dạng. invalid_token: expired: Mã thông báo truy cáºp đã hết hạn - revoked: Mã thông báo truy cáºp đã bị thu hồi + revoked: Mã token đăng nháºp đã bị há»§y unknown: Mã thông báo truy cáºp không hợp lệ resource_owner_authenticator_not_configured: Chá»§ sở hữu tà i nguyên tìm thấy thất bại do Doorkeeper.configure.resource_owner_authenticator không được định cấu hình. server_error: Có má»™t Ä‘iá»u kiện không thể chấp nháºn khiến máy chá»§ không thá»±c hiện yêu cầu. @@ -106,7 +106,7 @@ vi: notice: Ứng dụng cáºp nháºt. authorized_applications: destroy: - notice: Ứng dụng bị thu hồi. + notice: Ứng dụng bị gỡ. layouts: admin: nav: @@ -117,35 +117,35 @@ vi: scopes: admin:read: Ä‘á»c tất cả dữ liệu trên máy chá»§ admin:read:accounts: Ä‘á»c thông tin nhạy cảm cá»§a tất cả các tà i khoản - admin:read:reports: Ä‘á»c thông tin nhạy cảm cá»§a tất cả các báo cáo và tà i khoản báo cáo + admin:read:reports: Ä‘á»c thông tin cá»§a các báo cáo và các tà i khoản bị báo cáo admin:write: sá»a đổi tất cả dữ liệu trên máy chá»§ - admin:write:accounts: thá»±c hiện các hà nh động kiểm duyệt trên tà i khoản - admin:write:reports: thá»±c hiện các hà nh động kiểm duyệt trên các báo cáo + admin:write:accounts: áp đặt hà nh động kiểm duyệt trên tà i khoản + admin:write:reports: áp đặt kiểm duyệt vá»›i các báo cáo follow: sá»a đổi các mối quan hệ tà i khoản push: nháºn thông báo đẩy cá»§a bạn read: Ä‘á»c tất cả dữ liệu tà i khoản cá»§a bạn read:accounts: xem thông tin tà i khoản - read:blocks: xem khối cá»§a bạn - read:bookmarks: xem các mục đã lưu - read:favourites: xem yêu thÃch cá»§a bạn + read:blocks: xem những ngưá»i bạn chặn + read:bookmarks: xem những thứ bạn đã lưu + read:favourites: xem lượt thÃch read:filters: xem bá»™ lá»c cá»§a bạn - read:follows: xem sau cá»§a bạn + read:follows: xem lượt theo dõi cá»§a bạn read:lists: xem danh sách cá»§a bạn - read:mutes: xem những ngưá»i bạn cá»§a bạn + read:mutes: xem những ngưá»i bạn đã ẩn read:notifications: xem thông báo cá»§a bạn read:reports: xem báo cáo cá»§a bạn read:search: thay mặt bạn tìm kiếm - read:statuses: xem tất cả các trạng thái - write: sá»a đổi tất cả dữ liệu tà i khoản cá»§a bạn - write:accounts: sá»a đổi hồ sÆ¡ cá»§a bạn - write:blocks: chặn tà i khoản và tên miá»n - write:bookmarks: những trạng thái đã lưu - write:favourites: trạng thái yêu thÃch + read:statuses: xem toà n bá»™ tút + write: sá»a đổi má»i dữ liệu tà i khoản cá»§a bạn + write:accounts: sá»a đổi trang cá nhân cá»§a bạn + write:blocks: chặn ngưá»i dùng và máy chá»§ + write:bookmarks: sá»a đổi những thứ bạn lưu + write:favourites: lượt thÃch write:filters: tạo bá»™ lá»c - write:follows: theo dõi má»i ngưá»i + write:follows: theo dõi ai đó write:lists: tạo danh sách - write:media: tải lên táºp tin phương tiện truyá»n thông - write:mutes: ngưá»i câm và nói chuyện + write:media: tải lên táºp tin + write:mutes: ẩn ngưá»i dùng và cuá»™c đối thoại write:notifications: xóa thông báo cá»§a bạn write:reports: báo cáo ngưá»i khác - write:statuses: xuất bản trạng thái + write:statuses: đăng tút diff --git a/config/locales/doorkeeper.zgh.yml b/config/locales/doorkeeper.zgh.yml new file mode 100644 index 0000000000000000000000000000000000000000..d34b8109cf1b54c850d176bd882d0aedddffb2a1 --- /dev/null +++ b/config/locales/doorkeeper.zgh.yml @@ -0,0 +1,80 @@ +--- +zgh: + activerecord: + attributes: + doorkeeper/application: + name: ⵉⵙⵠⵠⵜⵙâµâµ™âµ‰ + redirect_uri: ⵜⴰâµâµ™â´° ⵠⵓⵙⵉⴼⴹ + website: ⴰⵙⵉⵜ ⵡⵉⴱ ⵠⵜⵙâµâµ™âµ‰ + doorkeeper: + applications: + buttons: + authorize: ⵙⵙⵓⵔⴳ + cancel: ⵙⵔ + edit: âµ™âµâ´¼âµ + submit: ⴰⵣⵠ+ confirmations: + destroy: ⵉⵙ âµâµ‰âµœ? + edit: + title: âµ™âµâ´¼âµ ⵜⵉⵙâµâµ™âµ‰ + help: + native_redirect_uri: ⵙⵎⵔⵙ %{native_redirect_uri} ⵉ ⵉⵔⵉⵎⵠⵉⴷⵖⴰⵔⴰⵜⵠ+ redirect_uri: ⵙⵎⵔⵙ ⵢⴰⵠⵓⵣⴳⵉⴳ ⵉ ⵢⴰⵜ ⵜⵖⵓâµâµ‰ + index: + application: ⵜⵉⵙâµâµ™âµ‰ + delete: ⴽⴽⵙ + empty: ⵓⵔ ⵖⵓⵔⴽ ⴽⵔⴰ ⵠⵜⵙâµâµ™âµ‰âµ¡âµ‰âµ. + name: ⵉⵙⵎ + new: ⵜⵉⵙâµâµ™âµ‰ ⵜⴰⵎⴰⵢâµâµ“ⵜ + show: ⵙⵎⴰⵠ+ title: ⵜⵉⵙâµâµ™âµ‰âµ¡âµ‰âµ âµâµâ´½ + new: + title: ⵜⵉⵙâµâµ™âµ‰ ⵜⴰⵎⴰⵢâµâµ“ⵜ + show: + actions: ⵜⵉⴳⴰⵡⵉⵠ+ title: ⵜⵉⵙâµâµ™âµ‰ %{name} + authorizations: + buttons: + authorize: ⵙⵙⵓⵔⴳ + deny: ⴰⴳⵢ + new: + prompt: ⵜⵙⵙⵓⵜⵓⵔ ⵜⵙâµâµ™âµ‰ %{client_name} ⴰⵙⴰⴷⴼ âµ–âµ” ⵓⵎⵉⴹⴰⵠâµâµâ´½ + authorized_applications: + confirmations: + revoke: ⵉⵙ âµâµ‰âµœ? + index: + application: ⵜⵉⵙâµâµ™âµ‰ + created_at: ⵜⴻⵜⵜⵓⵙⵓⵔⴳ + date_format: "%d-%m-%Y %H:%M:%S" + title: ⵜⵉⵙâµâµ™âµ‰âµ¡âµ‰âµ âµâµâ´½ ⵉⵜⵜⵓⵙⵓⵔⴷⵠ+ flash: + applications: + create: + notice: ⵜⴻⵜⵜⵓⵙâµâ´¼âµâµ“ⵠⵜⵙâµâµ™âµ‰. + destroy: + notice: ⵜⴻⵜⵜⵡⴰⴽⴽⵙ ⵜⵙâµâµ™âµ‰. + update: + notice: ⵜⴻⵜⵜⵓⵙⴷⵖⵉ ⵜⵙâµâµ™âµ‰. + layouts: + admin: + nav: + applications: ⵜⵉⵙâµâµ™âµ‰âµ¡âµ‰âµ + scopes: + admin:read: âµ–âµ” ⵉⴼⵙⴽⴰ ⴰⴽⴽⵯ â´³ ⵓⵎⴰⴽⴽⴰⵢ + admin:write: âµ™âµâ´¼âµ ⵉⴼⵙⴽⴰ ⴰⴽⴽⵯ â´³ ⵓⵎⴰⴽⴽⴰⵢ + read: âµ–âµ” ⵉⴼⵙⴽⴰ ⴰⴽⴽⵯ ⵠⵓⵎⵉⴹⴰⵠ+ read:filters: ⵥⵕ ⵉⵙⵜⴰⵢⵠâµâµâ´½ + read:follows: ⵥⵕ ⵉⵎⴹⴼⴰⵔⵠâµâµâ´½ + read:lists: ⵥⵕ ⵜⵉâµâ´³â´°âµŽâµ‰âµ âµâµâ´½ + read:notifications: ⵥⵕ ⵜⵉâµâµ–ⵎⵉⵙⵉⵠâµâµâ´½ + read:search: ⵔⵣⵓ âµ™ ⵢⵉⵙⵎ âµâµâ´½ + read:statuses: ⵥⵕ ⴰⴷⴷⴰⴷⵠⴰⴽⴽⵯ + write: âµ™âµâ´¼âµ ⵉⴼⵙⴽⴰ ⵠⵓⵎⵉⴹⴰⵠâµâµâ´½ + write:accounts: âµ™âµâ´¼âµ ⵉⴼⵔⵙ âµâµâ´½ + write:blocks: ⴳⴷⵠⵉⵎⵉⴹⴰâµâµ â´· ⵢⵉⴳⵔⴰⵠ+ write:follows: ⴹⴼⵕ ⵎⵉⴷⴷⵠ+ write:lists: âµ™âµâ´¼âµâµ“ⵠⵜⵉâµâ´³â´°âµŽâµ‰âµ + write:mutes: ⵥⵥⵉⵥⵠⵎⵉⴷⴷⵠⴷ ⵉⵎⵙⴰⵡⴰâµâµ + write:notifications: ⵙⴼⴹ ⵜⵉâµâµ–ⵎⵉⵙⵉⵠâµâµâ´½ + write:reports: ⵎⵠⵎⵉⴷⴷⵠâµâµâµ‰â´¹âµ + write:statuses: ⴼⵙⵔ ⵜⵉⵥⵕⴰⴳⵉⵠdiff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml index d59c859a31e5145da67ba005122c871bb28e6cd1..3e0d88c82dffe7076e627587881f5a0e2e2857d0 100644 --- a/config/locales/doorkeeper.zh-CN.yml +++ b/config/locales/doorkeeper.zh-CN.yml @@ -33,7 +33,7 @@ zh-CN: help: native_redirect_uri: 本地测试请使用 %{native_redirect_uri} redirect_uri: æ¯è¡Œåªèƒ½æœ‰ä¸€ä¸ª URL - scopes: ç”¨ç©ºæ ¼åˆ†å‰²æƒé™èŒƒå›´ï¼Œç•™ç©ºåˆ™ä½¿ç”¨é»˜è®¤è®¾ç½® + scopes: ç”¨ç©ºæ ¼åˆ†éš”æƒé™èŒƒå›´ï¼Œç•™ç©ºåˆ™ä½¿ç”¨é»˜è®¤è®¾ç½®ã€‚ index: application: 应用 callback_url: 回调 URL @@ -73,7 +73,7 @@ zh-CN: index: application: 应用 created_at: æŽˆæƒæ—¶é—´ - date_format: "%Yå¹´%m月%dæ—¥ %Hæ—¶%M分%Sç§’" + date_format: "%Yå¹´%m月%dæ—¥ %H:%M:%S" scopes: æƒé™èŒƒå›´ title: 已授æƒçš„应用列表 errors: diff --git a/config/locales/doorkeeper.zh-HK.yml b/config/locales/doorkeeper.zh-HK.yml index 38f07b0219fc8f67fb6adad6cd50b05a2bff6029..872727049b24642c7e78c85ce9b2e9b9de9bc866 100644 --- a/config/locales/doorkeeper.zh-HK.yml +++ b/config/locales/doorkeeper.zh-HK.yml @@ -3,8 +3,8 @@ zh-HK: activerecord: attributes: doorkeeper/application: - name: å稱 - redirect_uri: 轉接 URI + name: 應用程å¼å稱 + redirect_uri: 釿–°å°Žå‘ URI scopes: 權é™ç¯„åœ website: 應用網站 errors: @@ -12,10 +12,10 @@ zh-HK: doorkeeper/application: attributes: redirect_uri: - fragment_present: URI ä¸å¯åŒ…å« "#fragment" 部份。 - invalid_uri: 必需有æ£ç¢ºçš„ URI。 - relative_uri: 必需為完整 URI。 - secured_uri: 必需使用有 HTTPS/SSL åŠ å¯†çš„ URI。 + fragment_present: ä¸èƒ½åŒ…å« fragment。 + invalid_uri: 必需是一個有效的 URI。 + relative_uri: å¿…é ˆç‚ºçµ•å° URI。 + secured_uri: å¿…é ˆç‚º HTTPS/SSL åŠ å¯†çš„ URI。 doorkeeper: applications: buttons: @@ -32,26 +32,26 @@ zh-HK: error: 噢ï¼è«‹æª¢æŸ¥ä½ è¡¨æ ¼çš„éŒ¯èª¤è¨Šæ¯ help: native_redirect_uri: 使用 %{native_redirect_uri} 作局部測試 - redirect_uri: æ¯è¡Œè¼¸å…¥ä¸€å€‹ URI + redirect_uri: 一行一個 URI scopes: 請用åŠå½¢ç©ºæ ¼åˆ†é–‹æ¬Šé™ç¯„åœ (scope)。留空表示使用é è¨çš„æ¬Šé™ç¯„åœã€‚ index: - application: 應用 - callback_url: å›žå‚³ç¶²å€ + application: æ‡‰ç”¨ç¨‹å¼ + callback_url: å›žå‚³ç¶²å€ (Callback URL) delete: 刪除 - empty: æ‚¨æ²’æœ‰å®‰è£ App。 + empty: ä½ æ²’æœ‰æ‡‰ç”¨ç¨‹å¼ name: å稱 new: æ–°å¢žæ‡‰ç”¨ç¨‹å¼ - scopes: 權é™ç¯„åœ + scopes: 權é™ç¯„åœ (Scopes) show: 顯示 title: ä½ çš„æ‡‰ç”¨ç¨‹å¼ new: title: æ–°å¢žæ‡‰ç”¨ç¨‹å¼ show: actions: æ“作 - application_id: æ‡‰ç”¨ç¨‹å¼ ID - callback_urls: å›žå‚³ç¶²å€ - scopes: 權é™ç¯„åœ - secret: 密碼 + application_id: 用戶程å¼é‘°åŒ™ (Client key) + callback_urls: å›žå‚³ç¶²å€ (Callback URL) + scopes: 權é™ç¯„åœ (Scopes) + secret: 用戶程å¼å¯†ç¢¼ (Client secret) title: 應用程å¼ï¸° %{name} authorizations: buttons: @@ -60,7 +60,7 @@ zh-HK: error: title: 發生錯誤 new: - able_to: è¦æ±‚ç²å–æ¬Šé™ + able_to: 它將å¯ä»¥ prompt: æ‡‰ç”¨ç¨‹å¼ %{client_name} è¦æ±‚å¾—åˆ°ä½ ç”¨æˆ¶çš„éƒ¨ä»½æ¬Šé™ title: 需è¦ç”¨æˆ¶æŽˆæ¬Š show: @@ -73,27 +73,27 @@ zh-HK: index: application: æ‡‰ç”¨ç¨‹å¼ created_at: 授權日期 - date_format: "%Y-%m-%d %H:%M:%S" - scopes: 權é™ç¯„åœ + date_format: "%Yå¹´%m月%dæ—¥ %H:%M:%S" + scopes: 權é™ç¯„åœ (Scopes) title: å·²ç²ä½ æŽˆæ¬Šçš„ç¨‹ç”¨ç¨‹å¼ errors: messages: access_denied: è³‡æºæ“有者或授權伺æœå™¨ä¸æŽ¥å—請求。 credential_flow_not_configured: è³‡æºæ“有者密碼èªè‰ç¨‹åº (Resource Owner Password Credentials flow) å¤±æ•—ï¼ŒåŽŸå› æ˜¯ Doorkeeper.configure.resource_owner_from_credentials 沒有è¨å®šã€‚ - invalid_client: 用戶程å¼èªè‰ (Client authentication) å¤±æ•—ï¼ŒåŽŸå› æ˜¯ç”¨æˆ¶ç¨‹å¼æœªæœ‰ç™»è¨˜ã€æ²’æœ‰æŒ‡å®šç”¨æˆ¶ç¨‹å¼ (client)ã€æˆ–è€…ä½¿ç”¨äº†ä¸æ”¯æ´çš„èªè‰æ–¹æ³• (method)。 - invalid_grant: 授權申請 (authorization grant) 䏿£ç¢ºã€éŽæœŸã€å·²è¢«å–æ¶ˆï¼Œæˆ–è€…ç„¡æ³•å°æ‡‰æŽˆæ¬Šè«‹æ±‚ (authorization request) 內的轉接 URI,或者屬於別的用戶程å¼ã€‚ + invalid_client: 用戶程å¼èªè‰ (Client Authentication) å¤±æ•—ï¼ŒåŽŸå› æ˜¯ä½¿ç”¨äº†æœªçŸ¥çš„ç”¨æˆ¶ç¨‹å¼ã€æ²’有傳回用戶èªè‰è³‡è¨Šã€æˆ–è€…ä½¿ç”¨äº†ä¸æ”¯æ´çš„èªè‰æ–¹æ³• (Authentication Method)。 + invalid_grant: 所æä¾›çš„èªè‰ç”³è«‹ (authorization grant) 䏿£ç¢ºã€éŽæœŸã€å·²è¢«å–æ¶ˆã€æˆ–è€…ç„¡æ³•å°æ‡‰æŽˆæ¬Šè«‹æ±‚ (authorization request) 內的轉接 URI,或者屬於別的用戶程å¼ã€‚ invalid_redirect_uri: 䏿£ç¢ºçš„轉接網å€ã€‚ - invalid_request: 請求缺少了必è¦çš„åƒæ•¸ã€åŒ…å«äº†ä¸æ”¯æ´çš„åƒæ•¸ã€æˆ–者其他輸入錯誤。 - invalid_resource_owner: è³‡æºæ“æœ‰è€…çš„ç™»å…¥è³‡è¨ŠéŒ¯èª¤ã€æˆ–è€…ç„¡æ³•æ‰¾åˆ°è©²è³‡æºæ“有者 - invalid_scope: 請求的權é™ç¯„åœ (scope) 䏿£ç¢ºã€æœªæœ‰å®šç¾©ã€æˆ–者輸入錯誤。 + invalid_request: 請求缺少必è¦çš„åƒæ•¸ã€æœ‰ä¸æ”¯æ´çš„åƒæ•¸ã€æˆ–包å«å…¶ä»–æ ¼å¼éŒ¯èª¤ã€‚ + invalid_resource_owner: è³‡æºæ“æœ‰è€…çš„ç™»å…¥è³‡è¨Šç„¡æ•ˆã€æˆ–è€…ç„¡æ³•æ‰¾åˆ°è©²è³‡æºæ“有者 + invalid_scope: ä½ æ‰€è«‹æ±‚çš„æ¬Šé™ç¯„åœ (scope) ç„¡æ•ˆã€æœªçŸ¥ã€æˆ–æ ¼å¼éŒ¯èª¤ã€‚ invalid_token: - expired: access token å·²ç¶“éŽæœŸ - revoked: access token å·²è¢«å–æ¶ˆ - unknown: access token 䏿£ç¢º + expired: å˜å–æ†‘è‰ (access token) å·²éŽæœŸ + revoked: å˜å–æ†‘è‰ (access token) 已被撤銷 + unknown: å˜å–æ†‘è‰ (access token) 無效 resource_owner_authenticator_not_configured: ç„¡æ³•æ‰¾åˆ°è³‡æºæ“æœ‰è€…ï¼ŒåŽŸå› æ˜¯ Doorkeeper.configure.resource_owner_authenticator 沒有è¨å®šã€‚ - server_error: èªè‰ä¼ºæœå™¨é‡ä¸ŠæœªçŸ¥ç‹€æ³ï¼Œä»¤è«‹æ±‚無法通éŽã€‚ + server_error: èªè‰ä¼ºæœå™¨é‡ä¸ŠæœªçŸ¥ç‹€æ³ï¼Œä»¤è«‹æ±‚無法被æ£ç¢ºè™•ç†ã€‚ temporarily_unavailable: èªè‰ä¼ºæœå™¨ç”±æ–¼è‡¨æ™‚è² è·éŽé‡æˆ–者ç¶è·ï¼Œç›®å‰æœªèƒ½è™•ç†è«‹æ±‚。 - unauthorized_client: 用戶程å¼ç„¡æ¬Šç”¨æ¤æ–¹æ³• (method) 請行這個請求。 + unauthorized_client: 用戶程å¼ç„¡æ¬Šä½¿ç”¨æ‰€é¸çš„æ–¹æ³• (method) 進行這個請求。 unsupported_grant_type: 授權伺æœå™¨ä¸æ”¯æ´é€™å€‹æŽˆæ¬Šé¡žåž‹ (grant type)。 unsupported_response_type: 授權伺æœå™¨ä¸æ”¯æ´é€™å€‹å›žæ‡‰é¡žåž‹ (response type)。 flash: @@ -119,33 +119,33 @@ zh-HK: admin:read:accounts: è®€å–æ‰€æœ‰å¸³æˆ¶çš„æ•æ„Ÿè³‡è¨Š admin:read:reports: è®€å–æ‰€æœ‰å›žå ± / è¢«å›žå ±ä¹‹å¸³æˆ¶çš„æ•æ„Ÿè³‡è¨Š admin:write: 修改伺æœå™¨çš„æ‰€æœ‰è³‡æ–™ - admin:write:accounts: å°å¸³æˆ¶é€²è¡Œä»²è£ç®¡ç†å‹•作 - admin:write:reports: å°å ±å‘Šé€²è¡Œä»²è£ç®¡ç†å‹•作 - follow: 關注ã€å°éŽ–ã€è§£é™¤å°éŽ–åŠå–消關注用戶 + admin:write:accounts: å°å¸³è™Ÿé€²è¡Œä»²è£ç®¡ç†å‹•作 + admin:write:reports: å°å›žå ±é€²è¡Œä»²è£ç®¡ç†å‹•作 + follow: 修改帳號的å°å¤–è¯ç¹« push: æŽ¥æ”¶ä½ çš„å¸³è™Ÿçš„æŽ¨é€é€šçŸ¥ - read: é–±è®€ä½ çš„ç”¨æˆ¶è³‡æ–™ - read:accounts: 檢視帳戶資訊 - read:blocks: 檢視您的å°éŽ–åå–® - read:bookmarks: 檢視您的書籤 - read:favourites: 檢視您的收è—é …ç›® - read:filters: æª¢è¦–æ‚¨çš„éŽæ¿¾æ¢ä»¶ - read:follows: 檢視您關注的人 - read:lists: 檢視您的åå–® - read:mutes: 檢視您éœéŸ³çš„人 - read:notifications: 檢視您的通知 - read:reports: 檢視您的檢舉 - read:search: ä»¥ä½ çš„èº«ä»½æœå°‹ - read:statuses: 檢視所有嘟文 + read: é–±è®€ä½ å¸³è™Ÿçš„æ‰€æœ‰è³‡æ–™ + read:accounts: 檢視帳號資訊 + read:blocks: æª¢è¦–ä½ çš„å°éŽ–åå–® + read:bookmarks: æª¢è¦–ä½ çš„æ›¸ç±¤ + read:favourites: æª¢è¦–ä½ æœ€æ„›çš„æ–‡ç« + read:filters: æª¢è¦–ä½ çš„éŽæ¿¾æ¢ä»¶ + read:follows: æª¢è¦–ä½ é—œæ³¨çš„äºº + read:lists: æª¢è¦–ä½ çš„æ¸…å–® + read:mutes: æª¢è¦–è¢«ä½ éœéŸ³çš„人 + read:notifications: æª¢è¦–ä½ çš„é€šçŸ¥ + read:reports: æª¢è¦–ä½ çš„æª¢èˆ‰ + read:search: ä»¥ä½ çš„èº«ä»½é€²è¡Œæœå°‹ + read:statuses: æª¢è¦–æ‰€æœ‰æ–‡ç« write: ä»¥ä½ çš„åç¾©ç™¼ä½ˆæ–‡ç« - write:accounts: 修改您的個人檔案 - write:blocks: å°éŽ–å¸³æˆ¶åŠç«™å° - write:bookmarks: 書籤狀態 - write:favourites: æ”¶è—嘟文 + write:accounts: ä¿®æ”¹ä½ çš„å€‹äººæª”æ¡ˆ + write:blocks: å°éŽ–å¸³è™ŸåŠåŸŸå + write:bookmarks: æŠŠæ–‡ç« åŠ å…¥æœ€æ„› + write:favourites: å–œæ¡çš„æ–‡ç« write:filters: å»ºç«‹éŽæ¿¾æ¢ä»¶ write:follows: 關注其他人 - write:lists: 建立åå–® + write:lists: 建立清單 write:media: 上傳媒體檔案 write:mutes: éœéŸ³ä½¿ç”¨è€…åŠå°è©± - write:notifications: 清除您的通知 + write:notifications: æ¸…é™¤ä½ çš„é€šçŸ¥ write:reports: 檢舉其他人 write:statuses: 發布嘟文 diff --git a/config/locales/el.yml b/config/locales/el.yml index cf6622f10de38b300b92a067cc42bdf9b07f5a48..5442d38b851d803f415f1244b02e3b712f4bccc9 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -98,6 +98,7 @@ el: add_email_domain_block: ΕγγÏαφή τομÎα email σε μαÏÏη λίστα approve: ΈγκÏιση approve_all: ΈγκÏιση όλων + approved_msg: Επιτυχής ÎγκÏιση αίτησης εγγÏαφής του/της %{username} are_you_sure: ΣίγουÏα; avatar: Î‘Î²Î±Ï„Î¬Ï by_domain: ΤομÎας @@ -111,8 +112,10 @@ el: confirm: Επιβεβαίωση confirmed: Επιβεβαιώθηκε confirming: Î Ïος επιβεβαίωση + delete: ΔιαγÏαφή δεδομÎνων deleted: ΔιαγÏαμμÎνοι demote: Υποβίβαση + destroyed_msg: Τα δεδομÎνα του/της %{username} εκκÏεμοÏν για άμεση διαγÏαφή disable: ΑπενεÏγοποίηση disable_two_factor_authentication: ΑπενεÏγοποίηση 2FA disabled: ΑπενεÏγοποιημÎνο @@ -123,10 +126,12 @@ el: email_status: Κατάσταση email enable: ΕνεÏγοποίηση enabled: ΕνεÏγοποιημÎνο + enabled_msg: ΕπιτυχÎÏ‚ ξεπάγωμα λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Ï„Î¿Ï…/της %{username} followers: Ακόλουθοι follows: Ακολουθεί header: Επικεφαλίδα inbox_url: URL εισεÏχομÎνων + invite_request_text: Λόγοι για εγγÏαφή invited_by: Î Ïοσκλήθηκε από ip: IP joined: ΓÏάφτηκε @@ -138,6 +143,8 @@ el: login_status: Κατάσταση σÏνδεσης media_attachments: ΣυνημμÎνα πολυμÎσα memorialize: ΜετατÏοπή σε νεκÏολογία + memorialized: ΜετατÏοπή σε αναμνηστικό + memorialized_msg: Επιτυχής μετατÏοπή λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Ï„Î¿Ï…/της %{username} σε αναμνηστικό moderation: active: ΕνεÏγός/ή all: Όλα @@ -158,10 +165,14 @@ el: public: Δημόσιο push_subscription_expires: Η εγγÏαφή PuSH λήγει redownload: ΑνανÎωση Î±Î²Î±Ï„Î¬Ï + redownloaded_msg: Επιτυχής ανανÎωη Ï€Ïοφίλ του/της %{username} από την πηγή reject: ΑπόÏÏιψη reject_all: ΑπόÏÏιψη όλων + rejected_msg: Επιτυχής απόÏÏιψη αίτησης εγγÏαφής του/της %{username} remove_avatar: ΑπομακÏυσμÎνο Î±Î²Î±Ï„Î¬Ï remove_header: ΑφαίÏεση επικεφαλίδας + removed_avatar_msg: Επιτυχής αφαίÏεση εικόνας Ï€Ïοφίλ του/της%{username} + removed_header_msg: Επιτυχής αφαίÏεση εικόνας κεφαλίδας του/της %{username} resend_confirmation: already_confirmed: Ήδη επιβεβαιωμÎνος χÏήστης send: Επανάληψη αποστολής email επιβεβαίωσης @@ -178,6 +189,8 @@ el: search: Αναζήτηση search_same_email_domain: Άλλοι χÏήστες με τον ίδιο τομÎα e-mail search_same_ip: Υπόλοιποι χÏήστες με την ίδια διεÏθυνση IP + sensitive: Ευαίσθητο + sensitized: σήμανση ως ευαίσθητο shared_inbox_url: URL κοινόχÏηστων εισεÏχομÎνων show: created_reports: ΑναφοÏÎÏ‚ από αυτόν το λογαÏιασμό @@ -187,13 +200,19 @@ el: statuses: Καταστάσεις subscribe: ΕγγÏαφή suspended: Σε αναστολή + suspension_irreversible: Τα δεδομÎνα Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Îχουν διαγÏαφεί οÏιστικά. ΜποÏείς να άÏεις την αναστολή του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î³Î¹Î± να μποÏÎσει να χÏησιμοποιηθεί αλλά αυτό δεν θα επαναφÎÏει όσα δεδομÎνα είχε Ï€ÏοηγουμÎνως. + suspension_reversible_hint_html: Ο λογαÏιασμός Îχει ανασταλλεί και τα δεδομÎνα του θα διαγÏαφοÏν πλήÏως στις %{date}. ΜÎχÏι τότε ο λογαÏιασμός μποÏεί να επανÎλθει κανονικά. Αν θÎλεις να διαγÏάψεις όλα τα δεδομÎνα του λογαÏιασμοÏ, μποÏείς να το κάνεις παÏακάτω. time_in_queue: Σε αναμονή για %{time} title: ΛογαÏιασμοί unconfirmed_email: Ανεπιβεβαίωτο email + undo_sensitized: ΑναίÏεση ευαίσθητου undo_silenced: ΑναίÏεση αποσιώπησης undo_suspension: ΑναίÏεση παÏσης + unsilenced_msg: Επιτυχής άÏση πεÏιοÏισμών λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Ï„Î¿Ï…/της %{username} unsubscribe: ΚατάÏγηση εγγÏαφής + unsuspended_msg: Επιτυχής άÏση αναστολής λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Ï„Î¿Ï…/της %{username} username: Όνομα χÏήστη + view_domain: Î Ïοβολή πεÏίληψης για τομÎα warn: Î Ïοειδοποίηση web: Διαδίκτυο whitelisted: ΕγκεκÏιμÎνοι @@ -208,12 +227,14 @@ el: create_domain_allow: ΔημιουÏγία ΕπιτÏÎµÏ€Ï„Î¿Ï Î¤Î¿Î¼Îα create_domain_block: ΔημιουÏγία ΑποκλεισμÎνου ΤομÎα create_email_domain_block: ΔημουÏγία ΑποκλεισμÎνου ΤομÎα email + create_ip_block: ΔημιουÏγία κανόνα IP demote_user: Υποβιβασμός ΧÏήστη destroy_announcement: ΔιαγÏαφή Ανακοίνωσης destroy_custom_emoji: ΔιαγÏαφή Î ÏοσαÏμοσμÎνου Emoji destroy_domain_allow: ΔιαγÏαφή ΕπιτÏÎµÏ€Ï„Î¿Ï Î¤Î¿Î¼Îα destroy_domain_block: ΔιαγÏαφή Î‘Ï€Î¿ÎºÎ»ÎµÎ¹ÏƒÎ¼Î¿Ï Î¤Î¿Î¼Îα destroy_email_domain_block: ΔιαγÏαφή ΑποκλεισμÎνου ΤομÎα email + destroy_ip_block: ΔιαγÏαφή κανόνα IP destroy_status: ΔιαγÏαφή Κατάστασης disable_2fa_user: ΑπενεÏγοποίηση 2FA disable_custom_emoji: ΑπενεÏγοποίηση Î ÏοσαÏμοσμÎνων Emoji @@ -226,9 +247,11 @@ el: reopen_report: Ξανάνοιγμα Καταγγελίας reset_password_user: ΕπαναφοÏά Î£Ï…Î½Î¸Î·Î¼Î±Ï„Î¹ÎºÎ¿Ï resolve_report: Επίλυση Καταγγελίας + sensitive_account: Σήμανση των πολυμÎσων στον λογαÏιασμό σας ως ευαίσθητων silence_account: Σίγαση ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï suspend_account: Αναστολή ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï unassigned_report: ΑποδÎσμευση Καταγγελίας + unsensitive_account: ΑφαίÏεση σήμανσης των πολυμÎσων στον λογαÏιασμό σας ως ευαίσθητων unsilence_account: ΆÏση Σίγασης ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï unsuspend_account: ΆÏση Αναστολής ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï update_announcement: ΕνημÎÏωση Ανακοίνωσης @@ -244,12 +267,14 @@ el: create_domain_allow: Ο/Η %{name} Îβαλε τον τομÎα %{target} σε λευκή λίστα create_domain_block: Ο/Η %{name} μπλόκαÏε τον τομÎα %{target} create_email_domain_block: Ο/Η %{name} Îβαλε τον τομÎα email %{target} σε μαÏÏη λίστα + create_ip_block: Ο/Η %{name} δημιοÏÏγησε κανόνα για την IP %{target} demote_user: Ο/Η %{name} υποβίβασε το χÏήστη %{target} destroy_announcement: ΔιαγÏαφή ανακοίνωσης %{target} από %{name} destroy_custom_emoji: Ο/Η %{name} κατÎστÏεψε το emoji %{target} destroy_domain_allow: Ο/Η %{name} αφαίÏεσε τον τομÎα %{target} από λίστα εγκÏίσεων destroy_domain_block: Ο/Η %{name} ξεμπλόκαÏε τον τομÎα %{target} destroy_email_domain_block: Ο/Η %{name} Îβαλε τον τομÎα email %{target} σε λευκή λίστα + destroy_ip_block: Ο/Η %{name} διÎγÏαψε κανόνα για την IP %{target} destroy_status: Ο/Η %{name} αφαίÏεσε την κατάσταση του/της %{target} disable_2fa_user: Ο/Η %{name} απενεÏγοποίησε την απαίτηση δÏο παÏαγόντων για το χÏήστη %{target} disable_custom_emoji: Ο/Η %{name} απενεÏγοποίησε το emoji %{target} @@ -434,6 +459,20 @@ el: expired: ΛηγμÎνες title: ΦίλτÏο title: Î Ïοσκλήσεις + ip_blocks: + add_new: ΔημιουÏγία κανόνα + created_msg: Επιτυχής Ï€Ïοσθήκη νÎου κανόνα IP + delete: ΔιαγÏαφή + expires_in: + '1209600': 2 εβδομάδες + '15778476': 6 μήνες + '2629746': 1 μήνας + '31556952': 1 Îτος + '86400': 1 ημÎÏα + '94670856': 3 Îτη + new: + title: ΔημιουÏγία νÎου κανόνα IP + title: Κανόνες IP pending_accounts: title: ΛογαÏιασμοί σε αναμονή (%{count}) relationships: @@ -473,6 +512,8 @@ el: comment: none: ΚανÎνα created_at: ΚαταγγÎλθηκε + forwarded: Î ÏοωθημÎνα + forwarded_to: Î ÏοώθημÎνα Ï€Ïος %{domain} mark_as_resolved: ΣημειωμÎνο ως επιλυμÎνο mark_as_unresolved: ΣημειωμÎνο ως ανεπίλυτο notes: @@ -516,6 +557,7 @@ el: domain_blocks_rationale: title: Εμφάνιση ÏƒÎºÎµÏ€Ï„Î¹ÎºÎ¿Ï enable_bootstrap_timeline_accounts: + desc_html: Οι νÎοι χÏήστες να ακολουθοÏν τους Ï€ÏοÏυθμισμÎνουνς λογαÏιασμοÏÏ‚ ώστε η αÏχική Ïοή τους να μην είναι άδεια title: Î Ïοεπιλογή παÏακολοÏθησης για τους νÎους χÏήστες hero: desc_html: Εμφανίζεται στην μπÏοστινή σελίδα. Συνίσταται τουλάχιστον 600x100px. Όταν λείπει, χÏησιμοποιείται η μικÏογÏαφία του κόμβου @@ -681,8 +723,11 @@ el: prefix_sign_up: Άνοιξε λογαÏιασμό στο Mastodon σήμεÏα! suffix: Ανοίγοντας λογαÏιασμό θα μποÏείς να ακολουθείς άλλους, να ανεβάζεις ενημεÏώσεις και να ανταλλάζεις μηνÏματα με χÏήστες σε οποιοδήποτε διακομιστή Mastodon, καθώς και άλλα! didnt_get_confirmation: Δεν Îλαβες τις οδηγίες επιβεβαίωσης; + dont_have_your_security_key: Δεν Îχετε κλειδί ασφαλείας; forgot_password: ΞÎχασες το συνθηματικό σου; invalid_reset_password_token: Το διακÏιτικό επαναφοÏάς ÏƒÏ…Î½Î¸Î·Î¼Î±Ï„Î¹ÎºÎ¿Ï ÎµÎ¯Î½Î±Î¹ άκυÏο ή ληγμÎνο. ΠαÏακαλώ αιτήσου νÎο. + link_to_otp: ΓÏάψε τον κωδικό πιστοποίησης 2 παÏαγόντων (2FA) από το τηλÎφωνό σου ή τον κωδικό επαναφοÏάς + link_to_webauth: ΧÏήση συσκευής ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï Î±ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚ login: ΣÏνδεση logout: ΑποσÏνδεση migrate_account: Μετακόμιση σε διαφοÏετικό λογαÏιασμό @@ -708,6 +753,7 @@ el: pending: Η εφαÏμογή σας εκκÏεμεί ÎγκÏισης, πιθανόν θα διαÏκÎσει κάποιο χÏόνο. Θα λάβετε email αν εγκÏιθεί. redirecting_to: Ο λογαÏιασμός σου είναι ανενεÏγός γιατί επί του παÏόντος ανακατευθÏνει στον %{acct}. trouble_logging_in: Î Ïόβλημα σÏνδεσης; + use_security_key: ΧÏήση ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï Î±ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚ authorize_follow: already_following: Ήδη ακολουθείς αυτό το λογαÏιασμό already_requested: Έχετε ήδη στείλει Îνα αίτημα ακολοÏθησης σε αυτόν τον λογαÏιασμό @@ -732,6 +778,7 @@ el: date: formats: default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}ω" @@ -796,6 +843,7 @@ el: request: Αιτήσου το αÏχείο σου size: ΜÎγεθος blocks: ΜπλοκάÏεις + bookmarks: Σελιδοδείκτες csv: CSV domain_blocks: ΜπλοκαÏίσματα κόμβων lists: Λίστες @@ -863,6 +911,8 @@ el: status: Κατάσταση επαλήθευσης view_proof: Εμφάνιση απόδειξης imports: + errors: + over_rows_processing_limit: πεÏιÎχει πεÏισσότεÏες από %{count} γÏαμμÎÏ‚ modes: merge: Συγχώνευση merge_long: ΔιατήÏηση των εγγÏάφων που υπάÏχουν και Ï€Ïοσθηκη των νÎων @@ -872,6 +922,7 @@ el: success: Τα δεδομÎνα σου μεταφοÏτώθηκαν επιτυχώς και θα επεξεÏγαστοÏν εν καιÏÏŽ types: blocking: Λίστα Î±Ï€Î¿ÎºÎ»ÎµÎ¹ÏƒÎ¼Î¿Ï + bookmarks: Σελιδοδείκτες domain_blocking: Λίστα αποκλεισμÎνων τομÎων following: Λίστα ακολοÏθων muting: Λίστα αποσιωπήσεων @@ -992,6 +1043,10 @@ el: quadrillion: τετÏάκις. thousand: χ. trillion: Ï„Ïις. + otp_authentication: + code_hint: Για να συνεχίσεις, γÏάψε τον κωδικό που δημιοÏÏγησε η εφαÏμογή πιστοποίησης + enable: ΕνεÏγοποίηση + setup: ΡÏθμιση pagination: newer: ÎεότεÏο next: Επόμενο @@ -1154,6 +1209,8 @@ el: other: "%{count} ψήφοι" vote: Ψήφισε show_more: Δείξε πεÏισσότεÏα + show_newer: Εμφάνιση νεότεÏων + show_older: Εμφάνιση παλαιότεÏων show_thread: Εμφάνιση νήματος sign_in_to_participate: ΣυνδÎσου για να συμμετάσχεις στη συζήτηση title: '%{name}: "%{quote}"' @@ -1262,21 +1319,17 @@ el: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Βάλε τον κωδικό που δημιοÏÏγησε η εφαÏμογή πιστοποίησής σου για επιβεβαίωση - description_html: Αν ενεÏγοποιήσεις την <strong>πιστοποίηση 2 παÏαγόντων (2FA)</strong>, για να συνδεθείς θα Ï€ÏÎπει να Îχεις το τηλÎφωνό σου, που θα σου δημιουÏγήσει κλειδιά εισόδου. + add: Î Ïοσθήκη disable: ΑπενεÏγοποίησε - enable: ΕνεÏγοποίησε + edit: ΕπεξεÏγασία enabled: Η πιστοποίηση 2 παÏαγόντων (2FA) είναι ενεÏγοποιημÎνη enabled_success: Η πιστοποίηση 2 παÏαγόντων (2FA) ενεÏγοποιήθηκε επιτυχώς generate_recovery_codes: ΔημιοÏÏγησε κωδικοÏÏ‚ ανάκτησης - instructions_html: "<strong>ΣάÏωσε αυτόν τον κωδικό QR με την εφαÏμογή Google Authenticator ή κάποια άλλη αντίστοιχη στο τηλÎφωνό σου</strong>. Από εδώ και στο εξής, η εφαÏμογή αυτή θα δημιουÏγεί κλειδιά που θα Ï€ÏÎπει να εισάγεις όταν συνδÎεσαι." lost_recovery_codes: Οι κωδικοί ανάκτησης σου επιτÏÎπουν να ανακτήσεις ξανά Ï€Ïόσβαση στον λογαÏιασμό σου αν χάσεις το τηλÎφωνό σου. Αν Îχεις χάσει τους κωδικοÏÏ‚ ανάκτησης, μποÏείς να τους δημιουÏγήσεις ξανά εδώ. Οι παλιοί κωδικοί σου θα ακυÏωθοÏν. - manual_instructions: 'Αν δεν μποÏείς να σαÏώσεις τον κωδικό QR και χÏειάζεσαι να τον εισάγεις χειÏοκίνητα, οÏίστε η μυστική φÏάση σε μοÏφή κειμÎνου:' + otp: ΕφαÏμογή επαλήθευσης recovery_codes: ΕφεδÏικοί κωδικοί ανάκτησης recovery_codes_regenerated: Οι εφεδÏικοί κωδικοί ανάκτησης δημιουÏγήθηκαν επιτυχώς recovery_instructions_html: Αν ποτΠδεν Îχεις Ï€Ïόσβαση στο κινητό σου, μποÏείς να χÏησιμοποιήσεις Îναν από τους παÏακάτω κωδικοÏÏ‚ ανάκτησης για να αποκτήσεις Ï€Ïόσβαση στο λογαÏιασμό σου. <strong>ΔιαφÏλαξε τους κωδικοÏÏ‚ ανάκτησης</strong>. Για παÏάδειγμα, μποÏείς να τους εκτυπώσεις και να τους φυλάξεις μαζί με άλλα σημαντικά σου ÎγγÏαφα. - setup: Στήσιμο - wrong_code: Ο κωδικός που Îβαλες ήταν άκυÏος! Τα Ïολόγια στον διακομιστή και τη συσκευή είναι σωστά; user_mailer: backup_ready: explanation: Είχες ζητήσει εφεδÏικό αντίγÏαφο του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… στο Mastodon. Είναι Îτοιμο για κατÎβασμα! @@ -1304,6 +1357,7 @@ el: title: disable: ΠαγωμÎνος λογαÏιασμός none: Î Ïοειδοποίηση + sensitive: Το πολυμÎσο σας Îχει σημανθεί ως ευαίσθητο silence: ΠεÏιοÏισμÎνος λογαÏιασμός suspend: ΛογαÏιασμός σε αναστολή welcome: @@ -1324,9 +1378,11 @@ el: tips: ΣυμβουλÎÏ‚ title: Καλώς ÏŒÏισες, %{name}! users: + blocked_email_provider: Δεν είναι επιτÏεπτός αυτός ο πάÏοχος email follow_limit_reached: Δεν μποÏείς να ακολουθήσεις πεÏισσότεÏα από %{limit} άτομα generic_access_help_html: ΔυσκολεÏεσαι να μπεις στο λογαÏιασμό σου; ΜποÏείς να επικοινωνήσεις στο %{email} για βοήθεια invalid_email: Η διεÏθυνση email είναι άκυÏη + invalid_email_mx: Αυτή η διεÏθυνση email δεν φαίνεται να υπάÏχει invalid_otp_token: ΆκυÏος κωδικός πιστοποίησης 2 παÏαγόντων (2FA) invalid_sign_in_token: ΆκυÏος κωδικός ασφάλειας otp_lost_help_html: Αν χάσεις και τα δÏο, μποÏείς να επικοινωνήσεις με τον/την %{email} @@ -1336,3 +1392,13 @@ el: verification: explanation_html: 'ΜποÏείς να <strong>πιστοποιήσεις τον εαυτό σου ως ιδιοκτήτη των συνδÎσμων που εμφανίζεις στα μεταδεδομÎνα του Ï€Ïοφίλ σου</strong>. Για να συμβεί αυτό, ο συνδεδεμÎνος ιστότοπος Ï€ÏÎπει να πεÏιÎχει Îνα σÏνδεσμο που να επιστÏÎφει Ï€Ïος το Ï€Ïοφίλ σου στο Mastodon. Ο σÏνδεσμος επιστÏοφής <strong>Ï€ÏÎπει</strong> πεÏιÎχει την ιδιότητα (attribute) <code>rel="me"</code>. Το πεÏιεχόμενο του κειμÎνου δεν Îχει σημασία. Για παÏάδειγμα:' verification: Πιστοποίηση + webauthn_credentials: + add: Î Ïοσθήκη νÎου ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï Î±ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚ + create: + success: Το κλειδί ασφαλείας σας Ï€ÏοστÎθηκε με επιτυχία. + delete: ΔιαγÏαφή + delete_confirmation: Είστε βÎβαιοι ότι θÎλετε να διαγÏάψετε αυτό το κλειδί ασφαλείας; + destroy: + success: Το κλειδί ασφαλείας σας διαγÏάφηκε με επιτυχία. + invalid_credential: ΆκυÏο κλειδί ασφαλείας + registered_on: ΕγγÏαφή στις %{date} diff --git a/config/locales/en.yml b/config/locales/en.yml index 2cae0a3e3bad355d72efaf046b3fec03e5973721..8245397d7c7915f60d82cc370c961b864ee78c1b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -60,6 +60,7 @@ en: one: Follower other: Followers following: Following + instance_actor_flash: This account is a virtual actor used to represent the server itself and not any individual user. It is used for federation purposes and should not be suspended. joined: Joined %{date} last_active: last active link_verified_on: Ownership of this link was checked on %{date} @@ -98,6 +99,7 @@ en: add_email_domain_block: Block e-mail domain approve: Approve approve_all: Approve all + approved_msg: Successfully approved %{username}'s sign-up application are_you_sure: Are you sure? avatar: Avatar by_domain: Domain @@ -111,22 +113,26 @@ en: confirm: Confirm confirmed: Confirmed confirming: Confirming + delete: Delete data deleted: Deleted demote: Demote - disable: Disable + destroyed_msg: "%{username}'s data is now queued to be deleted imminently" + disable: Freeze disable_two_factor_authentication: Disable 2FA - disabled: Disabled + disabled: Frozen display_name: Display name domain: Domain edit: Edit email: Email email_status: Email status - enable: Enable + enable: Unfreeze enabled: Enabled + enabled_msg: Successfully unfroze %{username}'s account followers: Followers follows: Follows header: Header inbox_url: Inbox URL + invite_request_text: Reasons for joining invited_by: Invited by ip: IP joined: Joined @@ -138,6 +144,8 @@ en: login_status: Login status media_attachments: Media attachments memorialize: Turn into memoriam + memorialized: Memorialized + memorialized_msg: Successfully turned %{username} into a memorial account moderation: active: Active all: All @@ -158,10 +166,14 @@ en: public: Public push_subscription_expires: PuSH subscription expires redownload: Refresh profile + redownloaded_msg: Successfully refreshed %{username}'s profile from origin reject: Reject reject_all: Reject all + rejected_msg: Successfully rejected %{username}'s sign-up application remove_avatar: Remove avatar remove_header: Remove header + removed_avatar_msg: Successfully removed %{username}'s avatar image + removed_header_msg: Successfully removed %{username}'s header image resend_confirmation: already_confirmed: This user is already confirmed send: Resend confirmation email @@ -178,22 +190,30 @@ en: search: Search search_same_email_domain: Other users with the same e-mail domain search_same_ip: Other users with the same IP + sensitive: Sensitive + sensitized: marked as sensitive shared_inbox_url: Shared inbox URL show: created_reports: Made reports targeted_reports: Reported by others - silence: Silence - silenced: Silenced + silence: Limit + silenced: Limited statuses: Statuses subscribe: Subscribe suspended: Suspended + suspension_irreversible: The data of this account has been irreversibly deleted. You can unsuspend the account to make it usable but it will not recover any data it previously had. + suspension_reversible_hint_html: The account has been suspended, and the data will be fully removed on %{date}. Until then, the account can be restored without any ill effects. If you wish to remove all of the account's data immediately, you can do so below. time_in_queue: Waiting in queue %{time} title: Accounts unconfirmed_email: Unconfirmed email + undo_sensitized: Undo sensitive undo_silenced: Undo silence undo_suspension: Undo suspension + unsilenced_msg: Successfully unlimited %{username}'s account unsubscribe: Unsubscribe + unsuspended_msg: Successfully unsuspended %{username}'s account username: Username + view_domain: View summary for domain warn: Warn web: Web whitelisted: Allowed for federation @@ -208,12 +228,14 @@ en: create_domain_allow: Create Domain Allow create_domain_block: Create Domain Block create_email_domain_block: Create E-mail Domain Block + create_ip_block: Create IP rule demote_user: Demote User destroy_announcement: Delete Announcement destroy_custom_emoji: Delete Custom Emoji destroy_domain_allow: Delete Domain Allow destroy_domain_block: Delete Domain Block destroy_email_domain_block: Delete e-mail domain block + destroy_ip_block: Delete IP rule destroy_status: Delete Status disable_2fa_user: Disable 2FA disable_custom_emoji: Disable Custom Emoji @@ -226,13 +248,16 @@ en: reopen_report: Reopen Report reset_password_user: Reset Password resolve_report: Resolve Report + sensitive_account: Mark the media in your account as sensitive silence_account: Silence Account suspend_account: Suspend Account unassigned_report: Unassign Report + unsensitive_account: Unmark the media in your account as sensitive unsilence_account: Unsilence Account unsuspend_account: Unsuspend Account update_announcement: Update Announcement update_custom_emoji: Update Custom Emoji + update_domain_block: Update Domain Block update_status: Update Status actions: assigned_to_self_report: "%{name} assigned report %{target} to themselves" @@ -244,12 +269,14 @@ en: create_domain_allow: "%{name} allowed federation with domain %{target}" create_domain_block: "%{name} blocked domain %{target}" create_email_domain_block: "%{name} blocked e-mail domain %{target}" + create_ip_block: "%{name} created rule for IP %{target}" demote_user: "%{name} demoted user %{target}" destroy_announcement: "%{name} deleted announcement %{target}" destroy_custom_emoji: "%{name} destroyed emoji %{target}" destroy_domain_allow: "%{name} disallowed federation with domain %{target}" destroy_domain_block: "%{name} unblocked domain %{target}" destroy_email_domain_block: "%{name} unblocked e-mail domain %{target}" + destroy_ip_block: "%{name} deleted rule for IP %{target}" destroy_status: "%{name} removed status by %{target}" disable_2fa_user: "%{name} disabled two factor requirement for user %{target}" disable_custom_emoji: "%{name} disabled emoji %{target}" @@ -262,13 +289,16 @@ en: reopen_report: "%{name} reopened report %{target}" reset_password_user: "%{name} reset password of user %{target}" resolve_report: "%{name} resolved report %{target}" + sensitive_account: "%{name} marked %{target}'s media as sensitive" silence_account: "%{name} silenced %{target}'s account" suspend_account: "%{name} suspended %{target}'s account" unassigned_report: "%{name} unassigned report %{target}" + unsensitive_account: "%{name} unmarked %{target}'s media as sensitive" unsilence_account: "%{name} unsilenced %{target}'s account" unsuspend_account: "%{name} unsuspended %{target}'s account" update_announcement: "%{name} updated announcement %{target}" update_custom_emoji: "%{name} updated emoji %{target}" + update_domain_block: "%{name} updated domain block for %{target}" update_status: "%{name} updated status by %{target}" deleted_status: "(deleted status)" empty: No logs found. @@ -372,6 +402,8 @@ en: silence: Silence suspend: Suspend title: New domain block + obfuscate: Obfuscate domain name + obfuscate_hint: Partially obfuscate the domain name in the list if advertising the list of domain limitations is enabled private_comment: Private comment private_comment_hint: Comment about this domain limitation for internal use by the moderators. public_comment: Public comment @@ -411,6 +443,7 @@ en: instances: by_domain: Domain delivery_available: Delivery is available + empty: No domains found. known_accounts: one: "%{count} known account" other: "%{count} known accounts" @@ -434,6 +467,21 @@ en: expired: Expired title: Filter title: Invites + ip_blocks: + add_new: Create rule + created_msg: Successfully added new IP rule + delete: Delete + expires_in: + '1209600': 2 weeks + '15778476': 6 months + '2629746': 1 month + '31556952': 1 year + '86400': 1 day + '94670856': 3 years + new: + title: Create new IP rule + no_ip_block_selected: No IP rules were changed as none were selected + title: IP rules pending_accounts: title: Pending accounts (%{count}) relationships: @@ -473,6 +521,8 @@ en: comment: none: None created_at: Reported + forwarded: Forwarded + forwarded_to: Forwarded to %{domain} mark_as_resolved: Mark as resolved mark_as_unresolved: Mark as unresolved notes: @@ -516,6 +566,7 @@ en: domain_blocks_rationale: title: Show rationale enable_bootstrap_timeline_accounts: + desc_html: Make new users automatically follow configured accounts so their home feed doesn't start out empty title: Enable default follows for new users hero: desc_html: Displayed on the frontpage. At least 600x100px recommended. When not set, falls back to server thumbnail @@ -542,6 +593,9 @@ en: min_invite_role: disabled: No one title: Allow invitations by + require_invite_text: + desc_html: When registrations require manual approval, make the “Why do you want to join?†text input mandatory rather than optional + title: Require new users to enter a reason to join registrations_mode: modes: approved: Approval required for sign up @@ -681,8 +735,11 @@ en: prefix_sign_up: Sign up on Mastodon today! suffix: With an account, you will be able to follow people, post updates and exchange messages with users from any Mastodon server and more! didnt_get_confirmation: Didn't receive confirmation instructions? + dont_have_your_security_key: Don't have your security key? forgot_password: Forgot your password? invalid_reset_password_token: Password reset token is invalid or expired. Please request a new one. + link_to_otp: Enter a two-factor code from your phone or a recovery code + link_to_webauth: Use your security key device login: Log in logout: Logout migrate_account: Move to a different account @@ -707,7 +764,9 @@ en: functional: Your account is fully operational. pending: Your application is pending review by our staff. This may take some time. You will receive an e-mail if your application is approved. redirecting_to: Your account is inactive because it is currently redirecting to %{acct}. + too_fast: Form submitted too fast, try again. trouble_logging_in: Trouble logging in? + use_security_key: Use security key authorize_follow: already_following: You are already following this account already_requested: You have already sent a follow request to that account @@ -732,6 +791,7 @@ en: date: formats: default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -796,6 +856,7 @@ en: request: Request your archive size: Size blocks: You block + bookmarks: Bookmarks csv: CSV domain_blocks: Domain blocks lists: Lists @@ -809,7 +870,7 @@ en: filters: contexts: account: Profiles - home: Home timeline + home: Home and lists notifications: Notifications public: Public timelines thread: Conversations @@ -863,6 +924,8 @@ en: status: Verification status view_proof: View proof imports: + errors: + over_rows_processing_limit: contains more than %{count} rows modes: merge: Merge merge_long: Keep existing records and add new ones @@ -872,6 +935,7 @@ en: success: Your data was successfully uploaded and will now be processed in due time types: blocking: Blocking list + bookmarks: Bookmarks domain_blocking: Domain blocking list following: Following list muting: Muting list @@ -993,6 +1057,14 @@ en: thousand: K trillion: T unit: '' + otp_authentication: + code_hint: Enter the code generated by your authenticator app to confirm + description_html: If you enable <strong>two-factor authentication</strong> using an authenticator app, logging in will require you to be in possession of your phone, which will generate tokens for you to enter. + enable: Enable + instructions_html: "<strong>Scan this QR code into Google Authenticator or a similiar TOTP app on your phone</strong>. From now on, that app will generate tokens that you will have to enter when logging in." + manual_instructions: 'If you can''t scan the QR code and need to enter it manually, here is the plain-text secret:' + setup: Set up + wrong_code: The entered code was invalid! Are server time and device time correct? pagination: newer: Newer next: Next @@ -1021,6 +1093,7 @@ en: relationships: activity: Account activity dormant: Dormant + follow_selected_followers: Follow selected followers followers: Followers following: Following invited: Invited @@ -1117,6 +1190,7 @@ en: profile: Profile relationships: Follows and followers two_factor_authentication: Two-factor Auth + webauthn_authentication: Security keys spam_check: spam_detected: This is an automated report. Spam has been detected. statuses: @@ -1155,6 +1229,8 @@ en: other: "%{count} votes" vote: Vote show_more: Show more + show_newer: Show newer + show_older: Show older show_thread: Show thread sign_in_to_participate: Sign in to participate in the conversation title: '%{name}: "%{quote}"' @@ -1263,21 +1339,20 @@ en: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Enter the code generated by your authenticator app to confirm - description_html: If you enable <strong>two-factor authentication</strong>, logging in will require you to be in possession of your phone, which will generate tokens for you to enter. - disable: Disable - enable: Enable + add: Add + disable: Disable 2FA + disabled_success: Two-factor authentication successfully disabled + edit: Edit enabled: Two-factor authentication is enabled enabled_success: Two-factor authentication successfully enabled generate_recovery_codes: Generate recovery codes - instructions_html: "<strong>Scan this QR code into Google Authenticator or a similiar TOTP app on your phone</strong>. From now on, that app will generate tokens that you will have to enter when logging in." lost_recovery_codes: Recovery codes allow you to regain access to your account if you lose your phone. If you've lost your recovery codes, you can regenerate them here. Your old recovery codes will be invalidated. - manual_instructions: 'If you can''t scan the QR code and need to enter it manually, here is the plain-text secret:' + methods: Two-factor methods + otp: Authenticator app recovery_codes: Backup recovery codes recovery_codes_regenerated: Recovery codes successfully regenerated recovery_instructions_html: If you ever lose access to your phone, you can use one of the recovery codes below to regain access to your account. <strong>Keep the recovery codes safe</strong>. For example, you may print them and store them with other important documents. - setup: Set up - wrong_code: The entered code was invalid! Are server time and device time correct? + webauthn: Security keys user_mailer: backup_ready: explanation: You requested a full backup of your Mastodon account. It's now ready for download! @@ -1291,20 +1366,23 @@ en: title: Sign in attempt warning: explanation: - disable: While your account is frozen, your account data remains intact, but you cannot perform any actions until it is unlocked. - silence: While your account is limited, only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you. - suspend: Your account has been suspended, and all of your toots and your uploaded media files have been irreversibly removed from this server, and servers where you had followers. + disable: You can no longer login to your account or use it in any other way, but your profile and other data remains intact. + sensitive: Your uploaded media files and linked media will be treated as sensitive. + silence: You can still use your account but only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you. + suspend: You can no longer use your account, and your profile and other data are no longer accessible. You can still login to request a backup of your data until the data is fully removed, but we will retain some data to prevent you from evading the suspension. get_in_touch: You can reply to this e-mail to get in touch with the staff of %{instance}. review_server_policies: Review server policies statuses: 'Specifically, for:' subject: disable: Your account %{acct} has been frozen none: Warning for %{acct} + sensitive: Your account %{acct} posting media has been marked as sensitive silence: Your account %{acct} has been limited suspend: Your account %{acct} has been suspended title: disable: Account frozen none: Warning + sensitive: Your media has been marked as sensitive silence: Account limited suspend: Account suspended welcome: @@ -1325,9 +1403,11 @@ en: tips: Tips title: Welcome aboard, %{name}! users: + blocked_email_provider: This e-mail provider isn't allowed follow_limit_reached: You cannot follow more than %{limit} people generic_access_help_html: Trouble accessing your account? You may get in touch with %{email} for assistance invalid_email: The e-mail address is invalid + invalid_email_mx: The e-mail address does not seem to exist invalid_otp_token: Invalid two-factor code invalid_sign_in_token: Invalid security code otp_lost_help_html: If you lost access to both, you may get in touch with %{email} @@ -1337,3 +1417,20 @@ en: verification: explanation_html: 'You can <strong>verify yourself as the owner of the links in your profile metadata</strong>. For that, the linked website must contain a link back to your Mastodon profile. The link back <strong>must</strong> have a <code>rel="me"</code> attribute. The text content of the link does not matter. Here is an example:' verification: Verification + webauthn_credentials: + add: Add new security key + create: + error: There was a problem adding your security key. Please try again. + success: Your security key was successfully added. + delete: Delete + delete_confirmation: Are you sure you want to delete this security key? + description_html: If you enable <strong>security key authentication</strong>, logging in will require you to use one of your security keys. + destroy: + error: There was a problem deleting you security key. Please try again. + success: Your security key was successfully deleted. + invalid_credential: Invalid security key + nickname_hint: Enter the nickname of your new security key + not_enabled: You haven't enabled WebAuthn yet + not_supported: This browser doesn't support security keys + otp_required: To use security keys please enable two-factor authentication first. + registered_on: Registered on %{date} diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml index 1375ebb33ed09d100ba9c3e62945bc6d1a996096..d3461474b16c0423076003cca88fa3419c04efa8 100644 --- a/config/locales/en_GB.yml +++ b/config/locales/en_GB.yml @@ -600,7 +600,7 @@ en_GB: limit: You have already featured the maximum amount of hashtags filters: contexts: - home: Home timeline + home: Home and lists notifications: Notifications public: Public timelines thread: Conversations diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 5c11fa6fcce2b9678981a03b0f9f7196f7025e84..64b7ccfc702976cf33adfffb82ee5c9b86126a42 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -35,10 +35,13 @@ eo: status_count_before: Kie skribiÄis tagline: Sekvi amikojn kaj trovi iujn novajn terms: Uzkondiĉoj - unavailable_content: Nedisponebla enhavo + unavailable_content: Kontrolitaj serviloj unavailable_content_description: domain: Servilo reason: 'Kialo:' + rejecting_media_title: Filtritaj aÅdovidaĵoj + silenced_title: Silentigitaj serviloj + suspended_title: Haltigitaj serviloj user_count_after: one: uzanto other: uzantoj @@ -86,6 +89,7 @@ eo: delete: Forigi destroyed_msg: Kontrola noto sukcese detruita! accounts: + add_email_domain_block: Bloki retadresan domajnon approve: Aprobi approve_all: Aprobi ĉiujn are_you_sure: Ĉu vi certas? @@ -101,6 +105,7 @@ eo: confirm: Konfirmi confirmed: Konfirmita confirming: Konfirmante + delete: Forigi datumojn deleted: Forigita demote: Degradi disable: Malebligi @@ -117,6 +122,7 @@ eo: follows: Sekvatoj header: Kapa bildo inbox_url: Enira URL + invite_request_text: ê°€ìž…í•˜ë ¤ëŠ” ì´ìœ invited_by: Invitita de ip: IP joined: AliÄis @@ -128,6 +134,7 @@ eo: login_status: Ensaluta stato media_attachments: Ligitaj aÅdovidaĵoj memorialize: ÅœanÄi al memoro + memorialized: Memorita moderation: active: Aktivaj all: Ĉio @@ -154,7 +161,7 @@ eo: remove_header: Forigi kapan bildon resend_confirmation: already_confirmed: Ĉi tiu uzanto jam estas konfirmita - send: Esend konfirmi retpoÅton + send: Resendi konfirman retmesaÄon success: Konfirma retmesaÄo sukcese sendita! reset: Restarigi reset_password: Restarigi pasvorton @@ -167,6 +174,8 @@ eo: user: Uzanto search: Serĉi search_same_ip: Aliaj uzantoj kun la sama IP + sensitive: Tikla + sensitized: markita tikla shared_inbox_url: URL de kunhavigita leterkesto show: created_reports: Kreitaj signaloj @@ -179,28 +188,34 @@ eo: time_in_queue: Atendado en atendovico %{time} title: Kontoj unconfirmed_email: Nekonfirmita retadreso + undo_sensitized: Malfari sentema undo_silenced: Malfari kaÅon undo_suspension: Malfari haltigon unsubscribe: Malaboni username: Uzantnomo + view_domain: Vidi la resumon de la domajno warn: Averti web: Reto whitelisted: En la blanka listo action_logs: action_types: + assigned_to_self_report: Atribui Raporton + change_email_user: ÅœanÄi retadreson de uzanto confirm_user: Konfermi uzanto create_account_warning: Krei Averton create_announcement: Krei Anoncon create_custom_emoji: Krei Propran emoÄion create_domain_allow: Krei Domajnan Permeson - create_domain_block: Krei Domajnan Blokadon - create_email_domain_block: Krei RetpoÅtmesaÄan Domajnan Blokadon + create_domain_block: Krei blokadon de domajno + create_email_domain_block: Krei blokadon de retpoÅta domajno + create_ip_block: Krei IP-regulon demote_user: Malpromocii uzanton destroy_announcement: Forigi Anoncon destroy_custom_emoji: Forigi Propran emoÄion destroy_domain_allow: Forigi Domajnan Permeson - destroy_domain_block: Forigi Domajnan Blokadon - destroy_email_domain_block: Forigi retpoÅtmesaÄan domajnan blokadon + destroy_domain_block: Forigi blokadon de domajno + destroy_email_domain_block: Forigi blokadon de retpoÅta domajno + destroy_ip_block: Forigi IP-regulon destroy_status: Forigi mesaÄon disable_2fa_user: Malebligi 2FA disable_custom_emoji: Malebligi Propran EmoÄion @@ -212,8 +227,15 @@ eo: reopen_report: Remalfermi signalon reset_password_user: Restarigi pasvorton resolve_report: Solvitaj reporto + sensitive_account: Marki tikla la aÅdovidaĵojn de via konto silence_account: Silentigi konton suspend_account: Haltigi konton + unsilence_account: Malsilentigi konton + unsuspend_account: Malhaltigi konton + update_announcement: Äœisdatigi anoncon + update_custom_emoji: Äœisdatigi proprajn emoÄiojn + update_domain_block: Äœigdatigi domajnan blokadon + update_status: Äœisdatigi staton actions: assigned_to_self_report: "%{name} asignis signalon %{target} al si mem" change_email_user: "%{name} ÅanÄis retadreson de uzanto %{target}" @@ -223,13 +245,15 @@ eo: create_custom_emoji: "%{name} alÅutis novan emoÄion %{target}" create_domain_allow: "%{name} aldonis domajnon %{target} al la blanka listo" create_domain_block: "%{name} blokis domajnon %{target}" - create_email_domain_block: "%{name} aldonis retadresan domajnon %{target} al la nigra listo" + create_email_domain_block: "%{name} blokis retpoÅtan domajnon %{target}" + create_ip_block: "%{name} kreis regulon por IP %{target}" demote_user: "%{name} degradis uzanton %{target}" destroy_announcement: "%{name} forigis anoncon %{target}" destroy_custom_emoji: "%{name} neniigis la emoÄion %{target}" destroy_domain_allow: "%{name} forigis domajnon %{target} el la blanka listo" destroy_domain_block: "%{name} malblokis domajnon %{target}" - destroy_email_domain_block: "%{name} aldonis retadresan domajnon %{target} al la blanka listo" + destroy_email_domain_block: "%{name} malblokis retpoÅtan domajnon %{target}" + destroy_ip_block: "%{name} forigis regulon por IP %{target}" destroy_status: "%{name} forigis mesaÄojn de %{target}" disable_2fa_user: "%{name} malebligis dufaktoran aÅtentigon por uzanto %{target}" disable_custom_emoji: "%{name} malebligis emoÄion %{target}" @@ -251,6 +275,9 @@ eo: update_custom_emoji: "%{name} Äisdatigis emoÄion %{target}" update_status: "%{name} Äisdatigis mesaÄon de %{target}" deleted_status: "(forigita mesaÄo)" + empty: Neniu protokolo trovita. + filter_by_action: Filtri per ago + filter_by_user: Filtri per uzanto title: Kontrola protokolo announcements: destroyed_msg: Anonco sukcese forigita! @@ -289,6 +316,7 @@ eo: listed: Listigita new: title: Aldoni novan propran emoÄion + not_permitted: Vi ne rajtas plenumi ĉi tiun agon overwrite: AnstataÅigi shortcode: Mallonga kodo shortcode_hint: AlmenaÅ 2 signoj, nur literoj, ciferoj kaj substrekoj @@ -333,7 +361,7 @@ eo: destroyed_msg: Domajno estis forigita el la blanka listo undo: Forigi el la blanka listo domain_blocks: - add_new: Aldoni novan + add_new: Aldoni novan blokadon de domajno created_msg: Domajna blokado en traktado destroyed_msg: Domajna blokado malfarita domain: Domajno @@ -366,7 +394,7 @@ eo: retroactive: silence: MalkaÅi ĉiujn kontojn, kiuj ekzistas en ĉi tiu domajno suspend: Malhaltigi ĉiujn kontojn, kiuj ekzistas en ĉi tiu domajno - title: Malfari domajnan blokadon por %{domain} + title: Malfari blokadon de domajno %{domain} undo: Malfari undo: Malfari view: Vidi domajna blokado @@ -385,6 +413,7 @@ eo: instances: by_domain: Domajno delivery_available: Liverado disponeblas + empty: Neniuj domajnoj trovitaj. known_accounts: one: "%{count} konata konto" other: "%{count} konataj kontoj" @@ -408,6 +437,21 @@ eo: expired: Eksvalida title: Filtri title: Invitoj + ip_blocks: + add_new: Krei regulon + created_msg: Nova IP-regulo sukcese aldonita + delete: Forigi + expires_in: + '1209600': 2 semajnoj + '15778476': 6 monatoj + '2629746': 1 monato + '31556952': 1 jaro + '86400': 1 tago + '94670856': 3 jaroj + new: + title: Krei novan IP-regulon + no_ip_block_selected: Neniu IP-regulo estis ÅanÄita ĉar neniu estis elektita + title: IP-reguloj pending_accounts: title: Pritraktataj kontoj (%{count}) relationships: @@ -662,9 +706,11 @@ eo: status: account_status: Statuso de la konto functional: Via konto estas plene funkcianta. + too_fast: Formularo sendita tro rapide, klopodu denove. trouble_logging_in: Äœeni ensaluti? authorize_follow: already_following: Vi jam sekvas tiun konton + already_requested: Vi jam sendis peton de sekvado al ĉi tiu konto error: BedaÅrinde, estis eraro en la serĉado de la fora konto follow: Sekvi follow_request: 'Vi sendis peton de sekvado al:' @@ -745,6 +791,7 @@ eo: request: Peti vian arkivon size: Grandeco blocks: Vi blokas + bookmarks: Legosignoj csv: CSV domain_blocks: Blokoj de domajnoj lists: Listoj @@ -758,7 +805,7 @@ eo: filters: contexts: account: Profiloj - home: Hejma templinio + home: Hejmo kaj listoj notifications: Sciigoj public: Publika templinio thread: Konversacioj @@ -818,6 +865,7 @@ eo: success: Viaj datumoj estis sukcese alÅutitaj kaj estos traktitaj kiel planite types: blocking: Listo de blokitoj + bookmarks: Legosignoj domain_blocking: Listo de blokitaj domajnoj following: Listo de sekvatoj muting: Listo de silentigitoj @@ -922,6 +970,8 @@ eo: quadrillion: Dd thousand: m trillion: Dn + otp_authentication: + enable: Ebligi pagination: newer: Pli nova next: Sekva @@ -950,6 +1000,7 @@ eo: relationships: activity: Konta aktiveco dormant: Dormanta + follow_selected_followers: Forigu selektitajn sekvantojn followers: Sekvantoj following: Sekvatoj invited: Invitita @@ -965,7 +1016,7 @@ eo: status: Statuso de la konto remote_follow: acct: Enmetu vian uzantnomo@domajno de kie vi volas agi - missing_resource: La URL de plusendado ne estis trovita + missing_resource: La bezonata URL de plusendado por via konto ne estis trovita no_account_html: Ĉu vi ne havas konton? Vi povas <a href='%{sign_up_path}' target='_blank'>registriÄi tie</a> proceed: DaÅrigi por eksekvi prompt: 'Vi eksekvos:' @@ -1048,6 +1099,9 @@ eo: two_factor_authentication: Dufaktora aÅtentigo statuses: attached: + audio: + one: "%{count} aÅdaĵo" + other: "%{count} aÅdaĵoj" description: 'Ligita: %{attached}' image: one: "%{count} bildo" @@ -1077,6 +1131,8 @@ eo: other: "%{count} voĉdonoj" vote: Voĉdoni show_more: Malfoldi + show_newer: Montri pli novajn + show_older: Montri pli malnovajn show_thread: Montri la fadenon sign_in_to_participate: Ensaluti por partopreni en la konversacio title: "%{name}: “%{quote}â€" @@ -1104,21 +1160,17 @@ eo: default: "%Y-%m-%d %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Enmetu la kodon kreitan de via aÅtentiga aplikaĵo por konfirmi - description_html: Se vi ebligas <strong>dufaktoran aÅtentigon</strong>, vi bezonos vian poÅtelefonon por ensaluti, ĉar Äi kreos nombrojn, kiujn vi devos enmeti. + add: Aldoni disable: Malebligi - enable: Ebligi + disabled_success: Dufaktora aÅtentigo sukcese malebligita + edit: Redakti enabled: Dufaktora aÅtentigo ebligita enabled_success: Dufaktora aÅtentigo sukcese ebligita generate_recovery_codes: Krei realirajn kodojn - instructions_html: "<strong>Skanu ĉi tiun QR-kodon per Google Authenticator aÅ per simila aplikaĵo en via poÅtelefono</strong>. De tiam, la aplikaĵo kreos nombrojn, kiujn vi devos enmeti." lost_recovery_codes: Realiraj kodoj permesas rehavi aliron al via konto se vi perdis vian telefonon. Se vi perdis viajn realirajn kodojn, vi povas rekrei ilin ĉi tie. Viaj malnovaj realiraj kodoj iÄos eksvalidaj. - manual_instructions: 'Se vi ne povas skani la QR-kodon kaj bezonas enmeti Äin mane, jen la tut-teksta sekreto:' recovery_codes: Realiraj kodoj recovery_codes_regenerated: Realiraj kodoj sukcese rekreitaj recovery_instructions_html: Se vi perdas aliron al via telefono, vi povas uzi unu el la subaj realiraj kodoj por rehavi aliron al via konto. <strong>Konservu realirajn kodojn sekure</strong>. Ekzemple, vi povas printi ilin kaj konservi ilin kun aliaj gravaj dokumentoj. - setup: Agordi - wrong_code: La enmetita kodo estis nevalida! Ĉu la servila tempo kaj la aparata tempo Äustas? user_mailer: backup_ready: explanation: Vi petis kompletan arkivon de via Mastodon-konto. Äœi nun pretas por elÅutado! @@ -1159,7 +1211,7 @@ eo: tips: Konsiloj title: Bonvenon, %{name}! users: - follow_limit_reached: Vi ne povas sekvi pli da %{limit} homojn + follow_limit_reached: Vi ne povas sekvi pli ol %{limit} homo(j) invalid_email: La retadreso estas nevalida invalid_otp_token: Nevalida kodo de dufaktora aÅtentigo otp_lost_help_html: Se vi perdas aliron al ambaÅ, vi povas kontakti %{email} @@ -1168,3 +1220,6 @@ eo: verification: explanation_html: 'Vi povas <strong>pruvi, ke vi estas la posedanto de la ligiloj en viaj profilaj metadatumoj</strong>. Por fari tion, la alligita retejo devas enhavi ligilon reen al via Mastodon-profilo. La religilo <strong>devas</strong> havi la atributon <code>rel="me"</code>. Ne gravas la teksta enhavo de la religilo. Jen ekzemplo:' verification: Kontrolo + webauthn_credentials: + delete: Forigi + registered_on: Registrigita je %{date} diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 0a3c6e4ec508d33ab243d066d31eb658fabb1c83..32e07907496774f817885bfa9ff9bbfa9f03224e 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -2,7 +2,7 @@ es-AR: about: about_hashtag_html: Estos son toots públicos etiquetados con <strong>#%{hashtag}</strong>. Si tenés una cuenta en cualquier parte del fediverso, podés interactuar con ellos. - about_mastodon_html: Mastodon es una red social basada en protocolos abiertos de la web y es software libre y de código abierto. Es descentralizada, como el correo electrónico. + about_mastodon_html: 'La red social del futuro: ¡sin publicidad, sin vigilancia corporativa, con diseño ético y descentralización! ¡Con Mastodon vos sos el dueño de tus datos!' about_this: Acerca de Mastodon active_count_after: activo active_footnote: Usuarios activos mensualmente (MAU) @@ -18,7 +18,7 @@ es-AR: contact_unavailable: No disponible discover_users: Descubrir usuarios documentation: Documentación - federation_hint_html: Con una cuenta en %{instance} vas a poder seguir a gente de cualquier servidor de Mastodon y más allá. + federation_hint_html: Con una cuenta en %{instance} vas a poder seguir a cuentas de cualquier servidor de Mastodon y más allá. get_apps: Probá una aplicación móvil hosted_on: Mastodon alojado en %{domain} instance_actor_flash: | @@ -30,12 +30,12 @@ es-AR: server_stats: 'EstadÃsticas del servidor:' source_code: Código fuente status_count_after: - one: estado - other: estados + one: toot + other: toots status_count_before: Que enviaron tagline: Seguà a tus amigos y descubrà nueva gente terms: Términos del servicio - unavailable_content: Contenido no disponible + unavailable_content: Servidores moderados unavailable_content_description: domain: Servidor reason: Razón @@ -53,14 +53,15 @@ es-AR: what_is_mastodon: "¿Qué es Mastodon?" accounts: choices_html: 'Recomendados de %{name}:' - endorsements_hint: Podés recomendar a gente que seguÃs desde la interface web, y va aparecer acá. + endorsements_hint: Podés recomendar a cuentas que seguÃs desde la interface web, y van a aparecer acá. featured_tags_hint: Podés destacar etiquetas especÃficas que se mostrarán acá. follow: Seguir followers: one: Seguidor other: Seguidores following: Siguiendo - joined: Se unió en %{date} + instance_actor_flash: Esta cuenta es un actor virtual usado para representar al servidor en sà mismo y no a ningún usuario individual. Se usa para propósitos de la federación y no debe ser suspendido. + joined: En este servidor desde %{date} last_active: última actividad link_verified_on: La propiedad de este enlace fue verificada el %{date} media: Medios @@ -71,12 +72,12 @@ es-AR: people_followed_by: "%{name} sigue a estas personas" people_who_follow: Estas personas siguen a %{name} pin_errors: - following: Ya tenés que estar siguiendo a la persona que querés recomendar + following: Ya tenés que estar siguiendo a la cuenta que querés recomendar posts: one: Toot other: Toots posts_tab_heading: Toots - posts_with_replies: Toots con respuestas + posts_with_replies: Toots y respuestas reserved_username: El nombre de usuario está reservado roles: admin: Administrador @@ -95,9 +96,10 @@ es-AR: delete: Eliminar destroyed_msg: "¡Nota de moderación destruÃda exitosamente!" accounts: - add_email_domain_block: Desaprobar el dominio del correo electrónico + add_email_domain_block: Bloquear el dominio del correo electrónico approve: Aprobar approve_all: Aprobar todas + approved_msg: Se aprobó exitosamente la solicitud de registro de %{username} are_you_sure: "¿Estás seguro?" avatar: Avatar by_domain: Dominio @@ -110,40 +112,46 @@ es-AR: title: Cambiar correo electrónico para %{username} confirm: Confirmar confirmed: Confirmado - confirming: Confirmando + confirming: Confirmación + delete: Eliminar datos deleted: Eliminado demote: Bajar de nivel - disable: Deshabilitar + destroyed_msg: Los datos de %{username} están ahora en cola para ser eliminados inminentemente + disable: Congelar disable_two_factor_authentication: Deshabilitar 2FA - disabled: Deshabilitada + disabled: Congelada display_name: Nombre para mostrar domain: Dominio edit: Editar email: Correo electrónico email_status: Estado del correo - enable: Habilitar + enable: Descongelar enabled: Habilitada + enabled_msg: Se descongeló exitosamente la cuenta de %{username} followers: Seguidores follows: Seguidores header: Cabecera inbox_url: Dirección web de la bandeja de entrada + invite_request_text: Motivos para unirte invited_by: Invitado por ip: Dirección IP joined: Se unió en location: all: Todas - local: Local - remote: Remota + local: Locales + remote: Remotas title: Ubicación login_status: Estado del inicio de sesión media_attachments: Adjuntos - memorialize: Convertir en recordatorio + memorialize: Convertir en cuenta conmemorativa + memorialized: Cuenta conmemorativa + memorialized_msg: "%{username} se convirtió exitosamente en una cuenta conmemorativa" moderation: active: Activa all: Todas pending: Pendiente - silenced: Silenciados - suspended: Suspendidos + silenced: Silenciadas + suspended: Suspendidas title: Moderación moderation_notes: Notas de moderación most_recent_activity: Actividad más reciente @@ -153,15 +161,19 @@ es-AR: not_subscribed: No suscripto pending: Revisión pendiente perform_full_suspension: Suspender - promote: Promocionar + promote: Promover protocol: Protocolo public: Pública - push_subscription_expires: La suscripción PuSH vence + push_subscription_expires: La suscripción push vence redownload: Recargar perfil + redownloaded_msg: Se actualizó exitosamente el perfil de %{username} desde el origen reject: Rechazar reject_all: Rechazar todas + rejected_msg: Se rechazó exitosamente la solicitud de registro de %{username} remove_avatar: Quitar avatar remove_header: Quitar cabecera + removed_avatar_msg: Se quitó exitosamente el avatar de %{username} + removed_header_msg: Se quitó exitosamente el encabezado de %{username} resend_confirmation: already_confirmed: Este usuario ya está confirmado send: Reenviar correo electrónico de confirmación @@ -173,30 +185,38 @@ es-AR: roles: admin: Administrador moderator: Moderador - staff: Equipo + staff: Administración user: Usuario search: Buscar search_same_email_domain: Otros usuarios con el mismo dominio de correo electrónico search_same_ip: Otros usuarios con la misma dirección IP + sensitive: Sensible + sensitized: marcado como sensible shared_inbox_url: Dirección web de la bandeja de entrada compartida show: - created_reports: Informes hechos + created_reports: Denuncias hechas targeted_reports: Denunciado por otros - silence: Silenciar - silenced: Silenciadas - statuses: Estados + silence: Limitar + silenced: Limitadas + statuses: Toots subscribe: Suscribirse suspended: Suspendidas + suspension_irreversible: Se eliminaron irreversiblemente los datos de esta cuenta. Podés dejar de suspenderla para hacerla utilizable, pero no se recuperarán los datos que tenÃa anteriormente. + suspension_reversible_hint_html: La cuenta fue suspendida y los datos se eliminarán completamente el %{date}. Hasta entonces, la cuenta puede ser restaurada sin ningún efecto perjudicial. Si querés eliminar todos los datos de la cuenta inmediatamente, podés hacerlo abajo. time_in_queue: Esperando en cola %{time} title: Cuentas unconfirmed_email: Correo electrónico sin confirmar + undo_sensitized: Deshacer marcado como sensible undo_silenced: Deshacer silenciado undo_suspension: Deshacer suspensión + unsilenced_msg: Se quitó exitosamente el lÃmite de la cuenta de %{username} unsubscribe: Desuscribirse + unsuspended_msg: Se quitó exitosamente la suspensión de la cuenta de %{username} username: Nombre de usuario + view_domain: Ver resumen del dominio warn: Advertir web: Web - whitelisted: Aprobadas + whitelisted: Permitidas para federación action_logs: action_types: assigned_to_self_report: Asignar denuncia @@ -208,32 +228,37 @@ es-AR: create_domain_allow: Crear permiso de dominio create_domain_block: Crear bloqueo de dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico + create_ip_block: Crear regla de dirección IP demote_user: Descender usuario destroy_announcement: Eliminar anuncio destroy_custom_emoji: Eliminar emoji personalizado destroy_domain_allow: Eliminar permiso de dominio destroy_domain_block: Eliminar bloqueo de dominio destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico - destroy_status: Eliminar estado + destroy_ip_block: Eliminar regla de dirección IP + destroy_status: Eliminar toot disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar emoji personalizado disable_user: Deshabilitar usuario enable_custom_emoji: Habilitar emoji personalizado enable_user: Habilitar usuario - memorialize_account: Volver cuenta conmemorativa + memorialize_account: Convertir en cuenta conmemorativa promote_user: Promover usuario remove_avatar_user: Quitar avatar reopen_report: Reabrir denuncia reset_password_user: Cambiar contraseña resolve_report: Resolver denuncia + sensitive_account: Marcar los medios en tu cuenta como sensibles silence_account: Silenciar cuenta suspend_account: Suspender cuenta unassigned_report: Desasignar denuncia + unsensitive_account: Desmarcar los medios en tu cuenta como sensibles unsilence_account: Dejar de silenciar cuenta unsuspend_account: Dejar de suspender cuenta update_announcement: Actualizar anuncio update_custom_emoji: Actualizar emoji personalizado - update_status: Actualizar estado + update_domain_block: Actualizar bloque de dominio + update_status: Actualizar toot actions: assigned_to_self_report: "%{name} se asignó la denuncia %{target} a sÃ" change_email_user: "%{name} cambió la dirección de correo electrónico del usuario %{target}" @@ -241,36 +266,41 @@ es-AR: create_account_warning: "%{name} envió una advertencia a %{target}" create_announcement: "%{name} creó el nuevo anuncio %{target}" create_custom_emoji: "%{name} subió nuevo emoji %{target}" - create_domain_allow: "%{name} aprobó el dominio %{target}" + create_domain_allow: "%{name} permitió la federación con el dominio %{target}" create_domain_block: "%{name} bloqueó el dominio %{target}" - create_email_domain_block: "%{name} desaprobó el dominio de correo electrónico %{target}" + create_email_domain_block: "%{name} bloqueó el dominio de correo electrónico %{target}" + create_ip_block: "%{name} creó la regla para la dirección IP %{target}" demote_user: "%{name} bajó de nivel al usuario %{target}" destroy_announcement: "%{name} eliminó el anuncio %{target}" destroy_custom_emoji: "%{name} destruyó el emoji %{target}" - destroy_domain_allow: "%{name} quitó el dominio %{target} de los permitidos" + destroy_domain_allow: "%{name} no permitió la federación con el dominio %{target}" destroy_domain_block: "%{name} desbloqueó el dominio %{target}" - destroy_email_domain_block: "%{name} aprobó el dominio de correo electrónico %{target}" - destroy_status: "%{name} eliminó el estado de %{target}" + destroy_email_domain_block: "%{name} desbloqueó el dominio de correo electrónico %{target}" + destroy_ip_block: "%{name} eliminó la regla para la dirección IP %{target}" + destroy_status: "%{name} eliminó el toot de %{target}" disable_2fa_user: "%{name} deshabilitó el requerimiento de dos factores para el usuario %{target}" disable_custom_emoji: "%{name} deshabilitó el emoji %{target}" disable_user: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji: "%{name} habilitó el emoji %{target}" enable_user: "%{name} habilitó el inicio de sesión para el usuario %{target}" - memorialize_account: "%{name} convirtió la cuenta de %{target} en una página de recordatorio" + memorialize_account: "%{name} convirtió la cuenta de %{target} en una cuenta conmemorativa" promote_user: "%{name} promovió al usuario %{target}" remove_avatar_user: "%{name} quitó el avatar de %{target}" reopen_report: "%{name} reabrió la denuncia %{target}" reset_password_user: "%{name} cambió la contraseña del usuario %{target}" resolve_report: "%{name} resolvió la denuncia %{target}" + sensitive_account: "%{name} marcó los medios de %{target} como sensibles" silence_account: "%{name} silenció la cuenta de %{target}" suspend_account: "%{name} suspendió la cuenta de %{target}" unassigned_report: "%{name} desasignó la denuncia %{target}" + unsensitive_account: "%{name} desmarcó los medios de %{target} como sensibles" unsilence_account: "%{name} quitó el silenciado de la cuenta de %{target}" unsuspend_account: "%{name} quitó la suspensión de la cuenta de %{target}" update_announcement: "%{name} actualizó el anuncio %{target}" update_custom_emoji: "%{name} actualizó el emoji %{target}" - update_status: "%{name} actualizó el estado de %{target}" - deleted_status: "(estado borrado)" + update_domain_block: "%{name} actualizó el bloqueo de dominio para %{target}" + update_status: "%{name} actualizó el toot de %{target}" + deleted_status: "[toot eliminado]" empty: No se encontraron registros. filter_by_action: Filtrar por acción filter_by_user: Filtrar por usuario @@ -288,7 +318,7 @@ es-AR: scheduled_for: Programado para %{time} scheduled_msg: "¡Anuncio programado para su publicación!" title: Anuncios - unpublished_msg: "¡Anuncio dejado de publicar exitosamente!" + unpublished_msg: "¡Se dejó de publicar el anuncio exitosamente!" updated_msg: "¡Anuncio actualizado exitosamente!" custom_emojis: assign_category: Asignar categorÃa @@ -308,7 +338,7 @@ es-AR: enabled: Habilitado enabled_msg: Se habilitó ese emoji exitosamente image_hint: PNG de hasta 50KB - list: Lista + list: Listar listed: Listados new: title: Agregar nuevo emoji personalizado @@ -318,7 +348,7 @@ es-AR: shortcode_hint: Al menos 2 caracteres, sólo caracteres alfanuméricos y subguiones ("_") title: Emojis personalizados uncategorized: Sin categorÃa - unlist: No agregar a lista + unlist: No listar unlisted: No listado update_failed_msg: No se pudo actualizar ese emoji updated_msg: "¡Emoji actualizado exitosamente!" @@ -336,26 +366,26 @@ es-AR: feature_timeline_preview: Previsualización de la lÃnea temporal features: Funciones hidden_service: Federación con servicios ocultos - open_reports: abrir denuncias + open_reports: denuncias abiertas pending_tags: etiquetas esperando revisión pending_users: usuarios esperando revisión recent_users: Usuarios recientes search: Búsqueda de texto completo single_user_mode: Modo de usuario único software: Software - space: Uso del espacio + space: Uso de almacenamiento title: Panel total_users: usuarios en total trends: Tendencias week_interactions: interacciones esta semana week_users_active: activos esta semana week_users_new: usuarios esta semana - whitelist_mode: Modo de aprobación + whitelist_mode: Modo de federación limitada domain_allows: - add_new: Aprobar dominio - created_msg: El dominio se aprobó exitosamente - destroyed_msg: El dominio no se aprobó - undo: No aprobado + add_new: Permitir federación con el dominio + created_msg: El dominio fue exitosamente permitido para la federación + destroyed_msg: El dominio no fue permitido para la federación + undo: No permitir federación con el dominio domain_blocks: add_new: Agregar nuevo bloqueo de dominio created_msg: Ahora se está procesando el bloqueo de dominio @@ -372,19 +402,21 @@ es-AR: silence: Silenciar suspend: Suspender title: Nuevo bloqueo de dominio + obfuscate: Obfuscar nombre de dominio + obfuscate_hint: Obfusca parcialmente el nombre de dominio en la lista si el anuncio de la lista de limitaciones de dominio está habilitado private_comment: Comentario privado private_comment_hint: Comentario sobre la limitación de este dominio, para uso interno de los moderadores. public_comment: Comentario público public_comment_hint: Comentario sobre la limitación de este dominio para el público en general, si está habilitada la publicación de lista de limitaciones de dominio. - reject_media: Rechazar archivos de medio - reject_media_hint: Quita los archivos de medio almacenados e impide la descarga en el futuro. Irrelevante para suspensiones. + reject_media: Rechazar archivos de medios + reject_media_hint: Quita los archivos de medios almacenados e impide la descarga en el futuro. Irrelevante para suspensiones reject_reports: Rechazar denuncias - reject_reports_hint: Ignora todas las denuncias que vengan de este dominio. Irrelevante para suspensiones. - rejecting_media: rechazando archivos de medio - rejecting_reports: rechazando denuncias + reject_reports_hint: Ignora todas las denuncias que vengan de este dominio. Irrelevante para suspensiones + rejecting_media: rechazo de archivos de medios + rejecting_reports: rechazo de denuncias severity: - silence: silenciado - suspend: suspendido + silence: silenciados + suspend: suspendidos show: affected_accounts: one: Una cuenta afectada en la base de datos @@ -398,19 +430,20 @@ es-AR: view: Ver bloqueo de dominio email_domain_blocks: add_new: Agregar nuevo - created_msg: Se desaprobó dominio de correo electrónico exitosamente + created_msg: Se bloqueó el dominio de correo electrónico exitosamente delete: Eliminar - destroyed_msg: Se aprobó dominio de correo electrónico exitosamente + destroyed_msg: Se desbloqueó el dominio de correo electrónico exitosamente domain: Dominio - empty: Actualmente no hay dominios de correo electrónico desaprobados. + empty: Actualmente no hay dominios de correo electrónico bloqueados. from_html: de %{domain} new: create: Agregar dominio - title: Nueva desaprobación de correo electrónico - title: Desaprobación de correo electrónico + title: Bloquear nuevo dominio de correo electrónico + title: Dominios bloqueados de correo electrónico instances: by_domain: Dominio delivery_available: La entrega está disponible + empty: No se encontraron dominios. known_accounts: one: "%{count} cuenta conocida" other: "%{count} cuentas conocidas" @@ -422,8 +455,8 @@ es-AR: public_comment: Comentario público title: Federación total_blocked_by_us: Bloqueada por nosotros - total_followed_by_them: Seguidos por ellos - total_followed_by_us: Seguidos por nosotros + total_followed_by_them: Seguidas por ellos + total_followed_by_us: Seguidas por nosotros total_reported: Denuncias sobre ellos total_storage: Adjuntos invites: @@ -434,6 +467,21 @@ es-AR: expired: Vencidas title: Filtrar title: Invitaciones + ip_blocks: + add_new: Crear regla + created_msg: Se agregó exitosamente la nueva regla de dirección IP + delete: Eliminar + expires_in: + '1209600': 2 semanas + '15778476': 6 meses + '2629746': 1 mes + '31556952': 1 año + '86400': 1 dÃa + '94670856': 3 años + new: + title: Crear nueva regla de dirección IP + no_ip_block_selected: No se cambió ninguna regla de dirección IP, ya que no se seleccionó ninguna + title: Reglas de dirección IP pending_accounts: title: Cuentas pendientes (%{count}) relationships: @@ -441,7 +489,7 @@ es-AR: relays: add_new: Agregar nuevo relé delete: Eliminar - description_html: Un <strong>relé de federación</strong> es un servidor intermedio que intercambia grandes volúmenes de toots públicos entre servidores que se suscriben y publican en él. <strong>Puede ayudar a servidores chicos y medianos a descubrir contenido del fediverso</strong>, que de otra manera requerirÃa que los usuarios locales siguiesen manualmente a personas de servidores remotos. + description_html: Un <strong>relé de federación</strong> es un servidor intermedio que intercambia grandes volúmenes de toots públicos entre servidores que se suscriben y publican en él. <strong>Puede ayudar a servidores chicos y medianos a descubrir contenido del fediverso</strong>, que de otra manera requerirÃa que los usuarios locales siguiesen manualmente a cuentas de servidores remotos. disable: Deshabilitar disabled: Deshabilitado enable: Habilitar @@ -451,7 +499,7 @@ es-AR: pending: Esperando aprobación del relé save_and_enable: Guardar y habilitar setup: Configurar una conexión de relé - signatures_not_enabled: Los relés no funcionarán correctamente mientras el modo seguro o el de aprobación estén habilitados + signatures_not_enabled: Los relés no funcionarán correctamente mientras el modo seguro o el de federación limitada estén habilitados status: Estado title: Relés report_notes: @@ -473,6 +521,8 @@ es-AR: comment: none: Ninguno created_at: Denunciado + forwarded: Reenviado + forwarded_to: Reenviado a %{domain} mark_as_resolved: Marcar como resuelta mark_as_unresolved: Marcar como no resuelta notes: @@ -480,9 +530,9 @@ es-AR: create_and_resolve: Resolver con nota create_and_unresolve: Reabrir con nota delete: Eliminar - placeholder: Describà qué acciones se tomaron, o cualquier otra actualización relacionada… + placeholder: Describà qué acciones se tomaron, o cualquier otra actualización relacionada... reopen: Reabrir denuncia - report: 'Denunciar #%{id}' + report: 'Denuncia #%{id}' reported_account: Cuenta denunciada reported_by: Denunciada por resolved: Resueltas @@ -494,7 +544,7 @@ es-AR: updated_at: Actualizada settings: activity_api_enabled: - desc_html: Conteos de estados publicados localmente, usuarios activos y nuevos registros en tandas semanales + desc_html: Conteos de toots publicados localmente, usuarios activos y nuevos registros en tandas semanales title: Publicar estadÃsticas agregadas sobre la actividad del usuario bootstrap_timeline_accounts: desc_html: Separar múltiples nombres de usuario con coma. Sólo funcionarán las cuentas locales y desbloqueadas. Predeterminadamente, cuando está vacÃo todos los administradores locales. @@ -516,32 +566,36 @@ es-AR: domain_blocks_rationale: title: Mostrar razonamiento enable_bootstrap_timeline_accounts: + desc_html: Hacer que los nuevos usuarios sigan automáticamente las cuentas configuradas para que su lÃnea temporal principal no comience vacÃa title: Habilitar seguimientos predeterminados para nuevas cuentas hero: - desc_html: Mostrado en la página principal. Se recomienda un tamaño mÃnimo de 600x100 pÃxeles. Predeterminadamente se establece a la miniatura del servidor. + desc_html: Mostrado en la página principal. Se recomienda un tamaño mÃnimo de 600x100 pÃxeles. Predeterminadamente se establece a la miniatura del servidor title: Imagen de portada mascot: - desc_html: Mostrado en múltiples páginas. Se recomienda un tamaño mÃnimo de 293x205 pÃxeles. Cuando no se especifica, se muestra la mascota predeterminada. + desc_html: Mostrado en múltiples páginas. Se recomienda un tamaño mÃnimo de 293x205 pÃxeles. Cuando no se especifica, se muestra la mascota predeterminada title: Imagen de la mascota peers_api_enabled: desc_html: Nombres de dominio que este servidor encontró en el fediverso title: Publicar lista de servidores descubiertos preview_sensitive_media: - desc_html: Los enlaces de previsualizaciones en otros sitios web mostrarán una miniatura incluso si el medio está marcado como contenido sensible + desc_html: Las previsualizaciones de enlaces en otros sitios web mostrarán una miniatura incluso si el medio está marcado como contenido sensible title: Mostrar medios sensibles en previsualizaciones de OpenGraph profile_directory: desc_html: Permitir que los usuarios puedan ser descubiertos title: Habilitar directorio de perfiles registrations: closed_message: - desc_html: Mostrado en la portada cuando los registros están cerrados. Podés usar etiquetas HTML. - title: Mensaje de registro cerrado + desc_html: Mostrado en la página principal cuando los registros de nuevas cuentas están cerrados. Podés usar etiquetas HTML + title: Mensaje de registro de nuevas cuentas cerrado deletion: - desc_html: Permitor que cualquiera elimine su cuenta + desc_html: Permitir que cualquiera elimine su cuenta title: Abrir eliminación de cuenta min_invite_role: disabled: Nadie title: Permitir invitaciones de + require_invite_text: + desc_html: Cuando los registros requieran aprobación manual, hacé que la solicitud de invitación "¿Por qué querés unirte?" sea obligatoria, en vez de opcional + title: Requerir que los nuevos usuarios llenen un texto de solicitud de invitación registrations_mode: modes: approved: Se requiere aprobación para registrarse @@ -552,26 +606,26 @@ es-AR: desc_html: Cuando está deshabilitado, restringe la lÃnea temporal pública enlazada desde la página de inicio para mostrar sólo contenido local title: Incluir contenido federado en la página de lÃnea temporal pública no autenticada show_staff_badge: - desc_html: Mostrar una insignia de equipo en la página de un usuario - title: Mostrar insignia de equipo + desc_html: Mostrar una insignia de administración en la página de un usuario + title: Mostrar insignia de administración site_description: desc_html: Párrafo introductorio en la API. Describe qué hace especial a este servidor de Mastodon y todo lo demás que sea importante. Podés usar etiquetas HTML, en particular <code><a></code> y <code><em></code>. title: Descripción del servidor site_description_extended: - desc_html: Un buen lugar para tu código de conducta, reglas, guÃas y otras cosas que definen tu servidor. Podés usar etiquets HTML. + desc_html: Un buen lugar para tu código de conducta, reglas, guÃas y otras cosas que definen tu servidor. Podés usar etiquets HTML title: Información extendida personalizada site_short_description: desc_html: Mostrado en la barra lateral y las etiquetas de metadatos. Describe lo que es Mastodon y qué hace especial a este servidor en un solo párrafo. title: Descripción corta del servidor site_terms: - desc_html: Podés escribir tus propias polÃticas de privacidad, términos de servicio u otras legalidades. Podés usar etiquetas HTML. + desc_html: Podés escribir tus propias polÃticas de privacidad, términos de servicio u otras legalidades. Podés usar etiquetas HTML title: Términos de servicio personalizados site_title: Nombre del servidor spam_check_enabled: desc_html: Mastodon puede denunciar automáticamente cuentas que envÃan mensajes no solicitados de forma repetida. PodrÃan haber falsos positivos. title: Automatización antispam thumbnail: - desc_html: Usado para previsualizaciones vÃa OpenGraph y APIs. Se recomienda 1200x630 pÃxeles. + desc_html: Usado para previsualizaciones vÃa OpenGraph y APIs. Se recomienda 1200x630 pÃxeles title: Miniatura del servidor timeline_preview: desc_html: Mostrar enlace a la lÃnea temporal pública en la página de inicio y permitir el acceso a la API a la lÃnea temporal pública sin autenticación @@ -582,7 +636,7 @@ es-AR: title: Permitir que las etiquetas sean tendencia sin revisión previa trends: desc_html: Mostrar públicamente etiquetas previamente revisadas que son tendencia actualmente - title: Etiquetas tendencias + title: Etiquetas en tendencia site_uploads: delete: Eliminar archivo subido destroyed_msg: "¡Subida al sitio eliminada exitosamente!" @@ -597,8 +651,8 @@ es-AR: media: title: Medios no_media: Sin medios - no_status_selected: No se cambió ningún estado ya que ninguno fue seleccionado - title: Estados de la cuenta + no_status_selected: No se cambió ningún toot ya que ninguno fue seleccionado + title: Toots de la cuenta with_media: Con medios tags: accounts_today: Usos únicos de hoy @@ -617,7 +671,7 @@ es-AR: trending_right_now: En tendencia ahora mismo unique_uses_today: "%{count} toots hoy" unreviewed: No revisado - updated_msg: La configuración de la etiqueta se actualizó exitosamente + updated_msg: La configuración de letiqueta se actualizó exitosamente title: Administración warning_presets: add_new: Agregar nuevo @@ -641,13 +695,13 @@ es-AR: deleted_msg: Eliminaste el alias exitosamente. La mudanza de esa cuenta a esta ya no será posible. empty: No tenés alias. hint_html: Si querés mudarte desde otra cuenta a esta, acá podés crear un alias, el cual es necesario antes de empezar a mudar seguidores de la cuenta vieja a esta. Esta acción por sà misma es <strong>inofensiva y reversible</strong>. <strong>La migración de la cuenta se inicia desde la cuenta anterior</strong>. - remove: Desenlazar alias + remove: Desvincular alias appearance: advanced_web_interface: Interface web avanzada advanced_web_interface_hint: 'Si querés hacer uso de todo el ancho de tu pantalla, la interface web avanzada te permite configurar varias columnas diferentes para ver tanta información al mismo tiempo como quieras: "Principal", "Notificaciones", "LÃnea temporal federada", y cualquier número de listas y etiquetas.' animations_and_accessibility: Animaciones y accesibilidad confirmation_dialogs: Diálogos de confirmación - discovery: Descubrimiento + discovery: Descubrà localization: body: Mastodon es localizado por voluntarios. guide_link: https://es.crowdin.com/project/mastodon @@ -663,7 +717,7 @@ es-AR: view_status: Ver estado applications: created: Aplicación creada exitosamente - destroyed: Apicación eliminada exitosamente + destroyed: Aplicación eliminada exitosamente invalid_url: La dirección web ofrecida no es válida regenerate_token: Regenerar clave de acceso token_regenerated: Clave de acceso regenerada exitosamente @@ -675,14 +729,17 @@ es-AR: checkbox_agreement_html: Acepto las <a href="%{rules_path}" target="_blank">reglas del servidor</a> y los <a href="%{terms_path}" target="_blank">términos del servicio</a> checkbox_agreement_without_rules_html: Acepto los <a href="%{terms_path}" target="_blank">términos del servicio</a> delete_account: Eliminar cuenta - delete_account_html: Si querés eliminar tu cuenta, podés <a href="%{path}">seguà por acá</a>. Se te va a pedir una confirmación. + delete_account_html: Si querés eliminar tu cuenta, podés <a href="%{path}">seguir por acá</a>. Se te va a pedir una confirmación. description: prefix_invited_by_user: "¡@%{name} te invita para que te unás a este servidor de Mastodon!" prefix_sign_up: "¡Unite a Mastodon hoy!" - suffix: Con una cuenta vas a poder seguir gente, escribir estados e intercambiar mensajes ¡con usuarios de cualquier servidor de Mastodon y más! + suffix: Con una cuenta vas a poder seguir gente, escribir toots e intercambiar mensajes ¡con usuarios de cualquier servidor de Mastodon y más! didnt_get_confirmation: "¿No recibiste el correo electrónico de confirmación?" + dont_have_your_security_key: "¿No tenés tu llave de seguridad?" forgot_password: "¿Te olvidaste la contraseña?" invalid_reset_password_token: La clave para cambiar la contraseña no es válida o venció. Por favor, solicitá una nueva. + link_to_otp: Ingresá un código de dos factores desde tu dispositivo o un código de recuperación + link_to_webauth: Usá tu dispositivo de llave de seguridad login: Iniciar sesión logout: Cerrar sesión migrate_account: Mudarse a otra cuenta @@ -705,9 +762,11 @@ es-AR: account_status: Estado de la cuenta confirming: Esperando confirmación de correo electrónico. functional: Tu cuenta está totalmente operativa. - pending: Tu solicitud está pendiente de revisión por nuestro equipo. Eso puede tardar algún tiempo. Si se aprueba tu solicitud, vas a recibir un correo electrónico. + pending: Tu solicitud está pendiente de revisión por nuestra administración. Eso puede tardar algún tiempo. Si se aprueba tu solicitud, vas a recibir un correo electrónico. redirecting_to: Tu cuenta se encuentra inactiva porque está siendo redirigida a %{acct}. + too_fast: Formulario enviado demasiado rápido, probá de nuevo. trouble_logging_in: "¿Tenés problemas para iniciar sesión?" + use_security_key: Usar la llave de seguridad authorize_follow: already_following: Ya estás siguiendo a esta cuenta already_requested: Ya enviaste una solicitud de seguimiento a esa cuenta @@ -732,19 +791,20 @@ es-AR: date: formats: default: "%Y.%b.%d" + with_month_name: "%Y.%B.%d" datetime: distance_in_words: about_x_hours: "%{count}h" - about_x_months: "%{count}m" - about_x_years: "%{count}a" - almost_x_years: "%{count}a" + about_x_months: "%{count}M" + about_x_years: "%{count}A" + almost_x_years: "%{count}A" half_a_minute: Recién - less_than_x_minutes: "%{count}m" + less_than_x_minutes: "%{count}min" less_than_x_seconds: Recién - over_x_years: "%{count}a" - x_days: "%{count}d" - x_minutes: "%{count}m" - x_months: "%{count}m" + over_x_years: "%{count}A" + x_days: "%{count}D" + x_minutes: "%{count}min" + x_months: "%{count}M" x_seconds: "%{count}s" deletes: challenge_not_passed: La información que ingresaste no es correcta @@ -778,7 +838,7 @@ es-AR: '422': content: Falló la verificación de seguridad. ¿Estás bloqueando cookies? title: Falló la verificación de seguridad - '429': Asfixiado + '429': Demasiadas solicitudes '500': content: Lo sentimos, pero algo salió mal en nuestro lado. title: Esta página no es correcta @@ -792,14 +852,15 @@ es-AR: date: Fecha download: Descargá tu archivo historial hint_html: Podés solicitar un archivo historial de tus <strong>toots y medios subidos</strong>. Los datos exportados estarán en formato "ActivityPub", legibles por cualquier software compatible. Podés solicitar un archivo historial cada 7 dÃas. - in_progress: Compilando tu archivo historial… + in_progress: Compilando tu archivo historial... request: Solicitá tu archivo historial size: Tamaño - blocks: Tus bloqueos + blocks: Cuentas que bloqueaste + bookmarks: Marcadores csv: CSV domain_blocks: Dominios bloqueados lists: Listas - mutes: Quienes silenciaste + mutes: Cuentas que silenciaste storage: Almacenamiento de medios featured_tags: add_new: Agregar nueva @@ -809,7 +870,7 @@ es-AR: filters: contexts: account: Perfiles - home: LÃnea temporal principal + home: Inicio y listas notifications: Notificaciones public: LÃneas temporales públicas thread: Conversaciones @@ -817,7 +878,7 @@ es-AR: title: Editar filtro errors: invalid_context: Se suministró un contexto no válido o vacÃo - invalid_irreversible: El filtrado irreversible sólo funciona con los contextos de "Principal" o de notificaciones + invalid_irreversible: El filtrado irreversible sólo funciona con los contextos de "Principal" o de "Notificaciones" index: delete: Eliminar empty: No tenés filtros. @@ -863,20 +924,23 @@ es-AR: status: Estado de verificación view_proof: Ver prueba imports: + errors: + over_rows_processing_limit: contiene más de %{count} filas modes: merge: Combinar merge_long: Mantener registros existentes y agregar nuevos overwrite: Sobrescribir overwrite_long: Reemplazar registros actuales con los nuevos - preface: Podés importar ciertos datos que exportaste desde otro servidor, como una lista de las personas que estás siguiendo o bloqueando. + preface: Podés importar ciertos datos que exportaste desde otro servidor, como una lista de las cuentas que estás siguiendo o bloqueando. success: Tus datos se subieron exitosamente y serán procesados en brevedad types: blocking: Lista de bloqueados + bookmarks: Marcadores domain_blocking: Lista de dominios bloqueados following: Lista de seguidos muting: Lista de silenciados upload: Subir - in_memoriam_html: Como recordatorio. + in_memoriam_html: Cuenta conmemorativa. invites: delete: Desactivar expired: Vencidas @@ -904,8 +968,8 @@ es-AR: limit: Alcanzaste el máximo de listas media_attachments: validations: - images_and_video: No se puede adjuntar un video a un estado que ya contenga imágenes - not_ready: No se pueden adjuntar archivos que no terminaron de procesarse. ¡Intentá de nuevo en un rato! + images_and_video: No se puede adjuntar un video a un toot que ya contenga imágenes + not_ready: No se pueden adjuntar archivos que no se han terminado de procesar. ¡Intentá de nuevo en un rato! too_many: No se pueden adjuntar más de 4 archivos migrations: acct: Mudada a @@ -955,10 +1019,10 @@ es-AR: subject: one: "1 nueva notificación desde tu última visita \U0001F418" other: "%{count} nuevas notificaciones desde tu última visita \U0001F418" - title: En tu ausencia… + title: En tu ausencia... favourite: - body: 'Tu estado fue marcado como favorito por %{name}:' - subject: "%{name} marcó como favorito tu estado" + body: 'Tu toot fue marcado como favorito por %{name}:' + subject: "%{name} marcó tu toot como favorito" title: Nuevo favorito follow: body: "¡%{name} te está siguiendo!" @@ -975,8 +1039,8 @@ es-AR: subject: Fuiste mencionado por %{name} title: Nueva mención reblog: - body: "%{name} retooteó tu estado:" - subject: "%{name} retooteó tu estado" + body: "%{name} retooteó tu toot:" + subject: "%{name} retooteó tu toot" title: Nuevo retoot notifications: email_events: Eventos para notificaciones por correo electrónico @@ -987,11 +1051,19 @@ es-AR: decimal_units: format: "%n%u" units: - billion: B + billion: MM million: M - quadrillion: Q + quadrillion: C thousand: m trillion: T + otp_authentication: + code_hint: Ingresá el código generado por tu aplicación de autenticación para confirmar + description_html: Si habilitás la <strong>autenticación de dos factores</strong> usando una aplicación de autenticación, entonces en el inicio de sesión se te pedirá que estés con tu dispositivo, el cual generará un código numérico ("token") para que lo ingresés. + enable: Habilitar + instructions_html: <strong>Escaneá este código QR en Authy, Google Authenticator o en otra aplicación TOTP en tu dispositivo</strong>. A partir de ahora, esa aplicación generará un código numérico ("token") para que lo ingresés. + manual_instructions: 'Si no podés escanear el código QR y necesitás ingresarlo manualmente, acá está el secreto en texto plano:' + setup: Configurar + wrong_code: "¡El código ingresado no es válido! ¿La hora del servidor y del dispositivo son correctas?" pagination: newer: Más recientes next: Siguiente @@ -1010,7 +1082,7 @@ es-AR: too_few_options: debe tener más de un elemento too_many_options: no puede contener más de %{max} elementos preferences: - other: Otros + other: Otras opciones posting_defaults: Configuración predeterminada de publicaciones public_timelines: LÃneas temporales públicas reactions: @@ -1020,13 +1092,14 @@ es-AR: relationships: activity: Actividad de la cuenta dormant: Inactivas + follow_selected_followers: Seguir a los seguidores seleccionados followers: Seguidores following: Siguiendo invited: Invitado last_active: Última actividad most_recent: Más reciente moved: Mudada - mutual: Mutuo + mutual: Mutua primary: Principal relationship: Relación remove_selected_domains: Quitar todos los seguidores de los dominios seleccionados @@ -1036,10 +1109,10 @@ es-AR: remote_follow: acct: Ingresá tu usuario@dominio desde el que querés seguir missing_resource: No se pudo encontrar la dirección web de redireccionamiento requerida para tu cuenta - no_account_html: "¿No tenés cuenta? Podés <a href='%{sign_up_path}' target='_blank'>registrarte acá</a>." + no_account_html: "¿No tenés cuenta? Podés <a href='%{sign_up_path}' target='_blank'>registrarte acá</a>" proceed: Proceder para seguir prompt: 'Vas a seguir a:' - reason_html: "¿<strong>¿Por qué es necesario este paso?</strong> <code>%{instance}</code> puede que no sea el servidor donde estás registrado, asà que necesitamos redirigirte primero a tu servidor de origen." + reason_html: "<strong>¿Por qué es necesario este paso?</strong> <code>%{instance}</code> puede que no sea el servidor donde estás registrado, asà que necesitamos redirigirte primero a tu servidor de origen." remote_interaction: favourite: proceed: Proceder para marcar como favorito @@ -1063,15 +1136,15 @@ es-AR: chrome: Chrome edge: Edge electron: Electron - firefox: Firefox - generic: Navegador web desconocido + firefox: Mozilla Firefox + generic: "[Navegador web desconocido]" ie: Internet Explorer micro_messenger: MicroMessenger nokia: Navegador web de Nokia S40 Ovi opera: Opera otter: Otter phantom_js: PhantomJS - qq: Navegador QQ + qq: QQ Browser safari: Safari uc_browser: UC Browser weibo: Weibo @@ -1083,12 +1156,12 @@ es-AR: adobe_air: Adobe Air android: Android blackberry: BlackBerry - chrome_os: ChromeOS + chrome_os: Chrome OS firefox_os: Firefox OS ios: iOS linux: GNU/Linux mac: macOS - other: plataforma desconocida + other: "[Plataforma desconocida]" windows: Windows windows_mobile: Windows Mobile windows_phone: Windows Phone @@ -1105,7 +1178,7 @@ es-AR: delete: Eliminación de la cuenta development: Desarrollo edit_profile: Editar perfil - export: Exportar datos + export: Exportación de datos featured_tags: Etiquetas destacadas identity_proofs: Pruebas de identidad import: Importar @@ -1116,6 +1189,7 @@ es-AR: profile: Perfil relationships: Seguimientos two_factor_authentication: Autenticación de dos factores + webauthn_authentication: Llaves de seguridad spam_check: spam_detected: Este es un informe automatizado. Se detectó spam. statuses: @@ -1136,7 +1210,7 @@ es-AR: one: 'contenÃa una etiqueta no permitida: %{tags}' other: 'contenÃa las etiquetas no permitidas: %{tags}' errors: - in_reply_not_found: El estado al que intentás responder no existe. + in_reply_not_found: El toot al que intentás responder no existe. language_detection: Detectar idioma automáticamente open_in_web: Abrir en web over_character_limit: se excedió el lÃmite de %{max} caracteres @@ -1154,13 +1228,15 @@ es-AR: other: "%{count} votos" vote: Votar show_more: Mostrar más + show_newer: Mostrar más recientes + show_older: Mostrar más antiguos show_thread: Mostrar hilo sign_in_to_participate: Iniciá sesión para participar en la conversación title: '%{name}: "%{quote}"' visibilities: private: Sólo a seguidores private_long: Sólo mostrar a seguidores - public: Pública + public: Público public_long: Todos pueden ver unlisted: No listado unlisted_long: Todos pueden ver, pero no está listado en las lÃneas temporales públicas @@ -1177,7 +1253,7 @@ es-AR: <ul> <li><em>Información básica de la cuenta</em>: Si te registrás en este servidor, se te va a pedir un nombre de usuario, una dirección de correo electrónico y una contraseña. También podés ingresar información adicional de perfil como un nombre para mostrar y una biografÃa, y subir un avatar y una imagen de cabecera. El nombre de usuario, nombre para mostrar, biografÃa, avatar e imagen de cabecera siempre son visibles públicamente.</li> - <li><em>Toots, seguimiento y otra información pública</em>: La lista de gente a la que seguÃs es mostrada públicamente, al igual que la de tus seguidores. Cuando enviás un mensaje, se almacenan la fecha y hora, asà como la aplicación desde la cual enviaste el mensaje. Los mensajes pueden contener archivos adjuntos de medios, como imágenes y videos. Los toots públicos y no listados están técnicamente disponibles para todos. Cuando destacás un toot en tu perfil, eso también se considera información disponible públicamente. Tus toots son entregados a tus seguidores, en algunos casos significa que son entregados a diferentes servidores y las copias son almacenadas allÃ. Cuando eliminás toots, esto también afecta a tus seguidores. La acción de retootear o marcar como favorito otro toot es siempre pública.</li> + <li><em>Toots, seguimiento y otra información pública</em>: La lista de gente a la que seguÃs es mostrada públicamente, al igual que la de tus seguidores. Cuando enviás un mensaje, se almacenan la fecha y hora, asà como la aplicación desde la cual enviaste el mensaje. Los mensajes pueden contener archivos adjuntos de medios, como imágenes y videos. Los toots públicos y no listados están técnicamente disponibles para todos. Cuando destacás un toot en tu perfil, eso también se considera información disponible públicamente. Tus toots son entregados a tus seguidores; en algunos casos significa que son entregados a diferentes servidores y las copias son almacenadas allÃ. Cuando eliminás toots, esto también afecta a tus seguidores. La acción de retootear o marcar como favorito otro toot es siempre pública.</li> <li><em>Toots directos y sólo para seguidores</em>: Todos los toots se almacenan y procesan en el servidor. Los toots sólo para seguidores se entregan a los seguidores y usuarios que se mencionan en ellos, y los mensajes directos se entregan sólo a los usuarios que se mencionan en ellos. En algunos casos significa que se entregan a diferentes servidores y que las copias se almacenan allÃ. Hacemos un esfuerzo de buena fe para limitar el acceso a esos toots sólo a las personas autorizadas, pero otros servidores pueden no hacerlo. Por lo tanto, es importante revisar los servidores a los que pertenecen tus seguidores. Podés cambiar una opción para aprobar y rechazar nuevos seguidores manualmente en la configuración. <em>Por favor, tené en cuenta que los operadores del servidor y de cualquier servidor receptor pueden ver dichos mensajes</em>, y que los destinatarios pueden tomar capturas de pantalla, copiarlos o volver a compartirlos de alguna otra manera. <em>No compartas ninguna información peligrosa en Mastodon.</em></li> <li><em>Direcciones IP y otros metadatos</em>: Cuando iniciás sesión, registramos la dirección IP desde dónde lo estás haciendo, asà como el nombre de tu navegador web. Todos los inicios de sesiones están disponibles para tu revisión y revocación en la configuración. La última dirección IP usada se almacena hasta por 12 meses. También podemos conservar los registros del servidor que incluyen la dirección IP de cada solicitud a nuestro servidor.</li> </ul> @@ -1189,7 +1265,7 @@ es-AR: <p>Toda la información que recolectamos de vos puede ser usada de las siguientes maneras:</p> <ul> - <li>Para proporcionar la funcionalidad principal de Mastodon. Sólo puedes interactuar con el contenido de otras personas y publicar tu propio contenido cuando hayás iniciado sesión. Por ejemplo, podés seguir a otras personas para ver sus mensajes combinados en tu propia lÃnea temporal personalizada.</li> + <li>Para proporcionar la funcionalidad principal de Mastodon. Sólo podés interactuar con el contenido de otras personas y publicar tu propio contenido cuando hayás iniciado sesión. Por ejemplo, podés seguir a otras personas para ver sus mensajes combinados en tu propia lÃnea temporal personalizada.</li> <li>Para ayudar a la moderación de la comunidad, por ejemplo, comparando tu dirección IP con otras conocidas para determinar la evasión de prohibiciones u otras violaciones.</li> <li>La dirección de correo electrónico que nos proporcionés podrÃa usarse para enviarte información, notificaciones sobre otras personas que interactúen con tu contenido o para enviarte mensajes, asà como para responder a consultas y/u otras solicitudes o preguntas.</li> </ul> @@ -1198,20 +1274,20 @@ es-AR: <h3 id="protect">¿Cómo protegemos tu información?</h3> - <p>Implementamos una variedad de medidas de seguridad para mantener la seguridad de tu información personal cuando ingresás, enviás o accedés a tu información personal. Entre otras cosas, la sesión de tu navegador web, asà como el tráfico entre sus aplicaciones y la API, están protegidos con SSL; y tu contraseña está protegida mediante un algoritmo unidireccional fuerte. Podés habilitar la autenticación de dos factores para un acceso más seguro a tu cuenta.</p> + <p>Implementamos una variedad de medidas de seguridad para mantener la seguridad de tu información personal cuando ingresás, enviás o accedés a tu información personal. Entre otras cosas, la sesión de tu navegador web, asà como el tráfico entre sus aplicaciones y la API, están protegidos con SSL; y tu contraseña está protegida mediante un algoritmo unidireccional fuerte. Podés habilitar la autenticación de dos factores para obtener un acceso más seguro a tu cuenta.</p> <hr class="spacer" /> <h3 id="data-retention">¿Cuál es nuestra polÃtica de retención de datos?</h3> - <p>Haremos un esfuerzo de buena fe para:</p> + <p>Hacemos un esfuerzo de buena fe para:</p> <ul> <li>Conservar los registros del servidor que contengan la dirección IP de todas las solicitudes a este servidor, en la medida en que se mantengan dichos registros, por no más de 90 dÃas.</li> <li>Conservar las direcciones IP asociadas a los usuarios registrados, por no más de 12 meses.</li> </ul> - <p>Podé solicitar y descargar un archivo historial de tu contenido, incluyendo tus toots, archivos adjuntos de medios, avatar e imagen de cabecera.</p> + <p>Podés solicitar y descargar un archivo historial de tu contenido, incluyendo tus toots, archivos adjuntos de medios, avatar e imagen de cabecera.</p> <p>Podés eliminar tu cuenta de forma irreversible en cualquier momento.</p> @@ -1219,7 +1295,7 @@ es-AR: <h3 id="cookies">¿Usamos cookies?</h3> - <p>SÃ. Las cookies son pequeños archivos que un sitio o su proveedor de servicios transfiere a la unidad de almacenamiento de tu computadora a través de tu navegador web (si lo permitÃs). Estas cookies permiten al sitio reconocer tu navegador web y, si tenés una cuenta registrada, asociarla con la misma.</p> + <p>SÃ. Las cookies son pequeños archivos que un sitio o su proveedor de servicios transfiere a la unidad de almacenamiento de tu computadora a través de tu navegador web (si asà lo permitÃs). Estas cookies permiten al sitio reconocer tu navegador web y, si tenés una cuenta registrada, asociarla con la misma.</p> <p>Usamos cookies para entender y guardar tu configuración para futuras visitas.</p> @@ -1229,7 +1305,7 @@ es-AR: <p>No vendemos, comercializamos ni transferimos de ninguna otra manera a terceros tu información personal identificable. Esto no incluye a los terceros de confianza que nos asisten en la operación de nuestro sitio, en la realización de nuestros negocios o en la prestación de servicios, siempre y cuando dichas partes acuerden mantener la confidencialidad de esta información. También podrÃamos liberar tu información cuando creamos que es apropiado para cumplir con la ley, hacer cumplir las polÃticas de nuestro sitio web, o proteger derechos, propiedad o seguridad, nuestros o de otros.</p> - <p>Tu contenido público puede ser descargado por otros servidores de la red. Tus mensajes públicos y sólo para seguidores se envÃan a los servidores donde residen tus seguidores, y los mensajes directos se envÃan a los servidores de los destinatarios, en la medida en que dichos seguidores o destinatarios residan en un servidor diferente.</p> + <p>Tu contenido público puede ser descargado por otros servidores de la red. Tus mensajes públicos y tus mensajes sólo para seguidores se envÃan a los servidores donde residen tus seguidores, y los mensajes directos se envÃan a los servidores de los destinatarios, en la medida en que dichos seguidores o destinatarios residan en un servidor diferente.</p> <p>Cuando autorizás a una aplicación a usar tu cuenta, dependiendo del alcance de los permisos que aprobés, puede acceder a la información de tu perfil público, tu lista de seguimiento, tus seguidores, tus listas, todos tus mensajes y tus favoritos. Las aplicaciones nunca podrán acceder a tu dirección de correo electrónico o contraseña.</p> @@ -1237,9 +1313,9 @@ es-AR: <h3 id="children">Uso del sitio web por parte de niños</h3> - <p>Si este servidor está en la UE o en el EEE: Nuestro sitio web, productos y servicios están dirigidos a personas mayores de 16 años. Si tenés menos de 16 años, según los requisitos de la GDPR (<a href="https://es.wikipedia.org/wiki/Reglamento_General_de_Protecci%C3%B3n_de_Datos">Reglamento General de Protección de Datos</a>) no usés este sitio.</p> + <p>Si este servidor está en la UE o en el EEE: Nuestro sitio web, productos y servicios están dirigidos a personas mayores de 16 años. Si tenés menos de 16 años, según los requisitos de la GDPR (<a href="https://es.wikipedia.org/wiki/Reglamento_General_de_Protecci%C3%B3n_de_Datos">Reglamento General de Protección de Datos</a>) entonces, por favor, no usés este sitio web.</p> - <p>Si este servidor está en los EE.UU.: Nuestro sitio web, productos y servicios están todos dirigidos a personas que tienen al menos 13 años de edad. Si tenés menos de 13 años, según los requisitos de COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Acta de Protección de la Privacidad en LÃnea de Niños [en inglés]</a>) no usés este sitio.</p> + <p>Si este servidor está en los EE.UU.: Nuestro sitio web, productos y servicios están dirigidos a personas que tienen al menos 13 años de edad. Si tenés menos de 13 años, según los requisitos de COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Acta de Protección de la Privacidad en LÃnea de Niños [en inglés]</a>) entonces, por favor, no usés este sitio web.</p> <p>Los requisitos legales pueden ser diferentes si este servidor está en otra jurisdicción.</p> @@ -1260,23 +1336,22 @@ es-AR: time: formats: default: "%Y.%b.%d, %H:%M" - month: "%b %Y" + month: "%b de %Y" two_factor_authentication: - code_hint: Ingresá el código generado por tu aplicación de autenticación para confirmar - description_html: Si habilitás la <strong>autenticación de dos factores</strong>, se requerirá estar en posesión de tu dispositivo móvil, lo que generará claves para que las ingresés. - disable: Deshabilitar - enable: Habilitar + add: Agregar + disable: Deshabilitar 2FA + disabled_success: Autenticación de dos factores exitosamente deshabilitada + edit: Editar enabled: La autenticación de dos factores está activada enabled_success: Se habilitó exitosamente la autenticación de dos factores generate_recovery_codes: Generar códigos de recuperación - instructions_html: <strong>Escaneá este código QR con Authy, FreeOTP, Google Authenticator, Microsoft Authenticator o cualquier otra aplicación de generación de contraseñas por única vez basada en el tiempo ("TOTP") en tu dispositivo móvil</strong>. Desde ahora, esta aplicación va a generar claves que tenés que ingresar cuando quieras iniciar sesión. - lost_recovery_codes: Los códigos de recuperación te permiten recuperar el acceso a tu cuenta, si perdés tu dispositivo móvil. Si perdiste tus códigos de recuperación, podés regenerarlos acá. Tus antiguos códigos de recuperación serán invalidados. - manual_instructions: 'Si no podés escanear el código QR y necesitás introducirlo manualmente, este es el secreto en texto plano:' + lost_recovery_codes: Los códigos de recuperación te permiten recuperar el acceso a tu cuenta, si no tenés acceso a la aplicación de 2FA. Si perdiste tus códigos de recuperación, podés regenerarlos acá. Tus antiguos códigos de recuperación serán invalidados. + methods: Métodos de dos factores + otp: Aplicación de autenticación recovery_codes: Resguardar códigos de recuperación recovery_codes_regenerated: Los códigos de recuperación se regeneraron exitosamente - recovery_instructions_html: Si alguna vez perdés el acceso a tu dispositivo móvil, podés usar uno de los siguientes códigos de recuperación para recuperar el acceso a tu cuenta. <strong>Mantenelos a salvo</strong>. Por ejemplo, podés imprimirlos y guardarlos con otros documentos importantes. - setup: Configurar - wrong_code: "¡El código ingresado no es válido! ¿La hora en el dispositivo y en el servidor es correcta?" + recovery_instructions_html: Si alguna vez perdés el acceso a tu aplicación de 2FA, podés usar uno de los siguientes códigos de recuperación para recuperar el acceso a tu cuenta. <strong>Mantenelos a salvo</strong>. Por ejemplo, podés imprimirlos y guardarlos con otros documentos importantes. + webauthn: Llaves de seguridad user_mailer: backup_ready: explanation: Solicitado un resguardo completo de tu cuenta de Mastodon. ¡Ya está listo para descargar! @@ -1290,25 +1365,28 @@ es-AR: title: Intento de inicio de sesión warning: explanation: - disable: Mientras tu cuenta esté congelada, la información de la misma permanecerá intacta, pero no podés realizar ninguna acción hasta que se desbloquee. - silence: Mientras tu cuenta esté limitada, sólo las personas que ya te estén siguiendo verán tus toots en este servidor, y puede que se te excluya de varios listados públicos. Sin embargo, otras personas pueden seguirte manualmente. - suspend: Tu cuenta fue suspendida, y todos tus toots y tus archivos de medios subidos fueron irreversiblemente eliminados de este servidor, y de los servidores en donde tenÃas seguidores. - get_in_touch: Podés responder a esta dirección de correo electrónico para ponerte en contacto con el equipo de %{instance}. + disable: Ya no podés iniciar sesión en tu cuenta o usarla de alguna manera, pero tu perfil y otros datos permanecen intactos. + sensitive: Tus archivos de medios subidos y enlaces de medios serán tratados como sensibles. + silence: TodavÃa podés usar tu cuenta, pero sólo las personas que ya te estén siguiendo verán tus toots en este servidor, y puede que se te excluya de varios listados públicos. Sin embargo, otras personas pueden seguirte manualmente. + suspend: Ya no podés usar tu cuenta; tu perfil y otros datos ya no son accesibles. TodavÃa podés iniciar sesión para solicitar un resguardo de tus datos hasta que los mismos sean totalmente quitados, pero retendremos ciertos datos para prevenirte de evadir la suspensión. + get_in_touch: Podés responder a esta dirección de correo electrónico para ponerte en contacto con la administración de %{instance}. review_server_policies: Revisar las polÃticas del servidor statuses: 'EspecÃficamente, para:' subject: disable: Tu cuenta %{acct} fue congelada none: Advertencia para %{acct} + sensitive: Los toots con medios de tu cuenta %{acct} fueron marcados como sensibles silence: Tu cuenta %{acct} fue limitada suspend: Tu cuenta %{acct} fue suspendida title: disable: Cuenta congelada none: Advertencia + sensitive: Tus medios fueron marcados como sensibles silence: Cuenta limitada suspend: Cuenta suspendida welcome: edit_profile_action: Configurar perfil - edit_profile_step: Podés personalizar tu perfil subiendo un avatar, una cabecera, cambiando tu nombre para mostrar y más cosas. Si querés revisar a tus nuevos seguidores antes de que se les permita seguirte, podés bloquear tu cuenta. + edit_profile_step: Podés personalizar tu perfil subiendo un avatar, una cabecera, cambiando tu nombre para mostrar y más cosas. Si querés revisar a tus nuevos seguidores antes de que se les permita seguirte, podés bloquear tu cuenta (esto es, hacerla privada). explanation: Aquà hay algunos consejos para empezar final_action: Empezar a tootear final_step: ¡Empezá a tootear! Incluso sin seguidores, tus mensajes públicos pueden ser vistos por otros, por ejemplo en la linea temporal local y con etiquetas. Capaz que quieras presentarte al mundo con la etiqueta "#presentación". @@ -1320,13 +1398,15 @@ es-AR: tip_federated_timeline: La lÃnea temporal federada es una lÃnea contÃnua global de la red de Mastodon. Pero sólo incluye gente que tus vecinos están siguiendo, asà que no es completa. tip_following: Predeterminadamente seguÃs al / a los administrador/es de tu servidor. Para encontrar más gente interesante, revisá las lineas temporales local y federada. tip_local_timeline: La lÃnea temporal local es una lÃnea contÃnua global de cuentas en %{instance}. ¡Estos son tus vecinos inmediatos! - tip_mobile_webapp: Si tu navegador web móvil te ofrece agregar Mastodon a tu página de inicio, podés recibir notificaciones PuSH. ¡Actúa como una aplicación nativa de muchas maneras! + tip_mobile_webapp: Si tu navegador web móvil te ofrece agregar Mastodon a tu página de inicio, podés recibir notificaciones push. ¡Actúa como una aplicación nativa de muchas maneras! tips: Consejos title: "¡Bienvenido a bordo, %{name}!" users: - follow_limit_reached: No podés seguir a más de %{limit} personas + blocked_email_provider: No está permitido este proveedor de correo electrónico + follow_limit_reached: No podés seguir a más de %{limit} cuentas generic_access_help_html: "¿Tenés problemas para acceder a tu cuenta? Podés ponerte en contacto con %{email} para obtener ayuda" - invalid_email: La dirección de correo electrónico no es correcta + invalid_email: La dirección de correo electrónico no es válida + invalid_email_mx: Parece que esta dirección de correo electrónico no existe invalid_otp_token: Código de dos factores no válido invalid_sign_in_token: Código de seguridad no válido otp_lost_help_html: Si perdiste al acceso a ambos, podés ponerte en contacto con %{email} @@ -1336,3 +1416,20 @@ es-AR: verification: explanation_html: 'Podés <strong>verificarte a vos mismo como el propietario de los enlaces en los metadatos de tu perfil</strong>. Para eso, el sitio web del enlace debe contener un enlace de vuelta a tu perfil de Mastodon. El enlace en tu sitio <strong>debe</strong> tener un atributo <code>rel="me"</code>. El contenido del texto del enlace no importa. Acá tenés un ejemplo:' verification: Verificación + webauthn_credentials: + add: Agregar nueva llave de seguridad + create: + error: Hubo un problema al agregar tu llave de seguridad. Por favor, intentá de nuevo. + success: Se agregó exitosamente tu llave de seguridad. + delete: Eliminar + delete_confirmation: "¿Estás seguro que querés eliminar esta llave de seguridad?" + description_html: Si habilitás la <strong>autenticación de llave de seguridad</strong>, entonces en el inicio de sesión se te pedirá que usés una de tus llaves de seguridad. + destroy: + error: Hubo un problema al eliminar tu llave de seguridad. Por favor, intentá de nuevo. + success: Se eliminó exitosamente tu llave de seguridad. + invalid_credential: Llave de seguridad no válida + nickname_hint: Ingresá el apodo de tu nueva llave de seguridad + not_enabled: TodavÃa no habilitaste WebAuthn + not_supported: Este navegador web no soporta llaves de seguridad + otp_required: Para usar llaves de seguridad, por favor, primero habilitá la autenticación de dos factores. + registered_on: Registrado el %{date} diff --git a/config/locales/es.yml b/config/locales/es.yml index a87088cbb41a318e3e9265ab04b91056ee8b3425..0582fd1f1b9363b988efdd04cd93bf3b9d1b8143 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -60,6 +60,7 @@ es: one: Seguidor other: Seguidores following: Siguiendo + instance_actor_flash: Esta cuenta es un actor virtual utilizado para representar al servidor en sà mismo y no a ningún usuario individual. Se utiliza para propósitos de la federación y no se debe suspender. joined: Se unió el %{date} last_active: última conexión link_verified_on: La propiedad de este vÃnculo fue verificada el %{date} @@ -98,6 +99,7 @@ es: add_email_domain_block: Poner en lista negra el dominio del correo approve: Aprobar approve_all: Aprobar todos + approved_msg: La solicitud de registro de %{username} ha sido aprobada correctamente are_you_sure: "¿Estás seguro?" avatar: Avatar by_domain: Dominio @@ -111,8 +113,10 @@ es: confirm: Confirmar confirmed: Confirmado confirming: Confirmando + delete: Eliminar datos deleted: Borrado demote: Degradar + destroyed_msg: Los datos de %{username} están ahora en cola para ser eliminados inminentemente disable: Deshabilitar disable_two_factor_authentication: Desactivar autenticación de dos factores disabled: Deshabilitada @@ -123,10 +127,12 @@ es: email_status: E-mail Status enable: Habilitar enabled: Habilitada + enabled_msg: Se ha descongelado correctamente la cuenta de %{username} followers: Seguidores follows: Sigue header: Cabecera inbox_url: URL de la bandeja de entrada + invite_request_text: Razones para unirse invited_by: Invitado por ip: IP joined: Unido @@ -138,6 +144,8 @@ es: login_status: Estado del login media_attachments: Multimedia memorialize: Convertir en memorial + memorialized: Cuenta conmemorativa + memorialized_msg: "%{username} se convirtió con éxito en una cuenta conmemorativa" moderation: active: Activo all: Todos @@ -158,10 +166,14 @@ es: public: Público push_subscription_expires: Expiración de la suscripción PuSH redownload: Refrescar avatar + redownloaded_msg: Se actualizó correctamente el perfil de %{username} desde el origen reject: Rechazar reject_all: Rechazar todos + rejected_msg: La solicitud de registro de %{username} ha sido rechazada con éxito remove_avatar: Eliminar el avatar remove_header: Eliminar cabecera + removed_avatar_msg: Se ha eliminado exitosamente la imagen del avatar de %{username} + removed_header_msg: Se ha eliminado con éxito la imagen de cabecera de %{username} resend_confirmation: already_confirmed: Este usuario ya está confirmado send: Reenviar el correo electrónico de confirmación @@ -178,6 +190,8 @@ es: search: Buscar search_same_email_domain: Otros usuarios con el mismo dominio de correo search_same_ip: Otros usuarios con la misma IP + sensitive: Sensible + sensitized: marcado como sensible shared_inbox_url: URL de bandeja compartida show: created_reports: Reportes hechos por esta cuenta @@ -187,13 +201,19 @@ es: statuses: Estados subscribe: Suscribir suspended: Suspendido + suspension_irreversible: Los datos de esta cuenta han sido irreversiblemente eliminados. Puedes deshacer la suspensión de la cuenta para hacerla utilizable, pero no recuperará los datos que tenÃas anteriormente. + suspension_reversible_hint_html: La cuenta ha sido suspendida y los datos se eliminarán completamente el %{date}. Hasta entonces, la cuenta puede ser restaurada sin ningún efecto perjudicial. Si desea eliminar todos los datos de la cuenta inmediatamente, puede hacerlo a continuación. time_in_queue: Esperando en cola %{time} title: Cuentas unconfirmed_email: Correo electrónico sin confirmar + undo_sensitized: Desmarcar como sensible undo_silenced: Des-silenciar undo_suspension: Des-suspender + unsilenced_msg: Se quitó con éxito el lÃmite de la cuenta %{username} unsubscribe: Desuscribir + unsuspended_msg: Se quitó con éxito la suspensión de la cuenta de %{username} username: Nombre de usuario + view_domain: Ver resumen del dominio warn: Adevertir web: Web whitelisted: Añadido a la lista blanca @@ -208,12 +228,14 @@ es: create_domain_allow: Crear Permiso de Dominio create_domain_block: Crear Bloqueo de Dominio create_email_domain_block: Crear Bloqueo de Dominio de Correo Electrónico + create_ip_block: Crear regla IP demote_user: Degradar Usuario destroy_announcement: Eliminar Anuncio destroy_custom_emoji: Eliminar Emoji Personalizado destroy_domain_allow: Eliminar Permiso de Dominio destroy_domain_block: Eliminar Bloqueo de Dominio destroy_email_domain_block: Eliminar Bloqueo de Dominio de Correo Electrónico + destroy_ip_block: Eliminar regla IP destroy_status: Eliminar Estado disable_2fa_user: Deshabilitar 2FA disable_custom_emoji: Deshabilitar Emoji Personalizado @@ -226,13 +248,16 @@ es: reopen_report: Reabrir Reporte reset_password_user: Restablecer Contraseña resolve_report: Resolver Reporte + sensitive_account: Marcar multimedia en tu cuenta como sensible silence_account: Silenciar Cuenta suspend_account: Suspender Cuenta unassigned_report: Desasignar Reporte + unsensitive_account: Desmarcar multimedia en tu cuenta como sensible unsilence_account: Dejar de Silenciar Cuenta unsuspend_account: Dejar de Suspender Cuenta update_announcement: Actualizar Anuncio update_custom_emoji: Actualizar Emoji Personalizado + update_domain_block: Actualizar el Bloqueo de Dominio update_status: Actualizar Estado actions: assigned_to_self_report: "%{name} se ha asignado la denuncia %{target} a sà mismo" @@ -244,12 +269,14 @@ es: create_domain_allow: "%{name} ha añadido a la lista blanca el dominio %{target}" create_domain_block: "%{name} bloqueó el dominio %{target}" create_email_domain_block: "%{name} puso en lista negra el dominio de correos %{target}" + create_ip_block: "%{name} creó la regla para la IP %{target}" demote_user: "%{name} degradó al usuario %{target}" destroy_announcement: "%{name} eliminó el anuncio %{target}" destroy_custom_emoji: "%{name} destruyó el emoji %{target}" destroy_domain_allow: "%{name} ha eliminado el dominio %{target} de la lista blanca" destroy_domain_block: "%{name} desbloqueó el dominio %{target}" destroy_email_domain_block: "%{name} puso en lista blanca el dominio de correos %{target}" + destroy_ip_block: "%{name} eliminó la regla para la IP %{target}" destroy_status: "%{name} eliminó el estado de %{target}" disable_2fa_user: "%{name} deshabilitó el requerimiento de dos factores para el usuario %{target}" disable_custom_emoji: "%{name} deshabilitó el emoji %{target}" @@ -262,13 +289,16 @@ es: reopen_report: "%{name} ha reabierto la denuncia %{target}" reset_password_user: "%{name} restauró la contraseña del usuario %{target}" resolve_report: "%{name} ha resuelto la denuncia %{target}" + sensitive_account: "%{name} marcó multimedia de %{target} como sensible" silence_account: "%{name} silenció la cuenta de %{target}" suspend_account: "%{name} suspendió la cuenta de %{target}" unassigned_report: "%{name} ha desasignado la denuncia %{target}" + unsensitive_account: "%{name} desmarcó multimedia de %{target} como sensible" unsilence_account: "%{name} desactivó el silenciado de la cuenta de %{target}" unsuspend_account: "%{name} desactivó la suspensión de la cuenta de %{target}" update_announcement: "%{name} actualizó el anuncio %{target}" update_custom_emoji: "%{name} actualizó el emoji %{target}" + update_domain_block: "%{name} actualizó el bloqueo de dominio para %{target}" update_status: "%{name} actualizó el estado de %{target}" deleted_status: "(estado borrado)" empty: No se encontraron registros. @@ -372,6 +402,8 @@ es: silence: Silenciar suspend: Suspender title: Nuevo bloque de dominio + obfuscate: Ocultar nombre de dominio + obfuscate_hint: Oculta parcialmente el nombre de dominio en la lista si mostrar la lista de limitaciones de dominio está habilitado private_comment: Comentario privado private_comment_hint: Comentario sobre esta limitación de dominio para el uso interno por parte de los moderadores. public_comment: Comentario público @@ -411,6 +443,7 @@ es: instances: by_domain: Dominio delivery_available: Entrega disponible + empty: No se encontraron dominios. known_accounts: one: "%{count} cuenta conocida" other: "%{count} cuentas conocidas" @@ -434,6 +467,21 @@ es: expired: Expiradas title: Filtrar title: Invitaciones + ip_blocks: + add_new: Crear regla + created_msg: Nueva regla IP añadida con éxito + delete: Eliminar + expires_in: + '1209600': 2 semanas + '15778476': 6 meses + '2629746': 1 mes + '31556952': 1 año + '86400': 1 dÃa + '94670856': 3 años + new: + title: Crear nueva regla IP + no_ip_block_selected: No se han cambiado reglas IP ya que no se ha seleccionado ninguna + title: Reglas IP pending_accounts: title: Cuentas pendientes (%{count}) relationships: @@ -473,6 +521,8 @@ es: comment: none: Ninguno created_at: Denunciado + forwarded: Reenviado + forwarded_to: Reenviado a %{domain} mark_as_resolved: Marcar como resuelto mark_as_unresolved: Marcar como no resuelto notes: @@ -516,6 +566,7 @@ es: domain_blocks_rationale: title: Mostrar la razón de ser enable_bootstrap_timeline_accounts: + desc_html: Hacer que los nuevos usuarios sigan automáticamente las cuentas configuradas para que su lÃnea temporal de inicio no comience vacÃa title: Habilitar seguimientos predeterminados para usuarios nuevos hero: desc_html: Mostrado en la página principal. Recomendable al menos 600x100px. Por defecto se establece a la miniatura de la instancia @@ -542,6 +593,9 @@ es: min_invite_role: disabled: Nadie title: Permitir invitaciones de + require_invite_text: + desc_html: Cuando los registros requieren aprobación manual, haga obligatorio en la invitaciones el campo "¿Por qué quieres unirte?" en lugar de opcional + title: Requiere a los nuevos usuarios rellenar un texto de solicitud de invitación registrations_mode: modes: approved: Se requiere aprobación para registrarse @@ -681,8 +735,11 @@ es: prefix_sign_up: "¡Únete a Mastodon hoy!" suffix: "¡Con una cuenta podrás seguir a gente, publicar novedades e intercambiar mensajes con usuarios de cualquier servidor de Mastodon y más!" didnt_get_confirmation: "¿No recibió el correo de confirmación?" + dont_have_your_security_key: "¿No tienes tu clave de seguridad?" forgot_password: "¿Olvidaste tu contraseña?" invalid_reset_password_token: El token de reinicio de contraseña es inválido o expiró. Por favor pide uno nuevo. + link_to_otp: Introduce un código de dos factores desde tu teléfono o un código de recuperación + link_to_webauth: Utilice su dispositivo de clave de seguridad login: Iniciar sesión logout: Cerrar sesión migrate_account: Mudarse a otra cuenta @@ -707,7 +764,9 @@ es: functional: Su cuenta está totalmente operativa. pending: Su solicitud está pendiente de revisión por nuestros administradores. Eso puede tardar algún tiempo. Usted recibirá un correo electrónico si el solicitud sea aprobada. redirecting_to: Tu cuenta se encuentra inactiva porque está siendo redirigida a %{acct}. + too_fast: Formulario enviado demasiado rápido, inténtelo de nuevo. trouble_logging_in: "¿Problemas para iniciar sesión?" + use_security_key: Usar la clave de seguridad authorize_follow: already_following: Ya estás siguiendo a esta cuenta already_requested: Ya has enviado una solicitud de seguimiento a esa cuenta @@ -732,6 +791,7 @@ es: date: formats: default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -796,6 +856,7 @@ es: request: Solicitar tu archivo size: Tamaño blocks: Personas que has bloqueado + bookmarks: Marcadores csv: CSV domain_blocks: Bloqueos de dominios lists: Listas @@ -863,6 +924,8 @@ es: status: Estado de la verificación view_proof: Ver prueba imports: + errors: + over_rows_processing_limit: contiene más de %{count} filas modes: merge: Unir merge_long: Mantener registros existentes y añadir nuevos @@ -872,6 +935,7 @@ es: success: Sus datos se han cargado correctamente y serán procesados en brevedad types: blocking: Lista de bloqueados + bookmarks: Marcadores domain_blocking: Lista de dominios bloqueados following: Lista de seguidos muting: Lista de silenciados @@ -992,6 +1056,14 @@ es: quadrillion: Q thousand: m trillion: T + otp_authentication: + code_hint: Introduce el código generado por tu aplicación de autentificación para confirmar + description_html: Si habilitas <strong>autenticación de dos factores</strong> a través de una aplicación de autenticación, el ingreso requerirá que estés en posesión de tu teléfono, que generará códigos para que ingreses. + enable: Activar + instructions_html: "<strong>Escanea este código QR desde Google Authenticator o una aplicación similar en tu teléfono</strong>. A partir de ahora, esta aplicación generará códigos que tendrásque ingresar cuando quieras iniciar sesión." + manual_instructions: 'Si no puedes escanear el código QR y necesitas introducirlo manualmente, este es el secreto en texto plano:' + setup: Configurar + wrong_code: "¡El código ingresado es inválido! ¿Es correcta la hora del dispositivo y el servidor?" pagination: newer: Más nuevo next: Próximo @@ -1020,6 +1092,7 @@ es: relationships: activity: Actividad de la cuenta dormant: Inactivo + follow_selected_followers: Seguir a los seguidores seleccionados followers: Seguidores following: Siguiendo invited: Invitado @@ -1034,7 +1107,7 @@ es: remove_selected_follows: Dejar de seguir a los usuarios seleccionados status: Estado de la cuenta remote_follow: - acct: Ingesa tu usuario@dominio desde el que quieres seguir + acct: Ingresa tu usuario@dominio desde el que quieres seguir missing_resource: No se pudo encontrar la URL de redirección requerida para tu cuenta no_account_html: "¿No tienes una cuenta? Puedes <a href='%{sign_up_path}' target='_blank'>registrarte aqui</a>" proceed: Proceder a seguir @@ -1116,6 +1189,7 @@ es: profile: Perfil relationships: Siguiendo y seguidores two_factor_authentication: Autenticación de dos factores + webauthn_authentication: Claves de seguridad spam_check: spam_detected: Este es un informe automatizado. Se ha detectado correo no deseado. statuses: @@ -1154,7 +1228,9 @@ es: other: "%{count} votos" vote: Vota show_more: Mostrar más - show_thread: Mostrar hilo + show_newer: Mostrar más recientes + show_older: Mostrar más antiguos + show_thread: Mostrar discusión sign_in_to_participate: RegÃstrate para participar en la conversación title: '%{name}: "%{quote}"' visibilities: @@ -1262,21 +1338,20 @@ es: default: "%d de %b del %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Ingresa el código generado por tu aplicación de autenticación para confirmar - description_html: Si habilitas la <strong>autenticación de dos factores</strong>, se requerirá estar en posesión de su teléfono, lo que generará tokens para que usted pueda iniciar sesión. + add: Añadir disable: Deshabilitar - enable: Habilitar + disabled_success: Autenticación de doble factor desactivada correctamente + edit: Editar enabled: La autenticación de dos factores está activada enabled_success: Verificación de dos factores activada exitosamente generate_recovery_codes: generar códigos de recuperación - instructions_html: "<strong>Escanea este código QR desde Google Authenticator o una aplicación similar en su teléfono</strong>. Desde ahora, esta aplicación va a generar tokens que tienes que ingresar cuando quieras iniciar sesión." lost_recovery_codes: Los códigos de recuperación te permiten obtener acceso a tu cuenta si pierdes tu teléfono. Si has perdido tus códigos de recuperación, puedes regenerarlos aquÃ. Tus viejos códigos de recuperación se harán inválidos. - manual_instructions: 'Si no puedes escanear el código QR y necesitas introducirlo manualmente, este es el secreto en texto plano:' + methods: Métodos de autenticación de doble factor + otp: Aplicación de autenticación recovery_codes: Hacer copias de seguridad de tus códigos de recuperación recovery_codes_regenerated: Códigos de recuperación regenerados con éxito recovery_instructions_html: Si pierdes acceso a tu teléfono, puedes usar uno de los siguientes códigos de recuperación para obtener acceso a tu cuenta. <strong>Mantenlos a salvo</strong>. Por ejemplo, puedes imprimirlos y guardarlos con otros documentos importantes. - setup: Configurar - wrong_code: "¡El código ingresado es inválido! ¿El dispositivo y tiempo del servidor están correctos?" + webauthn: Claves de seguridad user_mailer: backup_ready: explanation: Has solicitado una copia completa de tu cuenta de Mastodon. ¡Ya está preparada para descargar! @@ -1291,6 +1366,7 @@ es: warning: explanation: disable: Mientras su cuenta esté congelada, la información de su cuenta permanecerá intacta, pero no puede realizar ninguna acción hasta que se desbloquee. + sensitive: Los archivos multimedia subidos y vinculados serán tratados como sensibles. silence: Mientras su cuenta está limitada, sólo las personas que ya le están siguiendo verán sus toots en este servidor, y puede que se le excluya de varios listados públicos. Sin embargo, otros pueden seguirle manualmente. suspend: Su cuenta ha sido suspendida, y todos tus toots y tus archivos multimedia subidos han sido irreversiblemente eliminados de este servidor, y de los servidores donde tenÃas seguidores. get_in_touch: Puede responder a esta dirección de correo electrónico para ponerse en contacto con el personal de %{instance}. @@ -1299,11 +1375,13 @@ es: subject: disable: Su cuenta %{acct} ha sido congelada none: Advertencia para %{acct} + sensitive: Tu cuenta %{acct} ha sido marcada como sensible silence: Su cuenta %{acct} ha sido limitada suspend: Su cuenta %{acct} ha sido suspendida title: disable: Cuenta congelada none: Advertencia + sensitive: Tu multimedia ha sido marcado como sensible silence: Cuenta limitada suspend: Cuenta suspendida welcome: @@ -1324,9 +1402,11 @@ es: tips: Consejos title: Te damos la bienvenida a bordo, %{name}! users: + blocked_email_provider: Este proveedor de correo electrónico no está permitido follow_limit_reached: No puedes seguir a más de %{limit} personas generic_access_help_html: "¿Tienes problemas para acceder a tu cuenta? Puedes ponerte en contacto con %{email} para conseguir ayuda" invalid_email: La dirección de correo es incorrecta + invalid_email_mx: La dirección de correo electrónico parece inexistente invalid_otp_token: Código de dos factores incorrecto invalid_sign_in_token: Código de seguridad no válido otp_lost_help_html: Si perdiste al acceso a ambos, puedes ponerte en contancto con %{email} @@ -1336,3 +1416,20 @@ es: verification: explanation_html: 'Puedes <strong> verificarte a ti mismo como el dueño de los links en los metadatos de tu perfil </strong>. Para eso, el sitio vinculado debe contener un vÃnculo a tu perfil de Mastodon. El vÃnculo en tu sitio <strong> debe </strong> tener un atributo <code> rel="me"</code>. El texto del vÃnculo no importa. Aquà un ejemplo:' verification: Verificación + webauthn_credentials: + add: Agregar nueva clave de seguridad + create: + error: Hubo un problema al añadir su clave de seguridad. Por favor, inténtalo de nuevo. + success: Su clave de seguridad se ha añadido correctamente. + delete: Eliminar + delete_confirmation: "¿Estás seguro de que quieres eliminar esta clave de seguridad?" + description_html: Si habilita la <strong>autenticación de clave de seguridad</strong>, iniciar sesión requerirá que utilice una de sus claves de seguridad. + destroy: + error: Hubo un problema al añadir su clave de seguridad. Por favor, inténtalo de nuevo. + success: Su clave de seguridad se ha eliminado correctamente. + invalid_credential: Clave de seguridad no válida + nickname_hint: Introduzca el apodo de su nueva clave de seguridad + not_enabled: Aún no has activado WebAuthn + not_supported: Este navegador no soporta claves de seguridad + otp_required: Para usar claves de seguridad, por favor habilite primero la autenticación de doble factor. + registered_on: Registrado el %{date} diff --git a/config/locales/et.yml b/config/locales/et.yml index d611059cc04cbc216319295035d6569fb37be69a..17f462da103d44727c640f9935178fb8de4b7b49 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1176,21 +1176,14 @@ et: default: "%d. %B, %Y. aastal, kell %H:%M" month: "%B %Y" two_factor_authentication: - code_hint: Sisesta kaheastmelise autentimise kood, mille lõi Teie autentimisrakendus, et jätkata - description_html: Kui Te aktiveerite <strong>kaheastmelise autentimise</strong>, siis sisselogimisel peab teil olema telefon, mis loob Teile koode sisenemiseks. disable: Lülita välja - enable: Lülita sisse enabled: Kaheastmeline autentimine on sisse lülitatud enabled_success: Kaheastmeline autentimine on edukalt sisse lülitatud generate_recovery_codes: Loo taastuskoodid - instructions_html: "<strong>Skaneeri see QR kood kasutades rakendust Google Authenticator või muu TOTP rakendus Teie telefonis</strong>. Nüüdsest alates loob see rakendus Teile koode, mida peate sisestama sisselogimisel." lost_recovery_codes: Taastuskoodide abil on Teil võimalik sisse logida kontosse, kui Te kaotate oma telefoni. Kui Te kaotate oma taastuskoodid, saate need uuesti luua siin. Teie vanad taastuskoodid tehakse kehtetuks. - manual_instructions: 'Kui Te ei saa seda QR koodi skaneerida ning peate sisestama selle käsitsi, on siin tekstiline salavõti:' recovery_codes: Tagavara taastuskoodid recovery_codes_regenerated: Taastuskoodid edukalt taasloodud recovery_instructions_html: Kui Te juhtute kunagi kaotama oma telefoni, saate kasutada ühte allpool olevatest taastuskoodidest, et saada ligipääsu oma kontole. <strong>Hoidke taastuskoodid turvaliselt</strong>. Näiteks võite Te need välja printida ning hoida need koos teiste tähtsate dokumentidega. - setup: Sätesta - wrong_code: Sisestatud kood on vale! Kas serveri aeg ja seadme aeg on õiged? user_mailer: backup_ready: explanation: Te taotlesite varukoopia oma Mastodoni kontost. See on nüüd valmis allalaadimiseks! diff --git a/config/locales/eu.yml b/config/locales/eu.yml index fde1a820ead393fb03f8d21b1fe265128a19b15e..cd82a5d9a1952e6aa5c312c0ae995d88d489ce90 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -21,7 +21,9 @@ eu: federation_hint_html: "%{instance} instantzian kontu bat izanda edozein Mastodon zerbitzariko jendea jarraitu ahal izango duzu, eta harago ere." get_apps: Probatu mugikorrerako aplikazio bat hosted_on: Mastodon %{domain} domeinuan ostatatua - instance_actor_flash: Kontu hau zerbitzaria bera adierazten duen aktore birtual bat da, ez norbanako bat. Federaziorako erabiltzen da eta ez zenuke blokeatu behar instantzia osoa blokeatu nahi ez baduzu, kasu horretan domeinua blokeatzea egokia litzateke. + instance_actor_flash: 'Kontu hau zerbitzaria bera adierazten duen aktore birtual bat da, ez norbanako bat. Federaziorako erabiltzen da eta ez zenuke blokeatu behar instantzia osoa blokeatu nahi ez baduzu, kasu horretan domeinua blokeatzea egokia litzateke. + +' learn_more: Ikasi gehiago privacy_policy: Pribatutasun politika see_whats_happening: Ikusi zer gertatzen ari den @@ -1230,21 +1232,14 @@ eu: default: "%Y(e)ko %b %d, %H:%M" month: "%Y(e)ko %b" two_factor_authentication: - code_hint: Sartu zure autentifikazio aplikazioak sortutako kodea berresteko - description_html: "<strong>Bi faktoreetako autentifikazioa</strong> gaitzen baduzu, saioa hasteko telefonoa eskura izan beharko duzu, honek zuk sartu behar dituzun kodeak sortuko dituelako." disable: Desgaitu - enable: Gaitu enabled: Bi faktoreetako autentifikazioa gaituta dago enabled_success: Bi faktoreetako autentifikazioa ongi gaitu da generate_recovery_codes: Sortu berreskuratze kodeak - instructions_html: "<strong>Eskaneatu QR kode hau Google Authentiocator edo antzeko TOTTP aplikazio batekin zure telefonoan</strong>. Hortik aurrera, aplikazio horrek saioa hasteko sartu behar dituzun kodeak sortuko ditu." lost_recovery_codes: Berreskuratze kodeek telefonoa galtzen baduzu kontura sarbidea berreskuratzea ahalbideko dizute. Berreskuratze kodeak galdu badituzu, hemen birsortu ditzakezu. Zure berreskuratze kode zaharrak indargabetuko dira,. - manual_instructions: 'Ezin baduzu QR kodea eskaneatu eta eskuz sartu behar baduzu, hona sekretua testu hutsean:' recovery_codes: Berreskuratze kodeen babes-kopia recovery_codes_regenerated: Berreskuratze kodeak ongi sortu dira recovery_instructions_html: Zure telefonora sarbidea galtzen baduzu, beheko berreskuratze kode bat erabili dezakezu kontura berriro sartu ahal izateko. <strong>Gore barreskuratze kodeak toki seguruan</strong>. Adibidez inprimatu eta dokumentu garrantzitsuekin batera gorde. - setup: Ezarri - wrong_code: Sartutako kodea baliogabea da! Zerbitzariaren eta gailuaren erlojuak ondo ezarrita daude? user_mailer: backup_ready: explanation: Zure Mastodon kontuaren babes-kopia osoa eskatu duzu. Deskargatzeko prest dago! diff --git a/config/locales/fa.yml b/config/locales/fa.yml index 25e66f328856ea26e798918a162feed1e28d6cd5..cf094478af15ad4a775ccf08cb4496ebbb9bd81f 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -62,6 +62,7 @@ fa: one: پیگیر other: پیگیر following: Ù¾ÛŒ می‌گیرد + instance_actor_flash: این ØØ³Ø§Ø¨ یک عامل مجازی است Ú©Ù‡ به نمایندگی از خود کارساز Ø§Ø³ØªÙØ§Ø¯Ù‡ می‌شود Ùˆ نه هیچ یکی از کاربران. این ØØ³Ø§Ø¨ به منظور اتصال به ÙØ¯Ø±Ø§Ø³ÛŒÙˆÙ† Ø§Ø³ØªÙØ§Ø¯Ù‡ می‌شود Ùˆ نباید معلق شود. joined: کاربر از %{date} last_active: آخرین ÙØ¹Ø§Ù„یت link_verified_on: مالکیت این پیوند در %{date} بررسی شد @@ -100,6 +101,7 @@ fa: add_email_domain_block: مسدود کردن دامنهٔ رایانامه approve: Ù¾Ø°ÛŒØ±ÙØªÙ† approve_all: Ù¾Ø°ÛŒØ±ÙØªÙ† همه + approved_msg: کارهٔ ثبت‌نام %{username} با موÙقیت تأیید شد are_you_sure: مطمئنید؟ avatar: تصویر نمایه by_domain: دامین @@ -113,8 +115,10 @@ fa: confirm: تأیید confirmed: تأیید شد confirming: تأیید + delete: ØØ°Ù داده‌ها deleted: ØØ°Ù شده demote: تنزل‌دادن + destroyed_msg: داده‌های %{username} در ØµÙ ØØ¯Ù قرار Ú¯Ø±ÙØªÙ†Ø¯ disable: از کار انداختن disable_two_factor_authentication: از کار انداختن ورود دومرØÙ„ه‌ای disabled: از کار Ø§ÙØªØ§Ø¯Ù‡ @@ -125,10 +129,12 @@ fa: email_status: وضعیت ایمیل enable: به کار انداختن enabled: به کار Ø§ÙØªØ§Ø¯Ù‡ + enabled_msg: ØØ³Ø§Ø¨ %{username} با موÙقیت به کار انداخته شد followers: پیگیران follows: Ù¾ÛŒ می‌گیرد header: تصویر زمینه inbox_url: نشانی صندوق ورودی + invite_request_text: دلایل‌تان برای پیوستن invited_by: دعوت‌شده از طر٠ip: IP joined: عضو شده در @@ -140,6 +146,8 @@ fa: login_status: وضعیت ورود media_attachments: پیوست‌های رسانه‌ای memorialize: تبدیل به یادمان + memorialized: یادمان‌سازی شده + memorialized_msg: "%{username} با موÙقیت به یک ØØ³Ø§Ø¨ یادمانی تبدیل شد" moderation: active: ÙØ¹Ù‘ال all: همه @@ -160,10 +168,14 @@ fa: public: عمومی push_subscription_expires: عضویت از راه PuSH منقضی شد redownload: نوسازی نمایه + redownloaded_msg: ØØ³Ø§Ø¨ %{username} با موÙقیت از ابتدا نوسازی شد reject: Ù†Ù¾Ø°ÛŒØ±ÙØªÙ† reject_all: Ù†Ù¾Ø°ÛŒØ±ÙØªÙ† هیچکدام + rejected_msg: کارهٔ ثبت‌نام %{username} با موÙقیت رد شد remove_avatar: ØØ°Ù تصویر نمایه remove_header: برداشتن تصویر زمینه + removed_avatar_msg: تصویر آواتار %{username} با موÙّقیت برداشته شد + removed_header_msg: تصویر سرایند %{username} با موÙّقیت برداشته شد resend_confirmation: already_confirmed: این کاربر قبلا تایید شده است send: ایمیل تایید را دوباره Ø¨ÙØ±Ø³ØªÛŒØ¯ @@ -180,6 +192,8 @@ fa: search: جستجو search_same_email_domain: دیگر کاربران با دامنهٔ رایانامهٔ یکسان search_same_ip: دیگر کاربران با IP یکسان + sensitive: ØØ³Ø§Ø³ + sensitized: علامت‌زده به عنوان ØØ³Ø§Ø³ shared_inbox_url: نشانی صندوق ورودی مشترک show: created_reports: گزارش‌های ثبت کرده @@ -189,13 +203,19 @@ fa: statuses: نوشته‌ها subscribe: اشتراک suspended: تعلیق‌شده + suspension_irreversible: داده‌های این ØØ³Ø§Ø¨ به صورت بی‌بازگشت ØØ°Ù شد. می‌توانید برای قابل Ø§Ø³ØªÙØ§Ø¯Ù‡ کردنش، آن را نامعلّق کنید، ولی این کار هیچ داده‌ای را Ú©Ù‡ از پیش داده، برنخواهد گرداند. + suspension_reversible_hint_html: ØØ³Ø§Ø¨ معلّق شد Ùˆ داده‌ها به صورت کامل در %{date} برداشته خواهند شد. تا آن زمان، ØØ³Ø§Ø¨ می‌تواند بی هیچ عوارضی بازگردانده شود. اگر می‌خواهید Ùوراً همهٔ داده‌های ØØ³Ø§Ø¨ را بردارید، می‌توانید در پایین این کار را بکنید. time_in_queue: در ØØ§Ù„ انتظار %{time} title: ØØ³Ø§Ø¨â€ŒÙ‡Ø§ unconfirmed_email: ایمیل تأییدنشده + undo_sensitized: بازگردانی ØØ³Ø§Ø³ undo_silenced: واگردانی بی‌صداکردن undo_suspension: واگردانی تعلیق + unsilenced_msg: ØØ³Ø§Ø¨ %{username} با موÙّقیت Ù†Ø§Ù…ØØ¯ÙˆØ¯ شد unsubscribe: لغو اشتراک + unsuspended_msg: ØØ³Ø§Ø¨ %{username} با موÙّقیت نامعلّق شد username: نام کاربری + view_domain: نمایش خلاصهٔ دامنه warn: هشدار web: وب whitelisted: Ùهرست مجاز @@ -210,12 +230,14 @@ fa: create_domain_allow: ایجاد اجازهٔ دامنه create_domain_block: ایجاد انسداد دامنه create_email_domain_block: ایجاد انسداد دامنهٔ رایانامه + create_ip_block: ایجاد قاعدهٔ آی‌پی demote_user: تنزل کاربر destroy_announcement: ØØ°Ù اعلامیه destroy_custom_emoji: ØØ°Ù اموجی Ø³ÙØ§Ø±Ø´ÛŒ destroy_domain_allow: ØØ°Ù اجازهٔ دامنه destroy_domain_block: ØØ°Ù انسداد دامنه destroy_email_domain_block: ØØ°Ù انسداد دامنهٔ رایانامه + destroy_ip_block: ØØ°Ù قاعدهٔ آی‌پی destroy_status: ØØ°Ù وضعیت disable_2fa_user: از کار انداختن ورود دومرØÙ„ه‌ای disable_custom_emoji: از کار انداختن اموجی Ø³ÙØ§Ø±Ø´ÛŒ @@ -228,13 +250,16 @@ fa: reopen_report: بازگشایی گزارش reset_password_user: بازنشانی گذرواژه resolve_report: Ø±ÙØ¹ گزارش + sensitive_account: علامت‌گذاری رسانه در ØØ³Ø§Ø¨ØªØ§Ù† به عنوان ØØ³Ø§Ø³ silence_account: خموشی ØØ³Ø§Ø¨ suspend_account: تعلیق ØØ³Ø§Ø¨ unassigned_report: Ø±ÙØ¹ واگذاری گزارش + unsensitive_account: برداشتن علامت رسانه در ØØ³Ø§Ø¨ØªØ§Ù† به عنوان ØØ³Ø§Ø³ unsilence_account: Ø±ÙØ¹ خموشی ØØ³Ø§Ø¨ unsuspend_account: Ø±ÙØ¹ تعلیق ØØ³Ø§Ø¨ update_announcement: به‌روز رسانی اعلامیه update_custom_emoji: به‌روز رسانی اموجی Ø³ÙØ§Ø±Ø´ÛŒ + update_domain_block: به‌روزرسانی مسدودسازی دامنه update_status: به‌روز رسانی وضعیت actions: assigned_to_self_report: "%{name} رسیدگی به گزارش %{target} را به عهده Ú¯Ø±ÙØª" @@ -246,12 +271,14 @@ fa: create_domain_allow: "%{name} دامنهٔ %{target} را مجاز کرد" create_domain_block: "%{name} دامین %{target} را مسدود کرد" create_email_domain_block: "%{name} دامین ایمیل %{target} را مسدود کرد" + create_ip_block: "%{name} برای آی‌پی %{target} قاعده‌ای ایجاد کرد" demote_user: "%{name} مقام کاربر %{target} را تنزل داد" destroy_announcement: "%{name} اعلامیهٔ %{target} را ØØ°Ù کرد" destroy_custom_emoji: "%{name} اموجی %{target} را نابود کرد" destroy_domain_allow: "%{name} دامنهٔ %{target} را از Ùهرست مجاز برداشت" destroy_domain_block: "%{name} انسداد دامنهٔ %{target} را Ø±ÙØ¹ کرد" destroy_email_domain_block: "%{name} دامنهٔ ایمیل %{target} را به Ùهرست مجاز Ø§ÙØ²ÙˆØ¯" + destroy_ip_block: "%{name} قاعده‌ای را از آی‌پی %{target} ØØ°Ù کرد" destroy_status: "%{name} نوشتهٔ %{target} را پاک کرد" disable_2fa_user: "%{name} اجبار ورود دومرØÙ„ه‌ای را برای کاربر %{target} ØºÛŒØ±ÙØ¹Ø§Ù„ کرد" disable_custom_emoji: "%{name} Ø´Ú©Ù„Ú© %{target} را ØºÛŒØ±ÙØ¹Ø§Ù„ کرد" @@ -264,13 +291,16 @@ fa: reopen_report: "%{name} گزارش %{target} را دوباره به جریان انداخت" reset_password_user: "%{name} رمز کاربر %{target} را بازنشاند" resolve_report: "%{name} گزارش %{target} را Ø±ÙØ¹ کرد" + sensitive_account: "%{name} رسانهٔ %{target} را به عنوان ØØ³Ø§Ø³ علامت‌گذاری کرد" silence_account: "%{name} ØØ³Ø§Ø¨ کاربر %{target} را خاموش (بی‌صدا) کرد" suspend_account: "%{name} ØØ³Ø§Ø¨ کاربر %{target} را تعلیق کرد" unassigned_report: "%{name} بررسی گزارش %{target} را متوق٠کرد" + unsensitive_account: "%{name} علامت ØØ³Ø§Ø³ رسانهٔ %{target} را برداشت" unsilence_account: "%{name} ØØ³Ø§Ø¨ کاربر %{target} را روشن (باصدا) کرد" unsuspend_account: "%{name} ØØ³Ø§Ø¨ کاربر %{target} را از تعلیق خارج کرد" update_announcement: "%{name} اعلامیهٔ %{target} را به‌روز کرد" update_custom_emoji: "%{name} Ø´Ú©Ù„Ú© %{target} را به‌روز کرد" + update_domain_block: "%{name} مسدودسازی دامنه را برای %{target} به‌روزرسانی کرد" update_status: "%{name} نوشتهٔ %{target} را به‌روز کرد" deleted_status: "(نوشتهٔ پاک‌شده)" empty: هیچ گزارشی پیدا نشد. @@ -413,6 +443,7 @@ fa: instances: by_domain: دامین delivery_available: پیام آماده است + empty: هیج دامنه‌ای پیدا نشد. known_accounts: one: "%{count} ØØ³Ø§Ø¨ شناخته‌شده" other: "%{count} ØØ³Ø§Ø¨ شناخته‌شده" @@ -436,6 +467,21 @@ fa: expired: منقضی‌شده title: Ùیلتر title: دعوت‌ها + ip_blocks: + add_new: ایجاد قانون + created_msg: قانون IP جدید با موÙقیت Ø§ÙØ²ÙˆØ¯Ù‡ شد + delete: پاک کردن + expires_in: + '1209600': Û² Ù‡ÙØªÙ‡ + '15778476': Û¶ ماه + '2629746': Û± ماه + '31556952': Û± سال + '86400': Û± روز + '94670856': Û³ سال + new: + title: ایجاد قانون جدید IP + no_ip_block_selected: هیچ قاعدهٔ آی‌پی‌ای تغییری نکرد زیرا هیچ‌کدام گزیده نشده بودند + title: قوانین IP pending_accounts: title: ØØ³Ø§Ø¨â€ŒÙ‡Ø§ÛŒ منتظر (%{count}) relationships: @@ -475,6 +521,8 @@ fa: comment: none: هیچ created_at: گزارش‌شده + forwarded: هدایت شده + forwarded_to: هدایت شده به %{domain} mark_as_resolved: علامت‌گذاری به عنوان ØÙ„‌شده mark_as_unresolved: علامت‌گذاری به عنوان ØÙ„‌نشده notes: @@ -544,6 +592,9 @@ fa: min_invite_role: disabled: هیچ کس title: اجازهٔ دعوت به + require_invite_text: + desc_html: زمانی Ú©Ù‡ نام‌نویسی نیازمند تایید دستی است، متن «چرا می‌خواهید عضو شود؟» بخش درخواست دعوت را به جای اختیاری، اجباری کنید + title: نیازمند پر کردن متن درخواست دعوت توسط کاربران جدید registrations_mode: modes: approved: ثبت نام نیازمند تأیید مدیران است @@ -683,8 +734,11 @@ fa: prefix_sign_up: همین امروز عضو ماستودون شوید! suffix: با داشتن ØØ³Ø§Ø¨ می‌توانید دیگران را Ù¾ÛŒ بگیرید، نوشته‌های تازه منتشر کنید، Ùˆ با کاربران دیگر از هر سرور ماستودون دیگری Ùˆ ØØªÛŒ سرورهای دیگر در ارتباط باشید! didnt_get_confirmation: راهنمایی برای تأیید را Ø¯Ø±ÛŒØ§ÙØª نکردید؟ + dont_have_your_security_key: کلید امنیتیتان را ندارید؟ forgot_password: رمزتان را Ú¯Ù… کرده‌اید؟ invalid_reset_password_token: کد بازنشانی رمز نامعتبر یا منقضی شده است. Ù„Ø·ÙØ§Ù‹ کد دیگری درخواست کنید. + link_to_otp: رمز بازگردانی یا رمز دوعاملی را از تلÙنتان وارد کنید + link_to_webauth: Ø§Ø³ØªÙØ§Ø¯Ù‡ از Ø§ÙØ²Ø§Ø±Ù‡Ù” امنیتیتان login: ورود logout: خروج migrate_account: نقل مکان به یک ØØ³Ø§Ø¨ دیگر @@ -709,7 +763,9 @@ fa: functional: ØØ³Ø§Ø¨ شما قابل Ø§Ø³ØªÙØ§Ø¯Ù‡ است. pending: درخواست شما منتظر تأیید مسئولان سایت است Ùˆ این ÙØ±Ø§ÛŒÙ†Ø¯ ممکن است Ú©Ù…ÛŒ طول بکشد. اگر درخواست شما Ù¾Ø°ÛŒØ±ÙØªÙ‡ شود به شما ایمیلی ÙØ±Ø³ØªØ§Ø¯Ù‡ خواهد شد. redirecting_to: ØØ³Ø§Ø¨ شما ØºÛŒØ±ÙØ¹Ø§Ù„ است زیرا هم‌اکنون به %{acct} منتقل شده است. + too_fast: ÙØ±Ù… با سرعت بسیار زیادی ÙØ±Ø³ØªØ§Ø¯Ù‡ شد، دوباره تلاش کنید. trouble_logging_in: برای ورود مشکلی دارید؟ + use_security_key: Ø§Ø³ØªÙØ§Ø¯Ù‡ از کلید امنیتی authorize_follow: already_following: شما همین الان هم این ØØ³Ø§Ø¨ را پی‌می‌گیرید already_requested: درخواست پی‌گیری‌ای برای آن ØØ³Ø§Ø¨ ÙØ±Ø³ØªØ§Ø¯Ù‡â€Œ بودید @@ -734,6 +790,7 @@ fa: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count} ساعت" @@ -798,6 +855,7 @@ fa: request: درخواست بایگانی داده‌هایتان size: اندازه blocks: ØØ³Ø§Ø¨â€ŒÙ‡Ø§ÛŒ مسدودشده + bookmarks: نشانک‌ها csv: CSV domain_blocks: دامین‌های مسدودشده lists: Ùهرست‌ها @@ -874,6 +932,7 @@ fa: success: داده‌های شما با موÙقیت بارگذاری شد Ùˆ به زودی پردازش می‌شود types: blocking: Ùهرست مسدودشده‌ها + bookmarks: نشانک‌ها domain_blocking: Ùهرست دامین‌های مسدودشده following: Ùهرست پی‌گیری‌ها muting: Ùهرست بی‌صداشده‌ها @@ -994,6 +1053,14 @@ fa: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: برای تأیید، کدی را Ú©Ù‡ برنامهٔ تأییدکننده ساخته است وارد کنید + description_html: اگر <strong>ورود دومرØÙ„ه‌ای</strong> را با Ø§Ø³ØªÙØ§Ø¯Ù‡ از از یک کارهٔ تأییدکننده به کار بیندازید، لازم است برای ورود، به تلÙÙ† خود Ú©Ù‡ برایتان یک ژتون خواهد ساخت دسترسی داشته باشید. + enable: به کار انداختن + instructions_html: "<strong>این کد QR را با برنامهٔ Google Authenticator یا برنامه‌های TOTP مشابه اسکن کنید</strong>. از این به بعد، آن برنامه کدهایی موقتی خواهد ساخت Ú©Ù‡ برای ورود باید آن‌ها را وارد کنید." + manual_instructions: 'اگر نمی‌توانید رمز QR را بپویید Ùˆ باید دستی واردظ کنید، متن رمز این‌جاست:' + setup: برپا سازی + wrong_code: رمز وارد شده نامعتبر بود! آیا زمان کارساز Ùˆ زمان Ø§ÙØ²Ø§Ø±Ù‡ درستند؟ pagination: newer: تازه‌تر next: بعدی @@ -1022,6 +1089,7 @@ fa: relationships: activity: ÙØ¹Ø§Ù„یت ØØ³Ø§Ø¨ dormant: ØºÛŒØ±ÙØ¹Ø§Ù„ + follow_selected_followers: پیگیری پیگیران انتخاب شده followers: پی‌گیران following: Ù¾ÛŒ می‌گیرد invited: مدعو @@ -1118,6 +1186,7 @@ fa: profile: نمایه relationships: پیگیری‌ها Ùˆ پیگیران two_factor_authentication: ورود دومرØÙ„ه‌ای + webauthn_authentication: کلیدهای امنیتی spam_check: spam_detected: این یک گزارش خودکار برای تشخیص هرزنامه است. statuses: @@ -1156,6 +1225,8 @@ fa: other: "%{count} رأی" vote: رأی show_more: نمایش + show_newer: نمایش جدیدتر + show_older: نمایش قدیمی‌تر show_thread: نمایش رشته sign_in_to_participate: برای شرکت در Ú¯ÙØªÚ¯Ùˆ وارد ØØ³Ø§Ø¨ خود شوید title: '%{name}: "%{quote}"' @@ -1264,21 +1335,20 @@ fa: default: "%d %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: برای تأیید، کدی را Ú©Ù‡ برنامهٔ تأییدکننده ساخته است وارد کنید - description_html: اگر <strong>ورود دومرØÙ„ه‌ای</strong> را ÙØ¹Ø§Ù„ کنید، برای ورود به سیستم به تلÙÙ† خود نیاز خواهید داشت تا برایتان یک کد موقتی بسازد. + add: Ø§ÙØ²ÙˆØ¯Ù† disable: ØºÛŒØ±ÙØ¹Ø§Ù„‌کردن - enable: ÙØ¹Ø§Ù„‌کردن + disabled_success: ورود دومرØÙ„ه‌ای با موÙقیت از کار Ø§ÙØªØ§Ø¯ + edit: ویرایش enabled: ورود دومرØÙ„ه‌ای ÙØ¹Ø§Ù„ است enabled_success: ورود دومرØÙ„ه‌ای با موÙقیت ÙØ¹Ø§Ù„ شد generate_recovery_codes: ساخت کدهای بازیابی - instructions_html: "<strong>این کد QR را با برنامهٔ Google Authenticator یا برنامه‌های TOTP مشابه اسکن کنید</strong>. از این به بعد، آن برنامه کدهایی موقتی خواهد ساخت Ú©Ù‡ برای ورود باید آن‌ها را وارد کنید." lost_recovery_codes: با کدهای بازیابی می‌توانید اگر تلÙÙ† خود را Ú¯Ù… کردید به ØØ³Ø§Ø¨ خود دسترسی داشته باشید. اگر کدهای بازیابی خود را Ú¯Ù… کردید، آن‌ها را این‌جا دوباره بسازید. کدهای بازیابی قبلی شما نامعتبر خواهند شد. - manual_instructions: 'اگر نمی‌توانید کدها را اسکن کنید Ùˆ باید آن‌ها را دستی وارد کنید، متن کد امنیتی این‌جاست:' + methods: روش‌های ورود دومرØÙ„ه‌ای + otp: کارهٔ تأیید کننده recovery_codes: پشتیبان‌گیری از کدهای بازیابی recovery_codes_regenerated: کدهای بازیابی با موÙقیت ساخته شدند recovery_instructions_html: اگر تلÙÙ† خود را Ú¯Ù… کردید، می‌توانید با یکی از کدهای بازیابی زیر کنترل ØØ³Ø§Ø¨ خود را به دست بگیرید. <strong>این کدها را در جای امنی Ù†Ú¯Ù‡ دارید.</strong> مثلاً آن‌ها را چاپ کنید Ùˆ کنار سایر مدارک مهم خود قرار دهید. - setup: راه اندازی - wrong_code: کدی Ú©Ù‡ وارد کردید نامعتبر بود! آیا ساعت کارساز Ùˆ ساعت دستگاه شما درست تنظیم شده‌اند؟ + webauthn: کلیدهای امنیتی user_mailer: backup_ready: explanation: شما یک نسخهٔ پشتیبان کامل از ØØ³Ø§Ø¨ خود را درخواست کردید. این پشتیبان الان آمادهٔ بارگیری است! @@ -1293,6 +1363,7 @@ fa: warning: explanation: disable: تا وقتی ØØ³Ø§Ø¨ شما متوق٠باشد، داده‌های شما دست‌نخورده باقی می‌مانند، ولی تا وقتی Ú©Ù‡ ØØ³Ø§Ø¨ØªØ§Ù† باز نشده، نمی‌توانید هیچ کاری با آن بکنید. + sensitive: پرونده‌های رسانهٔ بارگذاری‌شده Ùˆ رسانه‌های پیوسته به عنوان ØØ³Ø§Ø³ در نظر Ú¯Ø±ÙØªÙ‡ خواهند شد. silence: تا وقتی ØØ³Ø§Ø¨ شما Ù…ØØ¯ÙˆØ¯ باشد، تنها کسانی Ú©Ù‡ از قبل پیگیر شما بودند نوشته‌های شما در این کارساز را می‌بینند Ùˆ شاید شما در برخی از Ùهرست‌های عمومی دیده نشوید. ولی دیگران همچنان می‌توانند به دلخواه خودشان پیگیر شما شوند. suspend: ØØ³Ø§Ø¨ØªØ§Ù† معلق شده Ùˆ تمام بوق‌ها Ùˆ رسانه‌های بارگذاشته‌تان، از روی این کارساز Ùˆ کارسازهایی Ú©Ù‡ پیگیرانی رویشان داشتید، به طور بازگشت‌ناپذیری برداشته شده‌اند. get_in_touch: با پاسخ به این ایمیل می‌توانید با دست‌اندرکاران %{instance} در تماس باشید. @@ -1301,11 +1372,13 @@ fa: subject: disable: ØØ³Ø§Ø¨ %{acct} شما متوق٠شده است none: هشدار برای %{acct} + sensitive: رسانه‌های ÙØ±Ø³ØªØ§Ø¯Ù‡ شده توسط ØØ³Ø§Ø¨ %{acct} شما برچسب ØØ³Ø§Ø³ خورده‌اند silence: ØØ³Ø§Ø¨ %{acct} شما Ù…ØØ¯ÙˆØ¯ شده است suspend: ØØ³Ø§Ø¨ %{acct} شما معلق شده است title: disable: ØØ³Ø§Ø¨ متوق٠شده است none: هشدار + sensitive: رسانه‌تان به عنوان ØØ³Ø§Ø³ در نظر Ú¯Ø±ÙØªÙ‡ شد silence: ØØ³Ø§Ø¨ Ù…ØØ¯ÙˆØ¯ شده است suspend: ØØ³Ø§Ø¨ معلق شده است welcome: @@ -1326,9 +1399,11 @@ fa: tips: نکته‌ها title: خوش آمدید، کاربر %{name}! users: + blocked_email_provider: ÙØ±Ø§Ù‡Ù…‌کنندهٔ رایانامه مجاز نیست follow_limit_reached: شما نمی‌توانید بیش از %{limit} Ù†ÙØ± را Ù¾ÛŒ بگیرید generic_access_help_html: مشکل در دسترسی به ØØ³Ø§Ø¨ØªØ§Ù†ØŸ می‌توانید برای Ú©Ù…Ú© با %{email} تکاس بگیرید invalid_email: نشانی ایمیل نامعتبر است + invalid_email_mx: به نظر نمی‌رسد نشانی رایانامه وجود داشته باشد invalid_otp_token: کد ورود دومرØÙ„ه‌ای نامعتبر است invalid_sign_in_token: کد امنیتی نادرست otp_lost_help_html: اگر شما دسترسی به هیچ‌کدامشان ندارید، باید با ایمیل %{email} تماس بگیرید @@ -1338,3 +1413,20 @@ fa: verification: explanation_html: 'شما می‌توانید <strong>خود را به عنوان مالک ØµÙØÙ‡â€ŒØ§ÛŒ Ú©Ù‡ در نمایه‌تان به آن پیوند داده‌اید تأیید کنید.</strong> برای این کار، ØµÙØÙ‡â€ŒØ§ÛŒ Ú©Ù‡ به آن پیوند داده‌اید، خودش باید پیوندی به نمایهٔ ماستودون شما داشته باشد. پیوند در آن ØµÙØÙ‡ <strong>باید</strong> عبارت <code>rel="me"‎</code> را به عنوان مشخّصهٔ (attribute) در خود داشته باشد. Ù…ØØªÙˆØ§ÛŒ متن پیوند اهمتی ندارد. یک نمونه از چنین پیوندی:' verification: تأیید + webauthn_credentials: + add: Ø§ÙØ²ÙˆØ¯Ù† کلید امنیتی + create: + error: Ø§ÙØ²ÙˆØ¯Ù† کلید امنیتیتان با مشکل مواجه شد. Ù„Ø·ÙØ§Ù‹ دوباره تلاش کنید. + success: کلید امنیتیتان با موÙّقیت Ø§ÙØ²ÙˆØ¯Ù‡ شد. + delete: ØØ°Ù + delete_confirmation: مطمئنید Ú©Ù‡ می‌خواهید این کلید امنیتی را ØØ°Ù کنید؟ + description_html: اگر <strong>Ø§ØØ±Ø§Ø² هویت کلید امنیتی</strong> را ÙØ¹Ø§Ù„ کنید، ورود نیازمند این خواهد بود Ú©Ù‡ یکی از کلیدهای امنیتی‌تان را Ø§Ø³ØªÙØ§Ø¯Ù‡ کنید. + destroy: + error: ØØ°Ù کلید امنیتیتان با مشکل مواجه شد. Ù„Ø·ÙØ§Ù‹ دوباره تلاش کنید. + success: کلید امنیتیتان با موÙّقیت ØØ°Ù شد. + invalid_credential: کلید امنیتی نامعتبر + nickname_hint: نام مستعار کلید امنیتی جدیدتان را وارد کنید + not_enabled: شما هنوز WebAuthn را ÙØ¹Ø§Ù„ نکرده‌اید + not_supported: این مرورگر از کلیدهای امنیتی پشتیبانی نمی‌کند + otp_required: برای Ø§Ø³ØªÙØ§Ø¯Ù‡ از کلیدهای امنیتی، Ù„Ø·ÙØ§Ù‹ ابتدا تأیید هویت دو عاملی را به کار بیندازید. + registered_on: ثبت‌شده در %{date} diff --git a/config/locales/fi.yml b/config/locales/fi.yml index c5703e596a592d56e243de094ab002c588c18191..9eb0d9397fb4b959673d5ea903170ac61e837e3b 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -4,10 +4,12 @@ fi: about_hashtag_html: Nämä ovat hashtagilla <strong>#%{hashtag}</strong> merkittyjä julkisia tuuttauksia. Voit vastata niihin, jos sinulla on tili jossain päin fediversumia. about_mastodon_html: Mastodon on sosiaalinen verkosto. Se on toteutettu avoimilla verkkoprotokollilla ja vapailla, avoimen lähdekoodin ohjelmistoilla, ja se toimii hajautetusti samaan tapaan kuin sähköposti. about_this: Tietoja tästä palvelimesta + active_count_after: aktiivinen administered_by: 'Ylläpitäjä:' api: API apps: Mobiili sovellukset apps_platforms: Käytä Mastodonia iOS:llä, Androidilla tai muilla alustoilla + browse_directory: Selaa profiilihakemistoa ja suodata kiinnostuksen kohteiden mukaan contact: Ota yhteyttä contact_missing: Ei asetettu contact_unavailable: Ei saatavilla @@ -17,6 +19,7 @@ fi: hosted_on: Mastodon palvelimella %{domain} learn_more: Lisätietoja privacy_policy: Tietosuojaseloste + see_whats_happening: Näe mitä tapahtuu server_stats: 'Palvelimen tilastot:' source_code: Lähdekoodi status_count_after: @@ -28,6 +31,10 @@ fi: unavailable_content_description: domain: Palvelin reason: Syy + rejecting_media_title: Media suodatettu + silenced: 'Julkaisut näiltä palvelimilta piilotetaan julkisilta aikajanoilta ja keskusteluista, ilmoituksia ei luoda näiden käyttäjien tekemistä toiminnoista, jos et seuraa heitä:' + silenced_title: Hiljennetyt palvelimet + suspended: 'Dataa näiltä palvelimilta ei tulla käsittelemään, tallentamaan tai jakamaan. Tämä tekee kommunikoinnin näiden käyttäjien kanssa mahdottomaksi:' user_count_after: one: käyttäjä other: käyttäjät @@ -35,6 +42,7 @@ fi: what_is_mastodon: Mikä on Mastodon? accounts: choices_html: "%{name} valinnat:" + endorsements_hint: Voit suositella seuraamiasi henkilöitä web käyttöliittymän kautta, ne tulevat näkymään tähän. follow: Seuraa followers: one: Seuraaja @@ -66,8 +74,10 @@ fi: unavailable: Profiili ei saatavilla unfollow: Lopeta seuraaminen admin: + account_actions: + action: Suorita toimenpide account_moderation_notes: - create: Luo + create: Jätä muistiinpano created_msg: Moderointimerkinnän luonti onnistui! delete: Poista destroyed_msg: Moderointimerkinnän poisto onnistui! @@ -101,7 +111,9 @@ fi: enabled: Käytössä followers: Seuraajat follows: Seuraa + header: Otsakekuva inbox_url: Saapuvan postilaatikon osoite + invited_by: Kutsuja ip: IP joined: Liittynyt location: @@ -122,7 +134,9 @@ fi: moderation_notes: Moderointimerkinnät most_recent_activity: Viimeisin toiminta most_recent_ip: Viimeisin IP + no_limits_imposed: Rajoituksia ei ole asetettu not_subscribed: Ei tilaaja + pending: Odottaa tarkistusta perform_full_suspension: Siirrä kokonaan jäähylle promote: Ylennä protocol: Protokolla @@ -132,6 +146,7 @@ fi: reject: Hylkää reject_all: Hylkää kaikki remove_avatar: Poista profiilikuva + remove_header: Poista otsakekuva resend_confirmation: already_confirmed: Tämä käyttäjä on jo vahvistettu send: Lähetä varmistusviesti uudelleen @@ -146,6 +161,7 @@ fi: staff: Henkilöstö user: Käyttäjä search: Hae + search_same_ip: Muut käyttäjät samalla IP-osoitteella shared_inbox_url: Jaetun saapuvan postilaatikon osoite show: created_reports: Tämän tilin luomat raportit @@ -155,6 +171,7 @@ fi: statuses: Tilat subscribe: Tilaa suspended: Jäähyllä + time_in_queue: Odottaa jonossa %{time} title: Tilit unconfirmed_email: Sähköpostia ei vahvistettu undo_silenced: Peru hiljennys @@ -164,6 +181,22 @@ fi: warn: Varoita web: Verkko action_logs: + action_types: + confirm_user: Vahvista käyttäjä + create_account_warning: Luo varoitus + create_announcement: Luo ilmoitus + create_custom_emoji: Luo mukautettu emoji + demote_user: Alenna käyttäjä + destroy_announcement: Poista ilmoitus + destroy_custom_emoji: Poista mukautettu emoji + destroy_status: Poista tilapäivitys + disable_2fa_user: Poista kaksivaiheinen tunnistautuminen käytöstä + disable_user: Tili poistettu käytöstä + enable_custom_emoji: Käytä mukautettuja emojeita + enable_user: Tili otettu käyttöön + promote_user: Käyttäjä ylennetty + remove_avatar_user: Profiilikuvan poisto + silence_account: Hiljennä tili actions: assigned_to_self_report: "%{name} otti raportin %{target} tehtäväkseen" change_email_user: "%{name} vaihtoi käyttäjän %{target} sähköpostiosoitteen" @@ -192,8 +225,20 @@ fi: unsuspend_account: "%{name} perui käyttäjän %{target} jäähyn" update_custom_emoji: "%{name} päivitti emojin %{target}" update_status: "%{name} päivitti käyttäjän %{target} tilan" + deleted_status: "(poistettu tilapäivitys)" + empty: Lokeja ei löytynyt. + filter_by_action: Suodata tapahtuman mukaan + filter_by_user: Suodata käyttäjän mukaan title: Auditointiloki announcements: + destroyed_msg: Ilmoitus poistettu onnistuneesti! + edit: + title: Muokkaa ilmoitusta + empty: Yhtään ilmoitusta ei löytynyt. + new: + create: Luo ilmoitus + title: Uusi ilmoitus + published_msg: Ilmoitus julkaistu onnistuneesti! title: Ilmoitukset custom_emojis: assign_category: Aseta kategoria @@ -217,6 +262,7 @@ fi: listed: Listassa new: title: Lisää uusi mukautettu emoji + not_permitted: Sinulla ei ole oikeutta suorittaa tätä toimintoa overwrite: Kirjoita yli shortcode: Lyhennekoodi shortcode_hint: Vähintään kaksi merkkiä, vain kirjaimia, numeroita ja alaviivoja @@ -234,7 +280,18 @@ fi: feature_invites: Kutsulinkit feature_profile_directory: Profiilihakemisto feature_registrations: Rekisteröitymiset + feature_spam_check: Roskapostin esto + feature_timeline_preview: Aikajanan esikatselu + features: Ominaisuudet + recent_users: Viimeaikaiset käyttäjät + search: Haku koko tekstistä + software: Ohjelmisto + space: Tilankäyttö title: Hallintapaneeli + total_users: käyttäjiä yhteensä + trends: Trendit + week_users_active: aktiivinen tällä viikolla + week_users_new: käyttäjiä tällä viikolla domain_blocks: add_new: Lisää uusi created_msg: Verkkotunnuksen estoa käsitellään @@ -249,8 +306,13 @@ fi: silence: Hiljennys suspend: Jäähy title: Uusi verkkotunnuksen esto + private_comment: Yksityinen kommentti + public_comment: Julkinen kommentti reject_media: Hylkää mediatiedostot reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla + severity: + silence: hiljennetty + suspend: jäähyllä show: affected_accounts: one: Vaikuttaa yhteen tiliin tietokannassa @@ -272,14 +334,33 @@ fi: title: Uusi sähköpostiestolistan merkintä title: Sähköpostiestolista instances: + moderation: + all: Kaikki + limited: Rajoitettu + title: Moderointi + private_comment: Yksityinen kommentti + public_comment: Julkinen kommentti title: Tiedossa olevat instanssit + total_blocked_by_us: Estetty meidän toimesta + total_followed_by_them: Heidän seuraama + total_followed_by_us: Meidän seuraama + total_storage: Medialiitteet invites: + deactivate_all: Poista kaikki käytöstä filter: all: Kaikki available: Saatavilla expired: Vanhentunut title: Suodata title: Kutsut + relays: + delete: Poista + disable: Poista käytöstä + disabled: Poistettu käytöstä + enable: Ota käyttöön + enabled: Käytössä + save_and_enable: Tallenna ja ota käyttöön + status: Tila report_notes: created_msg: Muistiinpano onnistuneesti lisätty raporttiin! destroyed_msg: Muistiinpano onnistuneesti poistettu raportista! @@ -318,11 +399,21 @@ fi: contact_information: email: Työsähköposti username: Yhteyshenkilön käyttäjänimi + custom_css: + title: Mukautettu CSS + domain_blocks: + all: Kaikille + disabled: Ei kenellekkään + title: Näytä domainestot + domain_blocks_rationale: + title: Näytä syy enable_bootstrap_timeline_accounts: title: Uudet käyttäjät seuraavat oletuksena tilejä hero: desc_html: Näytetään etusivulla. Suosituskoko vähintään 600x100 pikseliä. Jos kuvaa ei aseteta, käytetään instanssin pikkukuvaa title: Sankarin kuva + mascot: + title: Maskottikuva peers_api_enabled: desc_html: Verkkotunnukset, jotka tämä instanssi on kohdannut fediversumissa title: Julkaise löydettyjen instanssien luettelo @@ -336,6 +427,11 @@ fi: min_invite_role: disabled: Ei kukaan title: Salli kutsut käyttäjältä + registrations_mode: + modes: + approved: Rekisteröinti vaatii hyväksynnän + none: Kukaan ei voi rekisteröityä + open: Kaikki voivat rekisteröityä show_known_fediverse_at_about_page: desc_html: Kun tämä on valittu, esikatselussa näytetään tuuttaukset kaikkialta tunnetusta fediversumista. Muutoin näytetään vain paikalliset tuuttaukset. title: Näytä aikajanan esikatselussa koko tunnettu fediversumi @@ -348,6 +444,8 @@ fi: site_description_extended: desc_html: Hyvä paikka käytösohjeille, säännöille, ohjeistuksille ja muille instanssin muista erottaville asioille. HTML-tagit käytössä title: Omavalintaiset laajat tiedot + site_short_description: + title: Lyhyt instanssin kuvaus site_terms: desc_html: Tähän voi kirjoittaa instanssin tietosuojakäytännöstä, käyttöehdoista ja sen sellaisista asioista. HTML-tagit käytössä title: Omavalintaiset käyttöehdot @@ -359,24 +457,53 @@ fi: desc_html: Näytä julkinen aikajana aloitussivulla title: Aikajanan esikatselu title: Sivuston asetukset + trends: + title: Trendaavat aihetunnisteet + site_uploads: + delete: Poista ladattu tiedosto statuses: back_to_account: Takaisin tilin sivulle batch: delete: Poista nsfw_off: NSFW POIS nsfw_on: NSFW PÄÄLLÄ + deleted: Poistettu failed_to_execute: Suoritus epäonnistui + media: + title: Media no_media: Ei mediaa title: Tilin tilat with_media: Sisältää mediaa + tags: + context: Konteksti + last_active: Aktiivinen viimeksi + most_popular: Suosituimmat + most_recent: Viimeisimmät + name: Aihetunniste + reviewed: Tarkistetut + title: Aihetunnisteet + trending_right_now: Trendaa juuri nyt title: Ylläpito + warning_presets: + add_new: Lisää uusi + delete: Poista admin_mailer: new_report: body: "%{reporter} on raportoinut kohteen %{target}" body_remote: Joku osoitteesta %{domain} on raportoinut kohteen %{target} subject: Uusi raportti instanssista %{instance} (nro %{id}) + aliases: + add_new: Luo alias + empty: Sinulla ei ole aliaksia. + remove: Poista aliaksen linkitys + appearance: + localization: + body: Mastodonin ovat kääntäneet vapaaehtoiset. + guide_link_text: Kaikki voivat osallistua. + sensitive_content: Arkaluontoista sisältöä application_mailer: notification_preferences: Muuta sähköpostiasetuksia + salutation: "%{name}," settings: 'Muuta sähköpostiasetuksia: %{link}' view: 'Näytä:' view_profile: Näytä profiili @@ -390,9 +517,13 @@ fi: warning: Säilytä tietoa hyvin. Älä milloinkaan jaa sitä muille! your_token: Pääsytunnus auth: + apply_for_account: Pyydä kutsu change_password: Salasana delete_account: Poista tili delete_account_html: Jos haluat poistaa tilisi, <a href="%{path}">paina tästä</a>. Poisto on vahvistettava. + description: + prefix_sign_up: Liity Mastodoniin tänään! + suffix: Tilillä voit seurata ihmisiä, julkaista päivityksiä ja lähetellä viestejä muille käyttäjille miltä palvelimelta tahansa ja paljon muuta! didnt_get_confirmation: Etkö saanut vahvistusohjeita? forgot_password: Unohditko salasanasi? invalid_reset_password_token: Salasananpalautustunnus on virheellinen tai vanhentunut. Pyydä uusi. @@ -406,6 +537,10 @@ fi: reset_password: Palauta salasana security: Tunnukset set_new_password: Aseta uusi salasana + status: + account_status: Tilin tila + functional: Tilisi on täysin toimiva. + trouble_logging_in: Ongelmia kirjautumisessa? authorize_follow: already_following: Sinä seuraat jo tätä tiliä error: Valitettavasti etätilin haussa tapahtui virhe @@ -417,6 +552,8 @@ fi: return: Palaa käyttäjän profiiliin web: Siirry verkkosivulle title: Seuraa käyttäjää %{acct} + challenge: + confirm: Jatka datetime: distance_in_words: about_x_hours: "%{count} h" @@ -435,6 +572,16 @@ fi: confirm_password: Tunnistaudu syöttämällä nykyinen salasanasi proceed: Poista tili success_msg: Tilin poisto onnistui + warning: + more_details_html: Lisätietoja saat <a href="%{terms_path}">tietosuojakäytännöstämme</a>. + username_available: Käyttäjänimesi tulee saataville uudestaan + username_unavailable: Käyttäjänimesi ei tule saataville enää uudestaan + directories: + directory: Profiilihakemisto + explanation: Löydä käyttäjiä hiedän kiinnostuksiensa kautta + explore_mastodon: Tutki %{title} + domain_validator: + invalid_domain: ei ole kelvollinen toimialueen nimi errors: '400': The request you submitted was invalid or malformed. '403': Sinulla ei ole lupaa nähdä tätä sivua. @@ -459,14 +606,44 @@ fi: request: Pyydä arkisto size: Koko blocks: Estot + lists: Listat mutes: Mykistetyt storage: Media-arkisto + featured_tags: + add_new: Lisää uusi + filters: + contexts: + account: Profiilit + home: Kotiaikajana + notifications: Ilmoitukset + public: Julkiset aikajanat + thread: Keskustelut + edit: + title: Muokkaa suodatinta + index: + delete: Poista + empty: Sinulla ei ole suodattimia. + title: Suodattimet + new: + title: Lisää uusi suodatin + footer: + developers: Kehittäjille + more: Lisää… + resources: Resurssit + trending_now: Suosittua nyt generic: + all: Kaikki changes_saved_msg: Muutosten tallennus onnistui! + copy: Kopioi + delete: Poista + order_by: Järjestä save_changes: Tallenna muutokset validation_errors: one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe other: Kaikki ei ole aivan oikein! Tarkasta alla olevat %{count} virhettä + identity_proofs: + active: Aktiivinen + authorize: Kyllä, valtuuta imports: preface: Voit tuoda toisesta instanssista viemiäsi tietoja, kuten esimerkiksi seuraamiesi tai estämiesi henkilöiden listan. success: Tietojen lähettäminen onnistui, ja ne käsitellään kohtapuoliin @@ -506,6 +683,16 @@ fi: too_many: Tiedostoja voi liittää enintään 4 migrations: acct: uuden tilin käyttäjätunnus@verkkotunnus + errors: + move_to_self: ei voi olla nykyinen tili + not_found: ei voitu löytää + on_cooldown: Sinä olet jäähyllä + followers_count: Seuraajat muuton aikana + past_migrations: Edelliset migraatiot + proceed_with_move: Siirrä seuraajat + set_redirect: Aseta uudelleenohjaus + warning: + before: 'Ennen jatkamista, lue nämä huomautukset huolellisesti:' moderation: title: Moderointi notification_mailer: @@ -548,6 +735,7 @@ fi: format: "%n %u" units: billion: Mrd + million: M quadrillion: Brd thousand: k trillion: B @@ -556,8 +744,22 @@ fi: next: Seuraava older: Vanhemmat prev: Edellinen + polls: + errors: + duration_too_long: on liian kaukana tulevaisuudessa + duration_too_short: on liian aikainen + expired: Äänestys on jo loppunut preferences: other: Muut + public_timelines: Julkiset aikajanat + reactions: + errors: + unrecognized_emoji: ei ole tunnistettu emoji + relationships: + activity: Tilin tapahtumat + followers: Seuraajat + following: Seuratut + invited: Kutsuttu remote_follow: acct: Syötä se käyttäjätunnus@verkkotunnus, josta haluat seurata missing_resource: Vaadittavaa uudelleenohjaus-URL:ää tiliisi ei löytynyt @@ -567,27 +769,62 @@ fi: activity: Viimeisin toiminta browser: Selain browsers: + alipay: Alipay + blackberry: Blackberry + chrome: Chrome + edge: Microsoft Edge + electron: Electron + firefox: Firefox generic: Tuntematon selain + ie: Internet Explorer + micro_messenger: MicroMessenger nokia: Nokia S40 Ovi -selain + opera: Opera + otter: Otter + phantom_js: PhantomJS + qq: QQ Browser + safari: Safari + uc_browser: UCBrowser + weibo: Weibo current_session: Nykyinen istunto description: "%{browser}, %{platform}" explanation: Nämä verkkoselaimet ovat tällä hetkellä kirjautuneet Mastodon-tilillesi. + ip: IP-osoite platforms: + adobe_air: Adobe Air + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS + ios: iOS + linux: Linux + mac: macOS other: tuntematon järjestelmä + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone revoke: Hylkää revoke_success: Istunnon hylkäys onnistui title: Istunnot settings: + account: Tili + account_settings: Tilin asetukset + aliases: Tilin aliakset + appearance: Ulkoasu authorized_apps: Valtuutetut sovellukset back: Takaisin Mastodoniin delete: Tilin poisto development: Kehittäminen edit_profile: Muokkaa profiilia export: Vie tietoja + featured_tags: Esitellyt aihetunnisteet import: Tuo + import_and_export: Tuo / Vie migrate: Tilin muutto muualle notifications: Ilmoitukset preferences: Ominaisuudet + profile: Profiili + relationships: Seurattavat ja seuraajat two_factor_authentication: Kaksivaiheinen todentaminen statuses: attached: @@ -599,6 +836,7 @@ fi: disallowed_hashtags: one: 'sisälsi aihetunnisteen jota ei sallita: %{tags}' other: 'sisälsi aihetunnisteet joita ei sallita: %{tags}' + language_detection: Tunnista kieli automaattisesti open_in_web: Avaa selaimessa over_character_limit: merkkimäärän rajoitus %{max} ylitetty pin_errors: @@ -606,7 +844,17 @@ fi: ownership: Muiden tuuttauksia ei voi kiinnittää private: Piilotettua tuuttausta ei voi kiinnittää reblog: Buustausta ei voi kiinnittää + poll: + total_people: + one: "%{count} henkilö" + other: "%{count} henkilöä" + total_votes: + one: "%{count} ääni" + other: "%{count} ääntä" + vote: Äänestä show_more: Näytä lisää + show_thread: Näytä ketju + sign_in_to_participate: Kirjaudu sisään osallistuaksesi keskusteluun title: "%{name}: â€%{quote}â€" visibilities: private: Vain seuraajille @@ -627,21 +875,14 @@ fi: formats: default: "%d.%m.%Y klo %H.%M" two_factor_authentication: - code_hint: Vahvista syöttämällä todentamissovelluksen generoima koodi - description_html: Jos otat käyttöön <strong>kaksivaiheisen todentamisen</strong>, kirjautumiseen vaaditaan puhelin, jolla voidaan luoda kirjautumistunnuksia. disable: Poista käytöstä - enable: Ota käyttöön enabled: Kaksivaiheinen todentaminen käytössä enabled_success: Kaksivaiheisen todentamisen käyttöönotto onnistui generate_recovery_codes: Luo palautuskoodit - instructions_html: "<strong>Lue tämä QR-koodi puhelimen Google Authenticator- tai vastaavalla TOTP-sovelluksella</strong>. Sen jälkeen sovellus luo tunnuksia, joita tarvitset sisäänkirjautuessasi." lost_recovery_codes: Palautuskoodien avulla voit käyttää tiliä, jos menetät puhelimesi. Jos olet hukannut palautuskoodit, voit luoda uudet tästä. Vanhat palautuskoodit poistetaan käytöstä. - manual_instructions: 'Jos et voi lukea QR-koodia ja haluat syöttää sen käsin, tässä on salainen koodi tekstinä:' recovery_codes: Varapalautuskoodit recovery_codes_regenerated: Uusien palautuskoodien luonti onnistui recovery_instructions_html: Jos menetät puhelimesi, voit kirjautua tilillesi jollakin alla olevista palautuskoodeista. <strong>Pidä palautuskoodit hyvässä tallessa</strong>. Voit esimerkiksi tulostaa ne ja säilyttää muiden tärkeiden papereiden joukossa. - setup: Ota käyttöön - wrong_code: Annettu koodi oli virheellinen! Ovatko palvelimen aika ja laitteen aika oikein? user_mailer: backup_ready: explanation: Pyysit täydellistä varmuuskopiota Mastodon-tilistäsi. Voit nyt ladata sen! diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 224fefd9e8f36b4cddcb704b3c29822704749e15..0c96d462d7de88cb3192fca5d4d92a87719959e5 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -15,7 +15,7 @@ fr: browse_public_posts: Parcourir un flux en direct de messages publics sur Mastodon contact: Contact contact_missing: Non défini - contact_unavailable: N/D + contact_unavailable: Non disponible discover_users: Découvrez des utilisateur·rice·s documentation: Documentation federation_hint_html: Avec un compte sur %{instance}, vous pourrez suivre les gens sur n’importe quel serveur Mastodon et au-delà . @@ -33,14 +33,14 @@ fr: one: statut other: statuts status_count_before: Ayant publié - tagline: Suivez vos ami·e·s et découvrez-en de nouveaux·elles + tagline: Suivez vos ami·e·s et découvrez en de nouveaux·elles terms: Conditions d’utilisation - unavailable_content: Contenu non disponible + unavailable_content: Serveurs modérés unavailable_content_description: domain: Serveur reason: Motif rejecting_media: 'Les fichiers média de ces serveurs ne seront pas traités ou stockés et aucune miniature ne sera affichée, nécessitant un clic vers le fichier d’origine :' - rejecting_media_title: Média filtré + rejecting_media_title: Médias filtrés silenced: 'Les messages de ces serveurs seront cachés des flux publics et conversations, et les interactions de leurs utilisateur·rice·s ne donneront lieu à aucune notification, à moins que vous ne les suiviez :' silenced_title: Serveurs masqués suspended: 'Aucune donnée venant de ces serveurs ne sera traitée, stockée ou échangée, rendant toute interaction ou communication avec les utilisateur·rice·s de ces serveurs impossible :' @@ -60,6 +60,7 @@ fr: one: Abonné·e other: Abonné·e·s following: Abonnements + instance_actor_flash: Ce compte est un acteur virtuel utilisé pour représenter le serveur lui-même et non un utilisateur individuel. Il est utilisé à des fins de fédération et ne doit pas être suspendu. joined: Inscrit·e en %{date} last_active: dernière activité link_verified_on: La propriété de ce lien a été vérifiée le %{date} @@ -98,6 +99,7 @@ fr: add_email_domain_block: Mettre le domaine du courriel sur liste noire approve: Approuver approve_all: Tout approuver + approved_msg: La demande d’inscription de %{username} a été approuvée avec succès are_you_sure: Voulez-vous vraiment faire ça ? avatar: Avatar by_domain: Domaine @@ -111,8 +113,10 @@ fr: confirm: Confirmer confirmed: Confirmé confirming: Confirmation + delete: Supprimer les données deleted: Supprimé demote: Rétrograder + destroyed_msg: Les données de %{username} sont maintenant en file d’attente pour être supprimées imminemment disable: Désactiver disable_two_factor_authentication: Désactiver l’authentification à deux facteurs disabled: Désactivé @@ -123,10 +127,12 @@ fr: email_status: État du courriel enable: Activer enabled: Activé + enabled_msg: Le compte de %{username} a été débloqué avec succès followers: Abonné·e·s follows: Abonnements header: Entête inbox_url: URL d’entrée + invite_request_text: Raisons de l’adhésion invited_by: Invité par ip: Adresse IP joined: Inscrit·e depuis @@ -138,6 +144,8 @@ fr: login_status: Statut de connexion media_attachments: Fichiers médias memorialize: Convertir en mémorial + memorialized: Mémorialisé + memorialized_msg: Transformation réussie de %{username} en un compte mémorial moderation: active: Actif·ve·s all: Tous @@ -158,10 +166,14 @@ fr: public: Publique push_subscription_expires: Expiration de l’abonnement PuSH redownload: Rafraîchir le profil + redownloaded_msg: Le profil de %{username} a été actualisé avec succès depuis l’origine reject: Rejeter reject_all: Tout rejeter + rejected_msg: La demande d’inscription de %{username} a été rejetée avec succès remove_avatar: Supprimer l’avatar remove_header: Supprimer l’entête + removed_avatar_msg: L’avatar de %{username} a été supprimé avec succès + removed_header_msg: L’image d’en-tête de %{username} a été supprimée avec succès resend_confirmation: already_confirmed: Cet·te utilisateur·rice est déjà confirmé·e send: Renvoyer un courriel de confirmation @@ -178,6 +190,8 @@ fr: search: Rechercher search_same_email_domain: Autres utilisateurs·trices avec le même domaine de courriel search_same_ip: Autres utilisateur·rice·s avec la même IP + sensitive: Sensible + sensitized: marqué comme sensible shared_inbox_url: URL de la boite de réception partagée show: created_reports: Signalements faits @@ -187,13 +201,19 @@ fr: statuses: Statuts subscribe: S’abonner suspended: Suspendu + suspension_irreversible: Les données de ce compte ont été irréversiblement supprimées. Vous pouvez annuler la suspension du compte pour le rendre utilisable, mais il ne récupérera aucune donnée qu’il avait auparavant. + suspension_reversible_hint_html: Le compte a été suspendu et les données seront complètement supprimées le %{date}. D’ici là , le compte peut être restauré sans aucun effet néfaste. Si vous souhaitez supprimer toutes les données du compte immédiatement, vous pouvez le faire ci-dessous. time_in_queue: En file d’attente %{time} title: Comptes unconfirmed_email: Courriel non confirmé + undo_sensitized: Annuler sensible undo_silenced: Ne plus masquer undo_suspension: Annuler la suspension + unsilenced_msg: Le compte de %{username} a été illimité avec succès unsubscribe: Se désabonner + unsuspended_msg: Le compte de %{username} a été désuspendu avec succès username: Nom d’utilisateur·ice + view_domain: Voir le résumé du domaine warn: Avertissement web: Web whitelisted: Sur liste blanche @@ -208,12 +228,14 @@ fr: create_domain_allow: Créer un domaine autorisé create_domain_block: Créer un blocage de domaine create_email_domain_block: Créer un blocage de domaine de courriel + create_ip_block: Créer une règle IP demote_user: Rétrograder l’utilisateur·ice destroy_announcement: Supprimer l’annonce destroy_custom_emoji: Supprimer des émojis personnalisés destroy_domain_allow: Supprimer le domaine autorisé destroy_domain_block: Supprimer le blocage de domaine destroy_email_domain_block: Supprimer le blocage de domaine de courriel + destroy_ip_block: Supprimer la règle IP destroy_status: Supprimer le statut disable_2fa_user: Désactiver l’A2F disable_custom_emoji: Désactiver les émojis personnalisés @@ -226,13 +248,16 @@ fr: reopen_report: Rouvrir le signalement reset_password_user: Réinitialiser le mot de passe resolve_report: Résoudre le signalement + sensitive_account: Marquer les médias de votre compte comme sensibles silence_account: Masque le compte suspend_account: Suspendre le compte unassigned_report: Ne plus assigner le signalement + unsensitive_account: Ne pas marquer les médias de votre compte comme sensibles unsilence_account: Ne plus masquer le compte unsuspend_account: Annuler la suspension du compte update_announcement: Modifier l’annonce update_custom_emoji: Mettre à jour les émojis personnalisés + update_domain_block: Mettre à jour le blocage de domaine update_status: Mettre à jour le statut actions: assigned_to_self_report: "%{name} s’est assigné·e le signalement de %{target}" @@ -244,12 +269,14 @@ fr: create_domain_allow: "%{name} a inscrit le domaine %{target} sur liste blanche" create_domain_block: "%{name} a bloqué le domaine %{target}" create_email_domain_block: "%{name} a mis le domaine de courriel %{target} sur liste noire" + create_ip_block: "%{name} a créé une règle pour l’IP %{target}" demote_user: "%{name} a rétrogradé l’utilisateur·rice %{target}" destroy_announcement: "%{name} a supprimé l’annonce %{target}" destroy_custom_emoji: "%{name} a détruit l’émoticône %{target}" destroy_domain_allow: "%{name} a supprimé le domaine %{target} de la liste blanche" destroy_domain_block: "%{name} a débloqué le domaine %{target}" destroy_email_domain_block: "%{name} a mis le domaine de courriel %{target} sur liste blanche" + destroy_ip_block: "%{name} a supprimé la règle pour l’IP %{target}" destroy_status: "%{name} a enlevé le statut de %{target}" disable_2fa_user: "%{name} a désactivé l’authentification à deux facteurs pour l’utilisateur·rice %{target}" disable_custom_emoji: "%{name} a désactivé l’émoji %{target}" @@ -262,13 +289,16 @@ fr: reopen_report: "%{name} a rouvert le signalement %{target}" reset_password_user: "%{name} a réinitialisé le mot de passe de %{target}" resolve_report: "%{name} a résolu le signalement %{target}" + sensitive_account: "%{name} a marqué le média de %{target} comme sensible" silence_account: "%{name} a masqué le compte de %{target}" suspend_account: "%{name} a suspendu le compte %{target}" unassigned_report: "%{name} a désassigné le signalement %{target}" + unsensitive_account: "%{name} a enlevé le marquage du média de %{target} comme sensible" unsilence_account: "%{name} ne masque plus le compte de %{target}" unsuspend_account: "%{name} a réactivé le compte de %{target}" update_announcement: "%{name} a actualisé l’annonce %{target}" update_custom_emoji: "%{name} a mis à jour l’émoji %{target}" + update_domain_block: "%{name} a mis à jour le blocage de domaine pour %{target}" update_status: "%{name} a mis à jour le statut de %{target}" deleted_status: "(statut supprimé)" empty: Aucun journal trouvé. @@ -372,6 +402,8 @@ fr: silence: Masqué suspend: Suspendre title: Nouveau blocage de domaine + obfuscate: Obfusquer le nom de domaine + obfuscate_hint: Obfusquer partiellement le nom de domaine dans la liste si la liste des limitations de domaine est activée private_comment: Commentaire privé private_comment_hint: Commenter sur cette limitation de domaine pour informer les modérateurs internes. public_comment: Commentaire public @@ -411,6 +443,7 @@ fr: instances: by_domain: Domaine delivery_available: Livraison disponible + empty: Aucun domaine trouvé. known_accounts: one: "%{count} compte connu" other: "%{count} comptes connus" @@ -434,6 +467,21 @@ fr: expired: Expiré title: Filtre title: Invitations + ip_blocks: + add_new: Créer une règle + created_msg: Nouvelle règle IP ajoutée avec succès + delete: Supprimer + expires_in: + '1209600': 2 semaines + '15778476': 6 mois + '2629746': 1 mois + '31556952': 1 an + '86400': 1 jour + '94670856': 3 ans + new: + title: Créer une nouvelle règle IP + no_ip_block_selected: Aucune règle IP n’a été modifiée car aucune n’a été sélectionnée + title: Règles IP pending_accounts: title: Comptes en attente (%{count}) relationships: @@ -473,6 +521,8 @@ fr: comment: none: Aucun created_at: Signalé + forwarded: Transféré + forwarded_to: Transféré à %{domain} mark_as_resolved: Marquer comme résolu mark_as_unresolved: Marquer comme non-résolu notes: @@ -516,6 +566,7 @@ fr: domain_blocks_rationale: title: Montrer la raison enable_bootstrap_timeline_accounts: + desc_html: Faire suivre automatiquement les comptes configurés aux nouveaux·lles utilisateurs·rices afin que leur flux personnel ne démarre pas vide title: Activer les abonnements par défaut pour les nouveaux·elles utilisateur·rice·s hero: desc_html: Affichée sur la page d’accueil. Au moins 600x100px recommandé. Lorsqu’elle n’est pas définie, se rabat sur la vignette du serveur @@ -527,7 +578,7 @@ fr: desc_html: Noms des domaines que ce serveur a découvert dans le fediverse title: Publier la liste des serveurs découverts preview_sensitive_media: - desc_html: Les liens de prévisualisation sur les autres sites web afficheront une vignette même si le média est sensible + desc_html: Les aperçus de lien sur les autres sites web afficheront une vignette même si les médias sont marqués comme sensibles title: Montrer les médias sensibles dans les prévisualisations OpenGraph profile_directory: desc_html: Permettre aux utilisateur·ice·s d’être découvert·e·s @@ -542,6 +593,9 @@ fr: min_invite_role: disabled: Personne title: Autoriser les invitations par + require_invite_text: + desc_html: Lorsque les enregistrements nécessitent une approbation manuelle, rendre le texte de l’invitation "Pourquoi voulez-vous vous inscrire ?" obligatoire plutôt que facultatif + title: Exiger que les nouveaux utilisateurs remplissent un texte de demande d’invitation registrations_mode: modes: approved: Approbation requise pour s’inscrire @@ -599,7 +653,7 @@ fr: no_media: Aucun média no_status_selected: Aucun statut n’a été modifié car aucun n’a été sélectionné title: Statuts du compte - with_media: avec médias + with_media: Avec médias tags: accounts_today: Utilisations uniques aujourd'hui accounts_week: Utilisation unique cette semaine @@ -681,8 +735,11 @@ fr: prefix_sign_up: Inscrivez-vous aujourd’hui sur Mastodon ! suffix: Avec un compte, vous pourrez suivre des gens, publier des statuts et échanger des messages avec les utilisateur·rice·s de n'importe quel serveur Mastodon et bien plus ! didnt_get_confirmation: Vous n’avez pas reçu les consignes de confirmation ? + dont_have_your_security_key: Vous n'avez pas votre clé de sécurité? forgot_password: Mot de passe oublié ? invalid_reset_password_token: Le lien de réinitialisation du mot de passe est invalide ou a expiré. Merci de réessayer. + link_to_otp: Entrez un code à deux facteurs de votre téléphone ou un code de récupération + link_to_webauth: Utilisez votre appareil de clé de sécurité login: Se connecter logout: Se déconnecter migrate_account: Déménager vers un compte différent @@ -707,7 +764,9 @@ fr: functional: Votre compte est entièrement opérationnel. pending: Votre demande est en attente d'examen par notre personnel. Cela peut prendre un certain temps. Vous recevrez un courriel si votre demande est approuvée. redirecting_to: Votre compte est inactif car il est actuellement redirigé vers %{acct}. + too_fast: Formulaire envoyé trop rapidement, veuillez réessayer. trouble_logging_in: Vous avez un problème pour vous connecter ? + use_security_key: Utiliser la clé de sécurité authorize_follow: already_following: Vous suivez déjà ce compte already_requested: Vous avez déjà envoyé une demande d’abonnement à ce compte @@ -732,6 +791,7 @@ fr: date: formats: default: "%d %b %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count} h" @@ -796,6 +856,7 @@ fr: request: Demandez vos archives size: Taille blocks: Vous bloquez + bookmarks: Signets csv: CSV domain_blocks: Bloqueurs de domaine lists: Listes @@ -809,7 +870,7 @@ fr: filters: contexts: account: Profils - home: Accueil + home: Accueil et listes notifications: Notifications public: Fils publics thread: Conversations @@ -863,6 +924,8 @@ fr: status: État de la vérification view_proof: Voir la preuve imports: + errors: + over_rows_processing_limit: contient plus de %{count} lignes modes: merge: Fusionner merge_long: Garder les enregistrements existants et ajouter les nouveaux @@ -872,6 +935,7 @@ fr: success: Vos données ont été importées avec succès et seront traitées en temps et en heure types: blocking: Liste de comptes bloqués + bookmarks: Signets domain_blocking: Liste des serveurs bloqués following: Liste d’utilisateur·rice·s suivi·e·s muting: Liste d’utilisateur·rice·s que vous masquez @@ -992,6 +1056,14 @@ fr: quadrillion: P thousand: K trillion: T + otp_authentication: + code_hint: Entrez le code généré par votre application d'authentification pour confirmer + description_html: Si vous activez <strong>l’authentification à deux facteurs</strong> en utilisant une application d'authentification, votre connexion vous imposera d'être en possession de votre téléphone, ce qui génèrera des jetons que vous devrez saisir. + enable: Activer + instructions_html: "<strong>Scannez ce code QR dans Google Authenticator ou une application TOTP similiaire sur votre téléphone</strong>. À partir de maintenant, cette application générera des jetons que vous devrez entrer lorsque vous vous connecterez." + manual_instructions: 'Si vous ne pouvez pas scanner le QR code et que vous devez le saisir manuellement, voici le texte secret en brut :' + setup: Mise en place + wrong_code: Le code saisi est invalide. L'heure du serveur et l'heure de l'appareil sont-ils corrects ? pagination: newer: Plus récent next: Suivant @@ -1020,6 +1092,7 @@ fr: relationships: activity: Activité du compte dormant: Dormant + follow_selected_followers: Suivre les abonné·e·s sélectionné·e·s followers: Abonné·e·s following: Abonnements invited: Invité·e @@ -1035,7 +1108,7 @@ fr: status: État du compte remote_follow: acct: Entrez l’adresse profil@serveur depuis laquelle vous voulez effectuer cette action - missing_resource: L’URL de redirection n’a pas pu être trouvée + missing_resource: L’URL de redirection requise pour votre compte n’a pas pu être trouvée no_account_html: Vous n’avez pas de compte ? Vous pouvez <a href='%{sign_up_path}' target='_blank'>vous inscrire ici</a> proceed: Confirmer l’abonnement prompt: 'Vous allez suivre :' @@ -1116,6 +1189,7 @@ fr: profile: Profil relationships: Abonnements et abonné·e·s two_factor_authentication: Identification à deux facteurs + webauthn_authentication: Clés de sécurité spam_check: spam_detected: Ceci est un rapport automatisé. Des pollupostages ont été détectés. statuses: @@ -1154,6 +1228,8 @@ fr: other: "%{count} votes" vote: Voter show_more: Déplier + show_newer: Plus récents + show_older: Plus anciens show_thread: Afficher le fil de discussion sign_in_to_participate: Inscrivez-vous pour prendre part à la conversation title: '%{name} : "%{quote}"' @@ -1262,21 +1338,20 @@ fr: default: "%d %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Entrez le code généré par votre application pour confirmer - description_html: Si vous activez <strong>l’identification à deux facteurs</strong>, vous devrez être en possession de votre téléphone afin de générer un code de connexion. + add: Ajouter disable: Désactiver - enable: Activer + disabled_success: L'authentification à deux facteurs a été désactivée avec succès + edit: Modifier enabled: L’authentification à deux facteurs est activée enabled_success: Identification à deux facteurs activée avec succès generate_recovery_codes: Générer les codes de récupération - instructions_html: "<strong>Scannez ce QR code grâce à Google Authenticator, Authy ou une application similaire sur votre téléphone</strong>. Désormais, cette application génèrera des jetons que vous devrez saisir à chaque connexion." lost_recovery_codes: Les codes de récupération vous permettent de retrouver les accès à votre compte si vous perdez votre téléphone. Si vous perdez vos codes de récupération, vous pouvez les générer à nouveau ici. Vos anciens codes de récupération seront invalidés. - manual_instructions: 'Si vous ne pouvez pas scanner le code QR et devez l’entrer manuellement, voici le secret en texte-plein :' + methods: Méthodes à deux facteurs + otp: Application d'authentification recovery_codes: Codes de récupération recovery_codes_regenerated: Codes de récupération régénérés avec succès recovery_instructions_html: Si vous perdez l’accès à votre téléphone, vous pouvez utiliser un des codes de récupération ci-dessous pour retrouver l’accès à votre compte. <strong>Conservez les codes de récupération en sécurité</strong>. Par exemple, en les imprimant et en les stockant avec vos autres documents importants. - setup: Installer - wrong_code: Les codes entrés sont incorrects ! L’heure du serveur et celle de votre appareil sont-elles correctes ? + webauthn: Clés de sécurité user_mailer: backup_ready: explanation: Vous avez demandé une sauvegarde complète de votre compte Mastodon. Elle est maintenant prête à être téléchargée ! @@ -1291,6 +1366,7 @@ fr: warning: explanation: disable: Lorsque votre compte est gelé, les données de votre compte demeurent intactes, mais vous ne pouvez effectuer aucune action jusqu’à ce qu’il soit débloqué. + sensitive: Vos fichiers médias téléversés et vos médias liés seront traités comme sensibles. silence: Lorsque votre compte est limité, seul·e·s les utilisateur·rice·s qui vous suivent déjà verront vos pouets sur ce serveur, et vous pourriez être exclu de plusieurs listes publiques. Néanmoins, d’autres utilisateur·rice·s peuvent vous suivre manuellement. suspend: Votre compte a été suspendu, et tous vos pouets et vos fichiers multimédia téléversés ont été supprimés irréversiblement de ce serveur, et des serveurs où vous aviez des abonné·e·s. get_in_touch: Vous pouvez répondre à cette adresse pour entrer en contact avec l’équipe de %{instance}. @@ -1299,11 +1375,13 @@ fr: subject: disable: Votre compte %{acct} a été gelé none: Avertissement pour %{acct} + sensitive: Les médias publiés depuis votre compte %{acct} ont été marqués comme étant sensibles silence: Votre compte %{acct} a été limité suspend: Votre compte %{acct} a été suspendu title: disable: Compte gelé none: Avertissement + sensitive: Vos médias ont été marqués comme sensibles silence: Compte limité suspend: Compte suspendu welcome: @@ -1324,9 +1402,11 @@ fr: tips: Astuces title: Bienvenue à bord, %{name} ! users: + blocked_email_provider: Ce fournisseur de courriel n'est pas autorisé follow_limit_reached: Vous ne pouvez pas suivre plus de %{limit} personnes generic_access_help_html: Rencontrez-vous des difficultés d’accès à votre compte ? Vous pouvez contacter %{email} pour obtenir de l’aide invalid_email: L’adresse courriel est invalide + invalid_email_mx: L’adresse courriel n’existe pas invalid_otp_token: Le code d’authentification à deux facteurs est invalide invalid_sign_in_token: Code de sécurité non valide otp_lost_help_html: Si vous perdez accès aux deux, vous pouvez contacter %{email} @@ -1336,3 +1416,20 @@ fr: verification: explanation_html: 'Vous pouvez <strong>vous vérifier en tant que propriétaire des liens dans les métadonnées de votre profil</strong>. Pour cela, le site web lié doit contenir un lien vers votre profil Mastodon. Le lien de retour <strong>doit</strong> avoir un attribut <code>rel="me"</code> . Le texte du lien n’a pas d’importance. Voici un exemple :' verification: Vérification + webauthn_credentials: + add: Ajouter une nouvelle clé de sécurité + create: + error: Il y a eu un problème en ajoutant votre clé de sécurité. Veuillez réessayer. + success: Votre clé de sécurité a été ajoutée avec succès. + delete: Supprimer + delete_confirmation: Êtes-vous sûr de vouloir supprimer cette clé de sécurité ? + description_html: Si vous activez l' <strong>authentification de la clé de sécurité</strong>, la connexion vous demandera d'utiliser l'une de vos clés de sécurité. + destroy: + error: Il y a eu un problème en supprimant votre clé de sécurité. Veuillez réessayer. + success: Votre clé de sécurité a été supprimée avec succès. + invalid_credential: Clé de sécurité invalide + nickname_hint: Entrez le surnom de votre nouvelle clé de sécurité + not_enabled: Vous n'avez pas encore activé WebAuthn + not_supported: Ce navigateur ne prend pas en charge les clés de sécurité + otp_required: Pour utiliser les clés de sécurité, veuillez d'abord activer l'authentification à deux facteurs. + registered_on: Inscrit le %{date} diff --git a/config/locales/gl.yml b/config/locales/gl.yml index c2fb18d5743e9d48c6bcfe134ffaabf385c4d8bb..48aaff0ad3da30c9a86c896c636af91aa1895431 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -21,7 +21,9 @@ gl: federation_hint_html: Cunha conta en %{instance} poderás seguir ás persoas en calquera servidor do Mastodon e alén. get_apps: Probar unha aplicación móbil hosted_on: Mastodon aloxado en %{domain} - instance_actor_flash: Esta conta é un actor virtual utilizado para representar ao servidor e non a unha usuaria individual. UtilÃzase para propósitos de federación e non deberÃa estar bloqueada a menos que queiras bloquear a toda a instancia, en tal caso deberÃas utilizar o bloqueo do dominio. + instance_actor_flash: 'Esta conta é un actor virtual utilizado para representar ao servidor e non a unha usuaria individual. UtilÃzase para propósitos de federación e non deberÃa estar bloqueada a menos que queiras bloquear a toda a instancia, en tal caso deberÃas utilizar o bloqueo do dominio. + +' learn_more: Saber máis privacy_policy: PolÃtica de privacidade see_whats_happening: Ver o que está a acontecer @@ -58,6 +60,7 @@ gl: one: Seguidora other: Seguidoras following: Seguindo + instance_actor_flash: Esta conta é un actor virtual utilizado para representar ó servidor mesmo e non a unha usuaria individual. UtilÃzase por motivos de federación e non deberÃa estar suspendida. joined: Uniuse en %{date} last_active: última actividade link_verified_on: A propiedade desta ligazón foi verificada en %{date} @@ -96,6 +99,7 @@ gl: add_email_domain_block: Bloquear o dominio do email approve: Aprobar approve_all: Aprobar todos + approved_msg: Aprobada a solicitude da aplicación de conexión de %{username} are_you_sure: Está segura? avatar: Imaxe de perfil by_domain: Dominio @@ -109,8 +113,10 @@ gl: confirm: Confirmar confirmed: Confirmado confirming: Estase a confirmar + delete: Eliminar datos deleted: Eliminado demote: Rebaixar + destroyed_msg: Os datos de %{username} están na cola para ser eliminados axiña disable: Desactivar disable_two_factor_authentication: Desactivar 2FA disabled: Desactivado @@ -121,10 +127,12 @@ gl: email_status: Estado do email enable: Activar enabled: Activado + enabled_msg: Desbloqueada a conta de %{username} followers: Seguidoras follows: Seguindo header: Cabeceira inbox_url: URL da caixa de entrada + invite_request_text: Razóns para unirte invited_by: Convidada por ip: IP joined: Uniuse @@ -136,6 +144,8 @@ gl: login_status: Estado da sesión media_attachments: Multimedia adxunta memorialize: Converter en lembranza + memorialized: Na lembranza + memorialized_msg: Convertiuse %{username} nunha conta para a lembranza moderation: active: Activa all: Todo @@ -156,10 +166,14 @@ gl: public: Público push_subscription_expires: A subscrición PuSH expira redownload: Actualizar perfil + redownloaded_msg: Actualizado o perfil de %{username} desde a orixe reject: Rexeitar reject_all: Rexeitar todo + rejected_msg: Rexeitada a solicitude da aplicación de conexión de %{username} remove_avatar: Eliminar imaxe de perfil remove_header: Eliminar cabeceira + removed_avatar_msg: Eliminado a imaxe de avatar de %{username} + removed_header_msg: Eliminada a imaxe de cabeceira de %{username} resend_confirmation: already_confirmed: Esta usuaria xa está confirmada send: Reenviar o email de confirmación @@ -176,22 +190,30 @@ gl: search: Procurar search_same_email_domain: Outras usuarias co mesmo dominio de email search_same_ip: Outras usuarias co mesmo IP + sensitive: Sensible + sensitized: marcado como sensible shared_inbox_url: URL da caixa de entrada compartida show: created_reports: Denuncias feitas targeted_reports: Denuncias feitas por outros - silence: Acalar - silenced: Acalada + silence: Silenciar + silenced: Silenciado statuses: Estados subscribe: Subscribirse suspended: Suspendida + suspension_irreversible: Elimináronse de xeito irreversible os datos desta conta. Podes reactivar a conta para facela usable novamente pero non recuperará os datos eliminados. + suspension_reversible_hint_html: Esta conta foi suspendida, e os datos serán totalmente eliminados o %{date}. Ata entón, a conta pode ser restaurada sen danos. Se desexas eliminar agora mesmo todos os datos da conta, podes facelo aquà embaixo. time_in_queue: Agardando na cola %{time} title: Contas unconfirmed_email: Email non confirmado + undo_sensitized: Desmarcar sensible undo_silenced: Desfacer acalar undo_suspension: Desfacer suspensión + unsilenced_msg: Retirado o lÃmite da conta %{username} unsubscribe: Desbotar a subscrición + unsuspended_msg: Desbloqueada a conta de %{username} username: Nome de usuaria + view_domain: Ver resumo para o dominio warn: Aviso web: Web whitelisted: Listaxe branca @@ -206,12 +228,14 @@ gl: create_domain_allow: Crear permiso de dominio create_domain_block: Crear bloqueo de dominio create_email_domain_block: Crear bloqueo de dominio de correo electrónico + create_ip_block: Crear regra IP demote_user: Degradar usuaria destroy_announcement: Eliminar anuncio destroy_custom_emoji: Eliminar emoticona personalizada destroy_domain_allow: Eliminar permiso de dominio destroy_domain_block: Eliminar bloqueo de dominio destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico + destroy_ip_block: Eliminar regra IP destroy_status: Eliminar estado disable_2fa_user: Desactivar 2FA disable_custom_emoji: Desactivar emoticona personalizada @@ -224,13 +248,16 @@ gl: reopen_report: Reabrir denuncia reset_password_user: Restabelecer contrasinal resolve_report: Resolver denuncia + sensitive_account: Marca o multimedia da túa conta como sensible silence_account: Silenciar conta suspend_account: Suspender conta unassigned_report: Desasignar denuncia + unsensitive_account: Retira a marca de sensible do multimedia da conta unsilence_account: Deixar de silenciar conta unsuspend_account: Retirar suspensión de conta update_announcement: Actualizar anuncio update_custom_emoji: Actualizar emoticona personalizada + update_domain_block: Actualizar bloqueo do dominio update_status: Actualizar estado actions: assigned_to_self_report: "%{name} atribuÃu a denuncia %{target} a el mesmo" @@ -242,12 +269,14 @@ gl: create_domain_allow: "%{name} engadiu á listaxe branca o dominio %{target}" create_domain_block: "%{name} bloqueou o dominio %{target}" create_email_domain_block: "%{name} engadiu á listaxe negra o dominio de email %{target}" + create_ip_block: "%{name} creou regra para IP %{target}" demote_user: "%{name} degradou a usuaria %{target}" destroy_announcement: "%{name} eliminou o anuncio %{target}" destroy_custom_emoji: "%{name} eliminou a emoticona %{target}" destroy_domain_allow: "%{name} eliminou o dominio %{target} da listaxe branca" destroy_domain_block: "%{name} desbloqueou o dominio %{target}" destroy_email_domain_block: "%{name} engadiu á lista branca o dominio de email %{target}" + destroy_ip_block: "%{name} eliminou regra para IP %{target}" destroy_status: "%{name} eliminou o estado de %{target}" disable_2fa_user: "%{name} desactivou o requirimento de dobre factor para a usuaria %{target}" disable_custom_emoji: "%{name} desactivou a emoticona %{target}" @@ -260,13 +289,16 @@ gl: reopen_report: "%{name} reabriu a denuncia %{target}" reset_password_user: "%{name} restableceu o contrasinal da usuaria %{target}" resolve_report: "%{name} resolveu a denuncia %{target}" + sensitive_account: "%{name} marcou o multimedia de %{target} como sensible" silence_account: "%{name} silenciou a conta de %{target}" suspend_account: "%{name} suspendeu a conta de %{target}" unassigned_report: "%{name} deixou de atribuÃr a denuncia %{target}" + unsensitive_account: "%{name} desmarcou o multimedia de %{target} como sensible" unsilence_account: "%{name} deixou de silenciar a conta de %{target}" unsuspend_account: "%{name} desactivou a suspensión da conta de %{target}" update_announcement: "%{name} actualizou o anuncio %{target}" update_custom_emoji: "%{name} actualizou a emoticona %{target}" + update_domain_block: "%{name} actualizou o bloqueo do dominio %{target}" update_status: "%{name} actualizou o estado de %{target}" deleted_status: "(estado eliminado)" empty: Non se atoparon rexistros. @@ -370,6 +402,8 @@ gl: silence: Silenciar suspend: Suspender title: Novo bloqueo de dominio + obfuscate: Ofuscar o nome de dominio + obfuscate_hint: Ofuscar parcialmente o nome do dominio na lista se está activada a publicación da lista de limitacións de dominio private_comment: Comentario privado private_comment_hint: Comentar sobre esta limitación de dominio para uso interno polos moderadores. public_comment: Comentario público @@ -409,6 +443,7 @@ gl: instances: by_domain: Dominio delivery_available: Entrega dispoñÃbel + empty: Non se atopan dominios. known_accounts: one: "%{count} conta coñecida" other: "%{count} contas coñecidas" @@ -432,6 +467,21 @@ gl: expired: Expirado title: Filtro title: Convites + ip_blocks: + add_new: Crear regra + created_msg: Engadeuse a nova regra IP + delete: Eliminar + expires_in: + '1209600': 2 semanas + '15778476': 6 meses + '2629746': 1 mes + '31556952': 1 ano + '86400': 1 dÃa + '94670856': 3 anos + new: + title: Crear nova regra IP + no_ip_block_selected: Non se cambiou ningunha regra iP porque non seleccionaches ningunha + title: Regras IP pending_accounts: title: Contas pendentes (%{count}) relationships: @@ -471,6 +521,8 @@ gl: comment: none: Ningún created_at: Denunciado + forwarded: Reenviado + forwarded_to: Reenviado a %{domain} mark_as_resolved: Marcar como resolto mark_as_unresolved: Marcar como non resolto notes: @@ -514,6 +566,7 @@ gl: domain_blocks_rationale: title: Amosar motivo enable_bootstrap_timeline_accounts: + desc_html: Facer que as novas usuarias sigan automáticamente certas contas para que asà a cronoloxÃa inicial non esté baleira title: Activar seguimentos por omisión para novas usuarias hero: desc_html: Amosado na páxina principal. Polo menos 600x100px recomendados. Se non está definido, estará por defecto a miniatura do servidor @@ -540,6 +593,9 @@ gl: min_invite_role: disabled: Ninguén title: Permitir convites por + require_invite_text: + desc_html: Cando os rexistros requiren aprobación manual, facer que o texto "Por que te queres rexistrar?" do convite sexa obrigatorio en lugar de optativo + title: Require que as novas usuarias completen solicitude de texto do convite registrations_mode: modes: approved: Precisa aprobación para rexistrarse @@ -585,7 +641,7 @@ gl: delete: Eliminar o ficheiro subido destroyed_msg: Eliminado correctamente o subido! statuses: - back_to_account: Voltar a páxina da conta + back_to_account: Volver a páxina da conta batch: delete: Eliminar nsfw_off: Marcar como non sensible @@ -679,8 +735,11 @@ gl: prefix_sign_up: RexÃstrate agora en Mastodon! suffix: Ao abrir unha conta, poderás seguir a xente, actualizacións das publicacións e intercambiar mensaxes coas usuarias de calquera servidor de Mastodon e moito máis! didnt_get_confirmation: Non recibeu as instruccións de confirmación? + dont_have_your_security_key: "¿Non tes a túa chave de seguridade?" forgot_password: Esqueceu o contrasinal? invalid_reset_password_token: O testemuño para restablecer o contrasinal non é válido ou caducou. Por favor solicite un novo. + link_to_otp: Escribe o código do segundo factor do móbil ou un código de recuperación + link_to_webauth: Usa o teu dispositivo de chave de seguridade login: Conectar logout: Desconectar migrate_account: Mover a unha conta diferente @@ -691,7 +750,7 @@ gl: saml: SAML register: Rexistro registration_closed: "%{instance} non está a aceptar novas usuarias" - resend_confirmation: Voltar a enviar intruccións de confirmación + resend_confirmation: Reenviar as intruccións de confirmación reset_password: Restablecer contrasinal security: Seguranza set_new_password: Estabelecer novo contrasinal @@ -705,7 +764,9 @@ gl: functional: A súa conta está totalmente operativa. pending: A túa aplicación está pendente de revisión. PoderÃanos levar algún tempo. Recibirás un correo se a aplicación está aprobada. redirecting_to: A túa conta está inactiva porque está redirixida a %{acct}. + too_fast: Formulario enviado demasiado rápido, inténtao outra vez. trouble_logging_in: Problemas para conectar? + use_security_key: Usa chave de seguridade authorize_follow: already_following: Xa está a seguir esta conta already_requested: Xa tes enviada unha solicitude de seguimento a esa conta @@ -730,6 +791,7 @@ gl: date: formats: default: "%d %b, %Y" + with_month_name: "%d %B, %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -794,6 +856,7 @@ gl: request: Solicite o ficheiro size: Tamaño blocks: Bloqueos + bookmarks: Marcadores csv: CSV domain_blocks: Bloqueos de dominio lists: Listaxes @@ -861,6 +924,8 @@ gl: status: Estado da validación view_proof: Ver proba imports: + errors: + over_rows_processing_limit: contén máis de %{count} filas modes: merge: Fusionar merge_long: Manter os rexistros actuais e engadir novos @@ -870,6 +935,7 @@ gl: success: Os seus datos foron correctamente subidos e serán procesados ao momento types: blocking: Lista de bloqueo + bookmarks: Marcadores domain_blocking: Lista de bloqueo de dominios following: Lista de seguimento muting: Lista de usuarias acaladas @@ -930,7 +996,7 @@ gl: warning: backreference_required: Tes que configurar primeiro a nova conta para referenciar hacia esta before: 'Antes de seguir, por favor lé estas notas con atención:' - cooldown: Tras a migración existe un perÃodo de calma durante o cal non poderás voltar a migrar de novo + cooldown: Tras a migración existe un perÃodo de calma durante o cal non poderás volver a migrar de novo disabled_account: Tras o cambio a túa conta actual non será totalmente usable, pero terás acceso a exportar os datos e tamén a reactivación. followers: Esta acción moverá todas as túas seguidoras desde a conta actual a nova conta only_redirect_html: De xeito alternativo, podes <a href="%{path}">simplemente por unha redirección no perfil</a>. @@ -990,6 +1056,14 @@ gl: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: Escribe o código creado pola app de autenticación para confirmar + description_html: Se activas a <strong>autenticación con dous factores</strong> utilizando unha app de autenticación, ó conectarte pedirémosche que teñas o móbil á man, para crear o código que precisas para conectarte. + enable: Activar + instructions_html: "<strong>Escanea este código QR na túa app TOTP no móbil ou Google Authenticator</strong>. A partir de agora, a app creará códigos que terás que escribir cando te conectes." + manual_instructions: 'Se non podes escanear o código QR e tes que escribilo á man, aquà tes o código en texto plano:' + setup: Configurar + wrong_code: O código escrito non é válido! ¿é correcta a hora no dispositivo e no servidor? pagination: newer: Máis novo next: Seguinte @@ -1018,6 +1092,7 @@ gl: relationships: activity: Actividade da conta dormant: En repouso + follow_selected_followers: Seguir seguidoras seleccionadas followers: Seguidoras following: Seguindo invited: Convidado @@ -1099,7 +1174,7 @@ gl: aliases: Alcumes da conta appearance: Aparencia authorized_apps: Apps autorizadas - back: Voltar a Mastodon + back: Volver a Mastodon delete: Eliminación da conta development: Desenvolvemento edit_profile: Editar perfil @@ -1114,6 +1189,7 @@ gl: profile: Perfil relationships: Seguindo e seguidoras two_factor_authentication: Validar Dobre Factor + webauthn_authentication: Chaves de seguridade spam_check: spam_detected: Esto é un informe automatizado. Detectouse Spam. statuses: @@ -1152,6 +1228,8 @@ gl: other: "%{count} votos" vote: Votar show_more: Mostrar máis + show_newer: Mostrar o máis novo + show_older: Mostrar o máis vello show_thread: Amosar fÃo sign_in_to_participate: Conéctese para participar na conversa title: '%{name}: "%{quote}"' @@ -1164,19 +1242,19 @@ gl: unlisted_long: Visible para calquera, pero non listado en liñas de tempo públicas stream_entries: pinned: Mensaxe fixada - reblogged: promovida + reblogged: comparteu sensitive_content: Contido sensible tags: does_not_match_previous_name: non concorda co nome anterior terms: body_html: | - <h2>Intimidade</h2> + <h2>Privacidade</h2> <h3 id="collect">Qué información recollemos?</h3> <ul> <li><em>Información básica da conta</em>: Se se rexistra en este servidor, pediráselle un nome de usuaria, un enderezo de correo electrónico e un contrasinal. De xeito adicional tamén poderá introducir información como un nome público e biografÃa, tamén subir unha fotografÃa de perfil e unha imaxe para a cabeceira. O nome de usuaria, o nome público, a biografÃa e as imaxes de perfil e cabeceira sempre se mostran publicamente.</li> - <li><em>Publicacións, seguimento e outra información pública</em>: O listado das persoas que segue é un listado público, o mesmo acontece coas súas seguidoras. Cando evÃa unha mensaxe, a data e hora gárdanse asà como o aplicativo que utilizou para enviar a mensaxe. As publicacións poderÃan conter ficheiros de medios anexos, como fotografÃas e vÃdeos. As publicacións públicas e as non listadas están dispoñibles de xeito público. Cando destaca unha publicación no seu perfil tamén é pública. As publicacións son enviadas as súas seguidoras, en algúns casos pode acontecer que estén en diferentes servidores e gárdanse copias neles. Cando elemina unha publicación tamén se envÃa as súas seguidoras. A acción de voltar a publicar ou marcar como favorita outra publicación sempre é pública.</li> - <li><em>Mensaxes directas e só para seguidoras</em>: Todas as mensaxes gárdanse e procésanse no servidor. As mensaxes só para seguidoras son entregadas as súas seguidoras e as usuarias que son mencionadas en elas, e as mensaxes directas entréganse só as usuarias mencionadas en elas. En algúns casos esto implica que son entregadas a diferentes servidores e gárdanse copias alÃ. Facemos un esforzo sincero para limitar o acceso a esas publicacións só as persoas autorizadas, pero outros servidores poderÃan non ser tan escrupulosos. Polo tanto, é importante revisar os servidores onde se hospedan as súas seguidoras. Nos axustes pode activar a opción de aprovar ou rexeitar novas seguidoras de xeito manual. <em>Teña en conta que a administración do servidor e todos os outros servidores implicados poden ver as mensaxes.</em>, e as destinatarias poderÃan facer capturas de pantalla, copiar e voltar a compartir as mensaxes. <em>Non comparta información comprometida en Mastodon.</em></li> + <li><em>Publicacións, seguimento e outra información pública</em>: O listado das persoas que segue é un listado público, o mesmo acontece coas súas seguidoras. Cando evÃa unha mensaxe, a data e hora gárdanse asà como o aplicativo que utilizou para enviar a mensaxe. As publicacións poderÃan conter ficheiros de medios anexos, como fotografÃas e vÃdeos. As publicacións públicas e as non listadas están dispoñibles de xeito público. Cando destaca unha publicación no seu perfil tamén é pública. As publicacións son enviadas as súas seguidoras, en algúns casos pode acontecer que estén en diferentes servidores e gárdanse copias neles. Cando elemina unha publicación tamén se envÃa as súas seguidoras. A acción de volver a publicar ou marcar como favorita outra publicación sempre é pública.</li> + <li><em>Mensaxes directas e só para seguidoras</em>: Todas as mensaxes gárdanse e procésanse no servidor. As mensaxes só para seguidoras son entregadas as súas seguidoras e as usuarias que son mencionadas en elas, e as mensaxes directas entréganse só as usuarias mencionadas en elas. En algúns casos esto implica que son entregadas a diferentes servidores e gárdanse copias alÃ. Facemos un esforzo sincero para limitar o acceso a esas publicacións só as persoas autorizadas, pero outros servidores poderÃan non ser tan escrupulosos. Polo tanto, é importante revisar os servidores onde se hospedan as súas seguidoras. Nos axustes pode activar a opción de aprovar ou rexeitar novas seguidoras de xeito manual. <em>Teña en conta que a administración do servidor e todos os outros servidores implicados poden ver as mensaxes.</em>, e as destinatarias poderÃan facer capturas de pantalla, copiar e volver a compartir as mensaxes. <em>Non comparta información comprometida en Mastodon.</em></li> <li><em>IPs e outros metadatos</em>: Cando se conecta, gravamos o IP desde onde se conecta, asà como o nome do aplicativo desde onde o fai. Todas as sesións conectadas están dispoñibles para revisar e revogar nos axustes. O último enderezo IP utilizado gárdase ate por 12 meses. Tamén poderiamos gardar informes do servidor que inclúan o enderezo IP de cada petición ao servidor.</li> </ul> @@ -1260,25 +1338,24 @@ gl: default: "%d %b, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Introducir o código xerado polo seu aplicativo de autenticación para confirmar - description_html: Se activa a <strong>autenticación de dobre factor</strong>, a conexión pediralle estar en posesión do seu teléfono, que creará testemuños para poder entrar. + add: Engadir disable: Deshabilitar - enable: Habilitar + disabled_success: Autenticación con doble factor desactivada + edit: Editar enabled: A autenticación de dobre-factor está activada enabled_success: Activouse con éxito a autenticación de dobre-factor generate_recovery_codes: Xerar códigos de recuperación - instructions_html: "<strong>Escanea este código QR en Google Authenticator ou aplicación TOTP no teu teléfono</strong>. Desde agora, esta aplicación proporcionará testemuños que debes introducir ao conectarte." lost_recovery_codes: Os códigos de recuperación permÃtenlle recuperar o acceso a súa conta si perde o teléfono. Si perde os códigos de recuperación, pode restauralos aquÃ. Os seus códigos de recuperación anteriores serán invalidados. - manual_instructions: 'Si non pode escanear o código QR e precisa introducilo manualmente, aquà está o testemuño secreto en texto plano:' + methods: Métodos para o segundo factor + otp: App autenticadora recovery_codes: Códigos de recuperación do respaldo recovery_codes_regenerated: Códigos de recuperación xerados correctamente recovery_instructions_html: Si perdese o acceso ao seu teléfono, pode utilizar un dos códigos inferiores de recuperación para recuperar o acceso a súa conta. <strong>Garde os códigos en lugar seguro</strong>. Por exemplo, pode imprimilos e gardalos xunto con outros documentos importantes. - setup: Configurar - wrong_code: O código introducido non é válido! Son correctas as horas no dispositivo e o servidor? + webauthn: Chaves de seguridade user_mailer: backup_ready: - explanation: Solicitou un respaldo completo da súa conta de Mastodon. Xa está listo para descargar! - subject: O seu ficheiro xa está listo para descargar + explanation: Solicitaches os datos completos da túa conta de Mastodon. Xa está preparados para descargar! + subject: O teu ficheiro xa está preparado para descargar title: Leve o ficheiro sign_in_token: details: 'Detalles sobre o intento:' @@ -1289,6 +1366,7 @@ gl: warning: explanation: disable: Cando a súa conta está conxelada, os datos permanecen intactos, pero non pode levar a fin accións ate que se desbloquea. + sensitive: Os teus ficheiros e ligazóns a multimedia serán tratados como sensibles. silence: Mentras a conta está limitada, só a xente que actualmente te segue verá os teus toots en este servidor, e poderÃas estar excluÃda de varias listaxes públicas. Porén, outras persoas poderÃante seguir de xeito manual. suspend: A súa conta foi suspendida, e todos os seus toots e medios subidos foron eliminados de este servidor de xeito irreversible, e dos servidores onde tivese seguidoras. get_in_touch: Pode responder a este correo para contactar coa administración de %{instance}. @@ -1297,16 +1375,18 @@ gl: subject: disable: A súa conta %{acct} foi conxelada none: Aviso para %{acct} + sensitive: Ó publicar multimedia a túa conta %{acct} foi marcada como sensible silence: A súa conta %{acct} foi limitada suspend: A súa conta %{acct} foi suspendida title: disable: Conta conxelada none: Aviso + sensitive: O teu multimedia foi marcado como sensible silence: Conta limitada suspend: Conta suspendida welcome: edit_profile_action: Configurar perfil - edit_profile_step: Podes personalizar o teu perfil subindo un avatar, cabeceira, cambiar o nome público e aÃnda máis. Se restrinxes a tua conta podes revisar a conta das persoas que solicitan seguirte antes de permitirlles o acceso aos teus toots. + edit_profile_step: Podes personalizar o teu perfil subindo un avatar, cabeceira, cambiar o nome público e aÃnda máis. Se restrinxes a túa conta podes revisar a conta das persoas que solicitan seguirte antes de permitirlles o acceso aos teus toots. explanation: Aquà ten alunhas endereitas para ir aprendendo final_action: Comece a publicar final_step: 'Publica! Incluso sen seguidoras as túas mensaxes serán vistas por outras, por exemplo na liña temporal local e nos cancelos. PoderÃas presentarte ao #fediverso utilizando o cancelo #introductions.' @@ -1322,9 +1402,11 @@ gl: tips: Consellos title: Benvida, %{name}! users: + blocked_email_provider: Este provedor de email non está permitido follow_limit_reached: Non pode seguir a máis de %{limit} persoas generic_access_help_html: Problemas para acceder a conta? Podes contactar con %{email} para obter axuda invalid_email: O enderezo de correo non é válido + invalid_email_mx: Semella que o enderezo de email non existe invalid_otp_token: O código do segundo factor non é válido invalid_sign_in_token: Código de seguridade non válido otp_lost_help_html: Si perde o acceso a ambos, pode contactar con %{email} @@ -1334,3 +1416,20 @@ gl: verification: explanation_html: 'Podes <strong>validarte a ti mesma como a dona das ligazóns nos metadatos do teu perfil</strong>. Para esto, o sitio web ligado debe conter unha ligazón de retorno ao perfil de Mastodon. Esta ligazón de retorno <strong>ten que</strong> ter un atributo <code>rel="me"</code>. O texto da ligazón non importa. Aquà tes un exemplo:' verification: Validación + webauthn_credentials: + add: Engadir nova chave de seguridade + create: + error: Houbo un problema ó engadir a chave de seguridade, inténtao outra vez. + success: Engadeuse correctamente a chave de seguridade. + delete: Eliminar + delete_confirmation: "¿Tes a certeza de que queres eliminar a chave de seguridade?" + description_html: Se activas a <strong>autenticación con chave de seguridade</strong>, ó conectarte pediráseche que uses unha das túas chaves. + destroy: + error: Houbo un problema ó eliminar a túa chave de seguridade, inténtao outra vez. + success: Eliminouse correctamente a chave de seguridade. + invalid_credential: Chave de seguridade non válida + nickname_hint: Escribe un alcume para a túa nova chave de seguridade + not_enabled: AÃnda non tes activado WebAuthn + not_supported: Este navegador non ten soporte para chaves de seguridade + otp_required: Para usar chaves de seguridade tes que activar primeiro o segundo factor. + registered_on: Rexistrado o %{date} diff --git a/config/locales/he.yml b/config/locales/he.yml index 2bdc816f34d5443460f7b1fa229177d19ab6ae62..7fa884cb31abb7449e0cd54a50e4c8231da68272 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -229,14 +229,6 @@ he: following: רשימת × ×¢×§×‘×™× muting: רשימת השתקות upload: ×™×‘×•× - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day media_attachments: validations: images_and_video: ×œ× × ×™×ª×Ÿ להוסיף ויד×ו לחצרוץ שכבר מכיל ×ª×ž×•× ×•×ª @@ -294,19 +286,12 @@ he: formats: default: "%d %b %Y, %H:%M" two_factor_authentication: - code_hint: ל×ישור, יש להקליד ×ת הקוד שיוצר על ידי ×™×©×•× ×”×ימות - description_html: ל×חר הפעלת <strong>×ימות דו-שלבי</strong>, × ×™×ª×Ÿ ×™×”×™×” ×œ×”×›× ×¡ רק כל עוד ברשותך טלפון, שייצר עבורך ×§×•×“×™× ×©×™×פשרו ×›× ×™×¡×”. disable: כיבוי - enable: הפעלה enabled_success: ×ימות דו-שלבי הופעל בהצלחה generate_recovery_codes: ייצור קודי ×חזור - instructions_html: "<strong>יש לסרוק קוד QR ×–×” בעזרת Google Authenticator ×ו ×™×©×•× TOTP דומה על ×˜×œ×¤×•× ×š</strong>. מעתה ו×ילך, ×™×©×•× ×–×” יוכל ליצר ×§×•×“×™× ×œ×©×™×ž×•×© לצורך ×›× ×™×¡×”." lost_recovery_codes: קודי ×”×חזור מ××¤×©×¨×™× ×חזור גישה לחשבון במידה ומכשירך ×בד. במידה וקודי ×”×חזור ×בדו, × ×™×ª×Ÿ ×œ×™×™×¦×¨× ×ž×—×“×© ×›×ן. תוקף קודי ×”×חזור ×”×™×©× ×™× ×™×¤×•×’. - manual_instructions: 'במידה ×•×œ× × ×™×ª×Ÿ לסרוק ×ת קוד ×”-QR ××œ× ×™×© צורך להקליד ×ותו ×™×“× ×™×ª, להלן סוד כמוס בלתי מוצפן:' recovery_codes_regenerated: קודי ×”×חזור יוצרו בהצלחה recovery_instructions_html: במידה והגישה למכשירך ת×בד, × ×™×ª×Ÿ לייצר קודי ×חזור למטה על ×ž× ×ª ל×חזר גישה ×œ×—×©×‘×•× ×š בכל עת. <strong>× × ×œ×©×ž×•×¨ על קודי הגישה ×‘×ž×§×•× ×‘×˜×•×—</strong>. ×œ×“×•×’×ž× ×¢×œ ידי ×”×“×¤×¡×ª× ×•×©×ž×™×¨×ª× ×¢× ×ž×¡×ž×›×™× ×—×©×•×‘×™× ×חרי×, ×ו שימוש ×‘×ª×•×›× ×” ייעודית ×œ× ×™×”×•×œ סיסמ×ות וסודות. - setup: ×”×›× ×” - wrong_code: הקוד שהוזן שגוי! ×”×× ×”×–×ž×Ÿ בשרת והזמן במכשירך × ×›×•× ×™×? users: invalid_email: כתובת הדו×"ל ××™× ×” חוקית invalid_otp_token: קוד דו-שלבי שגוי diff --git a/config/locales/hi.yml b/config/locales/hi.yml index fc4805625672b9e2581c13f73a345742c6f9b91e..d0b1082fcd761c468f6f9288f7cf34309ffffb59 100644 --- a/config/locales/hi.yml +++ b/config/locales/hi.yml @@ -22,11 +22,3 @@ hi: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/hr.yml b/config/locales/hr.yml index d7bd91c7a91d8d301a8f310c7331da7cd22dc374..f8a659ac20895a9bdaa0b749dd4b2b4cffeb084d 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -1,48 +1,124 @@ --- hr: about: - about_mastodon_html: Mastodon je <em>besplatna, open-source</em> socijalna mreža. <em>Decentralizirana</em> alternativa komercijalnim platformama, izbjegava rizik toga da jedna tvrtka monopolizira vaÅ¡u komunikaciju. Izaberite server kojem ćete vjerovati — koji god odabrali, moći ćete komunicirati sa svima ostalima. Bilo tko može imati svoju vlastitu Mastodon instancu i sudjelovati u <em>socijalnoj mreži</em> bez problema. - about_this: O ovoj instanci + about_hashtag_html: Ovo su javni tootovi oznaÄeni s <strong>#%{hashtag}</strong>. Možete biti u interakciji s njima, ako imate raÄun bilo gdje u fediverzumu. + about_mastodon_html: 'DruÅ¡tvena mreža budućnosti: bez oglasa, bez korporativnog nadzora, etiÄki dizajn i decentralizacija! Budite u vlasniÅ¡tvu svojih podataka pomoću Mastodona!' + about_this: Dodatne informacije + active_count_after: aktivnih + active_footnote: MjeseÄno aktivnih korisnika (MAU) + api: API + apps: Mobilne aplikacije + apps_platforms: Koristite Mastodon na iOS-u, Androidu i drugim platformama contact: Kontakt - source_code: Izvorni kod - status_count_before: Tko je autor + contact_missing: Nije postavljeno + discover_users: Otkrijte korisnike + documentation: Dokumentacija + get_apps: Isprobajte mobilnu aplikaciju + learn_more: Saznajte viÅ¡e + privacy_policy: Politika privatnosti + server_stats: 'Statistika poslužitelja:' + source_code: Izvorni kôd + status_count_before: Koji su objavili + terms: Uvjeti pružanja usluga + unavailable_content: Moderirani poslužitelji accounts: - follow: Slijedi - following: Slijedim + follow: Prati + following: Praćenih + last_active: posljednja aktivnost + media: Medijski sadržaj + never_active: Nikad nothing_here: Ovdje nema niÄeg! - people_followed_by: Ljudi koje %{name} slijedi - people_who_follow: Ljudi koji slijede %{name} - unfollow: Prestani slijediti + people_followed_by: Ljudi koje %{name} prati + people_who_follow: Ljudi koji prate %{name} + posts: + few: Toota + one: Toot + other: Tootova + posts_tab_heading: Tootovi + posts_with_replies: Tootovi i odgovori + reserved_username: KorisniÄko ime je rezervirano + roles: + admin: Admin + bot: Bot + group: Grupa + moderator: Mod + unavailable: Profil nije dostupan + unfollow: Prestani pratiti + admin: + account_actions: + action: IzvrÅ¡i radnju + account_moderation_notes: + create: Ostavi biljeÅ¡ku + accounts: + approve: Odobri + approve_all: Odobri sve + are_you_sure: Jeste li sigurni? + avatar: Avatar + by_domain: Domena + change_email: + changed_msg: E-poÅ¡ta raÄuna uspjeÅ¡no je promijenjena! + current_email: Trenutna e-poÅ¡ta + label: Promijeni e-poÅ¡tu + new_email: Nova e-poÅ¡ta + submit: Promijeni e-poÅ¡tu + title: Promjena e-poÅ¡te za %{username} + confirm: Potvrdi + confirmed: PotvrÄ‘eno + confirming: PotvrÄ‘ivanje + delete: IzbriÅ¡i podatke + deleted: Izbrisano + display_name: Prikazano ime + domain: Domena + edit: Uredi + email: E-poÅ¡ta + email_status: Status e-poÅ¡te + enabled: Omogućeno + followers: Pratitelji + follows: Praćeni + header: Zaglavlje + ip: IP + location: + all: Sve + local: Lokalno + remote: Udaljeno + title: Lokacija + moderation: + all: Sve + action_logs: + deleted_status: "(izbrisani status)" + empty: Nema pronaÄ‘enih izvješća. + filter_by_action: Filtriraj prema radnji + filter_by_user: Filtriraj prema korisniku application_mailer: - settings: 'Promijeni e-mail postavke: %{link}' + settings: 'Promijeni postavke e-poÅ¡te: %{link}' view: 'Vidi:' applications: - invalid_url: Uneseni link nije valjan + invalid_url: Unesena poveznica nije valjana auth: - didnt_get_confirmation: Niste primili instrukcije za potvrÄ‘ivanje? + didnt_get_confirmation: Niste primili upute za potvrÄ‘ivanje? forgot_password: Zaboravljena lozinka? login: Prijavi se logout: Odjavi se register: Registriraj se - resend_confirmation: Ponovo poÅ¡alji instrukcije za potvrÄ‘ivanje - reset_password: Resetiraj lozinku - security: Vjerodajnica + resend_confirmation: Ponovo poÅ¡alji upute za potvrÄ‘ivanje + reset_password: Ponovno postavi lozinku + security: Sigurnost set_new_password: Postavi novu lozinku authorize_follow: - error: Nažalost, doÅ¡lo je do greÅ¡ke looking up the remote raÄun - follow: Slijedi - title: Slijedi %{acct} + error: Nažalost, doÅ¡lo je do greÅ¡ke tijekom traženja udaljenog raÄuna + follow: Prati + title: Prati %{acct} datetime: distance_in_words: - about_x_hours: "%{count}s" + about_x_hours: "%{count}h" about_x_months: "%{count}mj" - about_x_years: "%{count}g" - almost_x_years: "%{count}g" - half_a_minute: upravo - less_than_x_seconds: upravo - over_x_years: "%{count}g" + about_x_years: "%{count}god" + almost_x_years: "%{count}god" + half_a_minute: Upravo sada + less_than_x_seconds: Upravo sada + over_x_years: "%{count}god" x_months: "%{count}mj" - x_seconds: "%{count}sek" + x_seconds: "%{count}s" errors: '400': The request you submitted was invalid or malformed. '403': You don't have permission to view this page. @@ -54,77 +130,178 @@ hr: '500': '503': The page could not be served due to a temporary server failure. exports: - blocks: Blokirao si - storage: Pohrana media zapisa + archive_takeout: + date: Datum + download: Preuzmite svoju arhivu + size: VeliÄina + blocks: Blokirali ste + csv: CSV + lists: Liste + storage: Pohrana medijskih sadržaja + filters: + contexts: + notifications: Obavijesti + index: + empty: Nemate filtera. + title: Filteri + new: + title: Dodaj novi filter + footer: + developers: Razvijatelji + more: ViÅ¡e… + resources: Resursi + trending_now: Popularno generic: + all: Sve changes_saved_msg: Izmjene su uspjeÅ¡no saÄuvane! + copy: Kopiraj + delete: ObriÅ¡i save_changes: SaÄuvaj izmjene + identity_proofs: + authorize: Da, autoriziraj + identity: Identitet imports: - preface: MožeÅ¡ uvesti odreÄ‘ene podatke kao Å¡to su svi ljudi koje slijediÅ¡ ili blokiraÅ¡ u svoj raÄun na ovoj instanci, sa fajlova kreiranih izvozom sa druge instance. - success: Tvoji podaci su uspjeÅ¡no uploadani i bit će obraÄ‘eni u dogledno vrijeme + preface: Možete uvesti podatke koje ste izveli s drugog poslužitelja, kao Å¡to su liste ljudi koje pratite ili blokirate. + success: VaÅ¡i podatci uspjeÅ¡no su preneseni i bit će obraÄ‘eni u dogledno vrijeme types: blocking: Lista blokiranih - following: Lista onih koje slijedim + following: Lista praćenih muting: Lista utiÅ¡anih invites: + expired: Isteklo expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day + '1800': 30 minuta + '21600': 6 sati + '3600': 1 sat + '43200': 12 sati + '604800': 1 tjedan + '86400': 1 dan + expires_in_prompt: Nikad + generate: Generiraj poveznicu za pozivanje + invited_by: 'Poziva Vas:' + max_uses: + few: "%{count} koriÅ¡tenja" + one: 1 koriÅ¡tenje + other: "%{count} koriÅ¡tenja" notification_mailer: digest: - body: Ovo je kratak sažetak propuÅ¡tenog od tvog proÅ¡log posjeta %{since} - mention: "%{name} te je spomenuo:" + body: Ovo je kratak sažetak propuÅ¡tenih poruka od VaÅ¡eg proÅ¡log posjeta %{since} + mention: "%{name} Vas je spomenuo/la:" favourite: - body: 'Tvoj status je %{name} oznaÄio kao omiljen:' - subject: "%{name} je oznaÄio kao omiljen tvoj status" + body: "%{name} je oznaÄio/la VaÅ¡ status favoritom:" + subject: "%{name} je oznaÄio/la VaÅ¡ status favoritom" follow: - body: "%{name} te sada slijedi!" - subject: "%{name} te sada slijedi" + body: "%{name} Vas sada prati!" + subject: "%{name} Vas sada prati" follow_request: - body: "%{name} je zatražio da te slijedi" - subject: 'Sljedbenik na Äekanju: %{name}' + body: "%{name} je zatražio/la da Vas prati" + subject: 'Pratitelj na Äekanju: %{name}' mention: - body: 'Spomenuo te je %{name} u:' - subject: Spomenuo te je %{name} + body: 'Spomenuo/la Vas je %{name} u:' + subject: Spomenuo/la Vas je %{name} reblog: - body: 'Tvoj status je potaknut od %{name}:' - subject: "%{name} je potakao tvoj status" + body: 'VaÅ¡ status boostao/la je %{name}:' + subject: "%{name} boostao/la je VaÅ¡ status" + number: + human: + decimal_units: + units: + billion: mrd + million: mil + thousand: tis + trillion: bil + otp_authentication: + setup: Postavi pagination: - next: Sljedeći - prev: ProÅ¡li + newer: Novije + next: Sljedeće + older: Starije + prev: Prethodno + truncate: "…" + polls: + errors: + already_voted: Već ste glasali u ovoj anketi remote_follow: - acct: Unesi svoje username@domain sa koje želiÅ¡ slijediti - missing_resource: Traženi redirect link za tvoj raÄun nije mogao biti naÄ‘en - proceed: Nastavi slijediti - prompt: 'Slijediti ćeÅ¡:' + acct: Unesite VaÅ¡e KorisniÄkoIme@domena s kojim želite izvrÅ¡iti radnju + missing_resource: Nije moguće pronaći traženi URL preusmjeravanja za VaÅ¡ raÄun + proceed: Dalje + prompt: 'Pratit ćete:' + sessions: + platforms: + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS + ios: iOS + linux: Linux + mac: macOS + other: nepoznata platforma + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone + revoke: Opozovi + revoke_success: Sesija je uspjeÅ¡no opozvana + title: Sesije settings: + account: RaÄun + account_settings: Postavke raÄuna + aliases: Pseudonimi raÄuna + appearance: Izgled authorized_apps: Autorizirane aplikacije back: Natrag na Mastodon + delete: Brisanje raÄuna + development: Razvijanje edit_profile: Uredi profil export: Izvoz podataka + featured_tags: Istaknuti hashtagovi import: Uvezi + notifications: Obavijesti preferences: Postavke - two_factor_authentication: Dvo-faktorska Autentifikacija + profile: Profil + two_factor_authentication: Dvofaktorska autentifikacija statuses: open_in_web: Otvori na webu - over_character_limit: prijeÄ‘en je limit od %{max} znakova + over_character_limit: prijeÄ‘eno je ograniÄenje od %{max} znakova + poll: + total_people: + few: "%{count} osobe" + one: "%{count} osoba" + other: "%{count} ljudi" + total_votes: + few: "%{count} glasa" + one: "%{count} glas" + other: "%{count} glasova" + vote: Glasaj show_more: Prikaži viÅ¡e + show_thread: Prikaži nit visibilities: - private: Pokaži samo sljedbenicima + private: Samo pratitelji public: Javno - unlisted: Javno, no nemoj prikazati na javnom timelineu + unlisted: Neprikazano stream_entries: - reblogged: potaknut + reblogged: boostano sensitive_content: Osjetljivi sadržaj two_factor_authentication: - description_html: Ako omogućiÅ¡ <strong>dvo-faktorsku autentifikaciju</strong>, prijavljivanje će zahtjevati da kod sebe imaÅ¡ svoj mobitel, koji će generirati tokene koje ćeÅ¡ unijeti. - disable: Onemogući - enable: Omogući - instructions_html: "<strong>Skeniraj ovaj QR kod u Google Authenticator ili sliÄnu aplikaciju na svom telefonu</strong>. Od sada, ta aplikacija će generirati tokene koje ćeÅ¡ unijeti pri prijavljivanju." + disable: Onemogući 2FA + user_mailer: + warning: + title: + disable: RaÄun je zamrznut + none: Upozorenje + silence: RaÄun je ograniÄen + suspend: RaÄun je suspendiran + welcome: + edit_profile_action: Postavi profil + review_preferences_action: Promijeni postavke + subject: Dobro doÅ¡li na Mastodon + tips: Savjeti users: - invalid_email: E-mail adresa nije valjana - invalid_otp_token: Nevaljani dvo-faktorski kod + invalid_email: Adresa e-poÅ¡te nije valjana + invalid_otp_token: Nevažeći dvo-faktorski kôd + invalid_sign_in_token: Nevažeći sigurnosni kôd + signed_in_as: 'Prijavljeni kao:' + verification: + verification: Verifikacija + webauthn_credentials: + add: Dodaj novi sigurnosni kljuÄ + delete: ObriÅ¡i diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 9ae551a34500f445bdb7c0c734565ab552895daa..97596ff0cd6b3b4b53583f46f4243692f2fa7e92 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -21,7 +21,9 @@ hu: federation_hint_html: Egy %{instance} fiókkal bármely más Mastodon szerveren vagy a föderációban lévÅ‘ felhasználót követni tudsz. get_apps: Próbálj ki egy mobil appot hosted_on: "%{domain} Mastodon szerver" - instance_actor_flash: Ez a fiók egy virtuális szereplÅ‘, mely magát a szervert reprezentálja, nem egy felhasználót. Ez a föderáció támogatására készült, ezért nem szabad blokkolni, hacsak egy teljes szervert nem akarsz kitiltani, amire persze a domain blokkolása jobb megoldás. + instance_actor_flash: | + Ez a fiók virtuális, magát a szervert reprezentálja, nem pedig konkrét + felhasználót. Föderációs célokra szolgál, nem szabad tehát felfüggeszteni, hacsak nem akarod a teljes szervert kitiltani, mely esetben a domain tiltásának használata javasolt. learn_more: Tudj meg többet privacy_policy: Adatvédelmi szabályzat see_whats_happening: Nézd, mi történik @@ -51,13 +53,16 @@ hu: what_is_mastodon: Mi a Mastodon? accounts: choices_html: "%{name} választásai:" - endorsements_hint: A webes felületen jóváhagyhatod a követett embereket, és itt jelennek meg. + endorsements_hint: A webes felületen promózhatsz általad követett embereket, akik itt fognak megjelenni. featured_tags_hint: Szerepeltethetsz bizonyos hashtageket, melyek itt jelennek majd meg. follow: Követés followers: one: KövetÅ‘ other: KövetÅ‘ following: Követett + instance_actor_flash: |- + Ez a fiók virtuális, magát a szervert reprezentálja, nem pedig konkrét + felhasználót. Föderációs célokra szolgál, nem szabad tehát felfüggeszteni. joined: Csatlakozott %{date} last_active: utoljára aktÃv link_verified_on: A link tulajdonosát %{date} -n ellenÅ‘riztük @@ -96,6 +101,7 @@ hu: add_email_domain_block: Email domain tiltólistára vétele approve: Jóváhagyás approve_all: Mindet jóváhagy + approved_msg: A %{username} fiók regisztrációs kérelmét sikeresen elfogadtuk are_you_sure: Biztos vagy benne? avatar: Profilkép by_domain: Domain @@ -109,8 +115,10 @@ hu: confirm: MegerÅ‘sÃtés confirmed: MegerÅ‘sÃtve confirming: MegerÅ‘sÃtés alatt + delete: Adatok törlése deleted: Törölve demote: Lefokozás + destroyed_msg: A %{username} fiók adatai bekerültek a végleges törlése váró sorba disable: Kikapcsolás disable_two_factor_authentication: KétlépcsÅ‘s hitelesÃtés kikapcsolása disabled: Kikapcsolva @@ -121,10 +129,12 @@ hu: email_status: E-mail állapot enable: Bekapcsolás enabled: Bekapcsolva + enabled_msg: A %{username} fiók fagyasztását sikeresen visszavontuk followers: KövetÅ‘ follows: Követett header: Fejléc inbox_url: Beérkezett üzenetek URL-je + invite_request_text: Csatlakozás oka invited_by: MeghÃvta ip: IP joined: Csatlakozott @@ -134,8 +144,10 @@ hu: remote: Távoli title: Hely login_status: Bejelentkezési állapot - media_attachments: Média-csatolmányok + media_attachments: Médiamellékletek memorialize: EmlékállÃtás + memorialized: Emlékezetünkben + memorialized_msg: A %{username} fiókot sikeresen emlékké nyilvánÃtottuk moderation: active: AktÃv all: Összes @@ -156,10 +168,14 @@ hu: public: Nyilvános push_subscription_expires: A PuSH feliratkozás elévül redownload: Profilkép frissÃtése + redownloaded_msg: "%{username} profilját sikeresen frissÃtettük az eredetibÅ‘l" reject: ElutasÃtás reject_all: Összes elutasÃtása + rejected_msg: A %{username} fiók regisztrációs kérelmét sikeresen elutasÃtottuk remove_avatar: Profilkép eltávolÃtása remove_header: Fejléc törlése + removed_avatar_msg: A %{username} fiók avatárját sikeresen töröltük + removed_header_msg: A %{username} fiók fejlécét sikeresen töröltük resend_confirmation: already_confirmed: Ezt a felhasználót már megerÅ‘sÃtették send: Küldd újra a megerÅ‘sÃtÅ‘ e-mailt @@ -176,6 +192,8 @@ hu: search: Keresés search_same_email_domain: Felhasználók ugyanezzel az email domainnel search_same_ip: Más felhasználók ugyanezzel az IP-vel + sensitive: SzenzitÃv + sensitized: szenzitÃvnek jelölve shared_inbox_url: Megosztott bejövÅ‘ üzenetek URL show: created_reports: Létrehozott jelentések @@ -185,13 +203,19 @@ hu: statuses: Tülkök subscribe: Feliratkozás suspended: Felfüggesztett + suspension_irreversible: Ennek a fióknak az adatait visszaállÃthatatlanul törölték. Visszavonhatod a fiók felfüggesztését, hogy újra használható legyen, de a régi adatok ettÅ‘l még nem fognak visszatérni. + suspension_reversible_hint_html: A fiókot felfüggesztettük, az adatait %{date}-n teljesen eltávolÃtjuk. Eddig az idÅ‘pontig a fiók probléma nélkül visszaállÃtható. Ha mégis azonnal törölni szeretnéd a fiókot, alább megteheted. time_in_queue: Várakozás a sorban %{time} title: Fiókok unconfirmed_email: Nem megerÅ‘sÃtett e-mail + undo_sensitized: SzenzitÃv jelölés levétele undo_silenced: NémÃtás visszavonása undo_suspension: Felfüggesztés visszavonása + unsilenced_msg: A %{username} fiók korlátozásait sikeresen levettük unsubscribe: Leiratkozás + unsuspended_msg: A %{username} fiók felfüggesztését sikeresen visszavontuk username: Felhasználónév + view_domain: Domain összefoglalójának megtekintése warn: Figyelmeztetés web: Web whitelisted: EngedélyezÅ‘-listán @@ -204,14 +228,16 @@ hu: create_announcement: Közlemény létrehozása create_custom_emoji: Egyéni emodzsi létrehozása create_domain_allow: Domain engedélyezés létrehozása - create_domain_block: Domain blokkolás létrehozása - create_email_domain_block: E-mail domain blokkolás létrehozása + create_domain_block: Domain tiltás létrehozása + create_email_domain_block: E-mail domain tiltás létrehozása + create_ip_block: IP szabály létrehozása demote_user: Felhasználó lefokozása destroy_announcement: Közlemény törlése destroy_custom_emoji: Egyéni emodzsi törlése destroy_domain_allow: Domain engedélyezés törlése - destroy_domain_block: Domain blokkolás törlése - destroy_email_domain_block: E-mail domain blokkolás törlése + destroy_domain_block: Domain tiltás törlése + destroy_email_domain_block: E-mail domain tiltás törlése + destroy_ip_block: IP szabály törlése destroy_status: Ãllapot törlése disable_2fa_user: KétlépcsÅ‘s hitelesÃtés letiltása disable_custom_emoji: Egyéni emodzsi letiltása @@ -224,13 +250,16 @@ hu: reopen_report: Jelentés újranyitása reset_password_user: Jelszó visszaállÃtása resolve_report: Jelentés megoldása + sensitive_account: A fiókodban minden média szenzitÃvnek jelölése silence_account: Fiók némÃtása suspend_account: Fiók felfüggesztése unassigned_report: Jelentés hozzárendelésének megszüntetése + unsensitive_account: A fiókodban minden média szenzitÃv állapotának törlése unsilence_account: Fiók némÃtásának feloldása unsuspend_account: Fiók felfüggesztésének feloldása update_announcement: Közlemény frissÃtése update_custom_emoji: Egyéni emodzsi frissÃtése + update_domain_block: Domain tiltás frissÃtése update_status: Ãllapot frissÃtése actions: assigned_to_self_report: "%{name} a %{target} bejelentést magához rendelte" @@ -241,13 +270,15 @@ hu: create_custom_emoji: "%{name} új emodzsit töltött fel: %{target}" create_domain_allow: "%{name} engedélyezÅ‘ listára vette %{target} domaint" create_domain_block: "%{name} letiltotta az alábbi domaint: %{target}" - create_email_domain_block: "%{name} feketelistára tette az alábbi e-mail domaint: %{target}" + create_email_domain_block: "%{name} letiltotta az e-mail domaint: %{target}" + create_ip_block: "%{name} létrehozott egy szabályt a %{target} IP-vel kapcsolatban" demote_user: "%{name} lefokozta az alábbi felhasználót: %{target}" destroy_announcement: "%{name} törölte a közleményt %{target}" destroy_custom_emoji: "%{name} törölte az emodzsit: %{target}" destroy_domain_allow: "%{name} leszedte %{target} domaint az engedélyezÅ‘ listáról" destroy_domain_block: "%{name} engedélyezte az alábbi domaint: %{target}" - destroy_email_domain_block: "%{name} fehérlistára tette az alábbi e-mail domaint: %{target}" + destroy_email_domain_block: "%{name} engedélyezte az e-mail domaint: %{target}" + destroy_ip_block: "%{name} törölt egy szabályt a %{target} IP-vel kapcsolatban" destroy_status: "%{name} eltávolÃtotta az alábbi felhasználó tülkjét: %{target}" disable_2fa_user: "%{name} kikapcsolta a kétlépcsÅ‘s azonosÃtást %{target} felhasználó fiókján" disable_custom_emoji: "%{name} letiltotta az alábbi emodzsit: %{target}" @@ -260,13 +291,16 @@ hu: reopen_report: "%{name} újranyitotta a bejelentést: %{target}" reset_password_user: "%{name} visszaállÃtotta az alábbi felhasználó jelszavát: %{target}" resolve_report: "%{name} megoldotta alábbi bejelentést: %{target}" + sensitive_account: "%{name} szenzitÃvnek jelölte %{target} médiatartalmát" silence_account: "%{name} lenémÃtotta %{target} felhasználói fiókját" suspend_account: "%{name} felfüggesztette %{target} felhasználói fiókját" unassigned_report: "%{name} törölte a %{target} bejelentés hozzárendelését" + unsensitive_account: "%{name} levette a szenzitÃv jelölést %{target} médiatartalmáról" unsilence_account: "%{name} feloldotta a némÃtást %{target} felhasználói fiókján" unsuspend_account: "%{name} feloldotta %{target} felhasználói fiókjának felfüggesztését" update_announcement: "%{name} frissÃtette a közleményt %{target}" update_custom_emoji: "%{name} frissÃtette az alábbi emodzsit: %{target}" + update_domain_block: "%{name} frissÃtette a %{target} domain tiltását" update_status: "%{name} frissÃtette %{target} felhasználó tülkjét" deleted_status: "(törölt tülk)" empty: Nem található napló. @@ -370,6 +404,8 @@ hu: silence: NémÃtás suspend: Felfüggesztés title: Új domain tiltása + obfuscate: Domain név álcázása + obfuscate_hint: Részlegesen álcázza a domain nevet a listában, ha a domain korlátozások listájának közzététele engedélyezett private_comment: Privát megjegyzés private_comment_hint: Megjegyzés domain tiltásával kapcsolatban belsÅ‘ használatra, a többi moderátor részére. public_comment: Nyilvános megjegyzés @@ -396,19 +432,20 @@ hu: view: Domain tiltásának megtekintése email_domain_blocks: add_new: Új hozzáadása - created_msg: E-mail domain sikeresen hozzáadva a feketelistához + created_msg: E-mail domain sikeresen letiltva delete: Törlés - destroyed_msg: E-mail domain sikeresen eltávolÃtva a feketelistáról + destroyed_msg: E-mail domain sikeresen engedélyezve domain: Domain - empty: Nincs email domain a feketelistán. + empty: Nincs letiltott email domain. from_html: "%{domain}-ról" new: create: Domain hozzáadása - title: Új e-mail feketelista bejegyzés - title: E-mail feketelista + title: Új e-mail domain tiltása + title: Tiltott e-mail domainek instances: by_domain: Domain delivery_available: KézbesÃtés elérhetÅ‘ + empty: Nem található domain. known_accounts: one: "%{count} ismert fiók" other: "%{count} ismert fiók" @@ -432,6 +469,21 @@ hu: expired: Elévült title: SzűrÅ‘ title: MeghÃvások + ip_blocks: + add_new: Szabály létrehozása + created_msg: Az új IP szabályt sikeresen felvettük + delete: Törlés + expires_in: + '1209600': 2 hét + '15778476': 6 hónap + '2629746': 1 hónap + '31556952': 1 év + '86400': 1 nap + '94670856': 3 év + new: + title: Új IP szabály létrehozása + no_ip_block_selected: Nem változtattunk egy IP szabályon sem, mivel egy sem volt kiválasztva + title: IP szabály pending_accounts: title: FüggÅ‘ben lévÅ‘ fiókok (%{count}) relationships: @@ -471,6 +523,8 @@ hu: comment: none: Egyik sem created_at: Jelentve + forwarded: TovábbÃtva + forwarded_to: 'TovábbÃtva ide: %{domain}' mark_as_resolved: Megjelölés megoldottként mark_as_unresolved: Megjelölés megoldatlanként notes: @@ -514,6 +568,7 @@ hu: domain_blocks_rationale: title: Mutasd meg az indokolást enable_bootstrap_timeline_accounts: + desc_html: Az új felhasználók automatikusan követik a beállÃtott fiókokat, Ãgy a Saját idÅ‘vonaluk kezdéskor nem lesz üres title: Alapértelmezett követés engedélyezése új felhasználóknak hero: desc_html: A kezdÅ‘oldalon látszik. Legalább 600x100px méret javasolt. Ha nincs beállÃtva, a szerver bélyegképet használjuk @@ -540,6 +595,9 @@ hu: min_invite_role: disabled: Senki title: MeghÃvások engedélyezése + require_invite_text: + desc_html: Ha a regisztrációhoz kézi jóváhagyásra van szükség, akkor a „Miért akarsz csatlakozni?†válasz kitöltése legyen kötelezÅ‘, és ne opcionális + title: Az új felhasználóktól legyen megkövetelve a meghÃvási kérés szövegének kitöltése registrations_mode: modes: approved: A regisztráció engedélyhez kötött @@ -679,8 +737,11 @@ hu: prefix_sign_up: Regisztrláj még ma a Mastodonra! suffix: Egy fiókkal követhetsz másokat, tülkölhetsz, eszmét cserélhetsz más Mastodon szerverek felhasználóival! didnt_get_confirmation: Nem kaptad meg a megerÅ‘sÃtési lépéseket? + dont_have_your_security_key: Nincs biztonsági kulcsod? forgot_password: Elfelejtetted a jelszavad? invalid_reset_password_token: A jelszó-visszaállÃtási kulcs nem megfelelÅ‘ vagy lejárt. Kérlek generálj egy újat. + link_to_otp: Ãrj be egy kétlépcsÅ‘s azonosÃtó kódot a telefonodról vagy egy visszaállÃtó kódot + link_to_webauth: Használd a biztonsági kulcs eszközödet login: Bejelentkezés logout: Kijelentkezés migrate_account: Felhasználói fiók költöztetése @@ -705,7 +766,9 @@ hu: functional: A fiókod teljesen működÅ‘képes. pending: A jelentkezésed engedélyezésre vár. Ez eltarthat egy ideig. Kapsz egy e-mailt, ha az elbÃrálás megtörtént. redirecting_to: A fiókod inaktÃv, mert jelenleg ide %{acct} van átirányÃtva. + too_fast: Túl gyorsan küldted el az űrlapot, próbáld késÅ‘bb. trouble_logging_in: Problémád van a bejelentkezéssel? + use_security_key: Biztonsági kulcs használata authorize_follow: already_following: Már követed ezt a felhasználót already_requested: Már küldtél követési kérelmet ennek a fióknak @@ -730,6 +793,7 @@ hu: date: formats: default: "%Y.%b.%d." + with_month_name: "%Y. %B %d" datetime: distance_in_words: about_x_hours: "%{count}ó" @@ -794,6 +858,7 @@ hu: request: ArchÃv kérése size: Méret blocks: Tiltólistádon + bookmarks: KönyvjelzÅ‘k csv: CSV domain_blocks: Tiltott domainjeid lists: Listáid @@ -836,8 +901,8 @@ hu: order_by: Rendezés save_changes: Változások mentése validation_errors: - one: Valami nincs rendjén! Kérlek tekintsd meg a hibát alant - other: Valami nincs rendjén! Kérlek tekintsd meg a %{count} darab hibát alant + one: Valami nincs rendjén! Tekintsd meg a hibát lent + other: Valami nincs rendjén! Tekintsd meg a(z) %{count} hibát lent html_validator: invalid_markup: 'hibás HTML leÃró: %{error}' identity_proofs: @@ -861,6 +926,8 @@ hu: status: EllenÅ‘rzés állapota view_proof: TanúsÃtás megtekintése imports: + errors: + over_rows_processing_limit: több mint %{count} sort tartalmaz modes: merge: Összefésülés merge_long: Megtartjuk a meglévÅ‘ bejegyzéseket és hozzávesszük az újakat @@ -870,6 +937,7 @@ hu: success: Adataidat sikeresen feltöltöttük és feldolgozásukat megkezdtük types: blocking: Letiltottak listája + bookmarks: KönyvjelzÅ‘k domain_blocking: Letiltott domainek listája following: Követettjeid listája muting: NémÃtott felhasználók listája @@ -939,7 +1007,7 @@ hu: moderation: title: Moderáció move_handler: - carry_blocks_over_text: Ez a fiók elköltözött innen %{acct}, melyet blokkoltatok. + carry_blocks_over_text: Ez a fiók elköltözött innen %{acct}, melyet letiltottatok. carry_mutes_over_text: Ez a fiók elköltözött innen %{acct}, melyet lenémÃtottatok. copy_account_note_text: 'Ez a fiók elköltözött innen %{acct}, itt vannak a bejegyzéseitek róla:' notification_mailer: @@ -990,6 +1058,14 @@ hu: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: Jóváhagyáshoz Ãrd be a hitelesÃtÅ‘ alkalmazás által generált kódot + description_html: Ha engedélyezed a <strong>kétlépcsÅ‘s azonosÃtást</strong>, a bejelentkezéshez szükséged lesz a telefonodra és egy alkalmazásra, amely hozzáférési kódot generál számodra. + enable: Engedélyezés + instructions_html: "<strong>Olvasd be ezt a QR-kódot a telefonodon futó Google Authenticator vagy egyéb TOTP alkalmazással</strong>. A jövÅ‘ben ez az alkalmazás fog számodra hozzáférési kódot generálni a belépéshez." + manual_instructions: 'Ha nem sikerült a QR-kód beolvasása, itt a szöveges kulcs, amelyet manuálisan kell begépelned:' + setup: BeállÃtás + wrong_code: A beÃrt kód nem érvényes! A szerver órája és az eszközöd órája szinkronban jár? pagination: newer: Újabb next: KövetkezÅ‘ @@ -1018,6 +1094,7 @@ hu: relationships: activity: Fiók aktivitás dormant: Elhagyott + follow_selected_followers: Kiválasztott követÅ‘k bekövetése followers: KövetÅ‘k following: Követve invited: MeghÃvva @@ -1113,7 +1190,8 @@ hu: preferences: BeállÃtások profile: Profil relationships: Követések és követÅ‘k - two_factor_authentication: KétlépcsÅ‘s azonosÃtás + two_factor_authentication: KétlépcsÅ‘s hitelesÃtés + webauthn_authentication: Biztonsági kulcsok spam_check: spam_detected: Ez egy automatikus jelentés. Spamet érzékeltünk. statuses: @@ -1151,7 +1229,9 @@ hu: one: "%{count} szavazat" other: "%{count} szavazat" vote: Szavazás - show_more: Mutass többet + show_more: Több megjelenÃtése + show_newer: Újabbak mutatása + show_older: Régebbiek mutatása show_thread: Szál mutatása sign_in_to_participate: Jelentkezz be, hogy részt vehess a beszélgetésben title: '%{name}: "%{quote}"' @@ -1260,21 +1340,20 @@ hu: default: "%Y. %b %d., %H:%M" month: "%Y %b" two_factor_authentication: - code_hint: MegerÅ‘sÃtéshez Ãrd be az alkalmazás által generált kódot - description_html: He engedélyezed a <strong>kétlépcsÅ‘s azonosÃtást</strong>, a bejelentkezéshez szükséged lesz a telefonodra és egy alkalmazásra, amely hozzáférési kódot generál számodra. + add: Hozzáadás disable: Kikapcsolás - enable: Engedélyezés + disabled_success: A kétlépcsÅ‘s azonosÃtást sikeresen letiltottuk + edit: Szerkesztés enabled: KétlépcsÅ‘s azonosÃtás engedélyezve enabled_success: A kétlépcsÅ‘s azonosÃtást sikeresen engedélyezted generate_recovery_codes: VisszaállÃtási kódok generálása - instructions_html: "<strong>Olvasd be ezt a QR-kódot a telefonodon futó Google Authenticator vagy egyéb TOTP alkalmazással</strong>. A jövÅ‘ben ez az alkalmazás fog számodra hozzáférési kódot generálni a belépéshez." lost_recovery_codes: A visszaállÃtási kódok segÃtségével tudsz belépni, ha elveszÃtenéd a telefonod. Ha a visszaállÃtási kódjaidat hagytad el, itt generálhatsz újakat. A régi kódokat ebben az esetben érvénytelenÃtjük. - manual_instructions: 'Ha nem sikerült a QR-kód beolvasása, itt a szöveges kulcs, amelyet manuálisan kell begépelned:' + methods: KétlépcsÅ‘s eljárások + otp: HitelesÃtÅ‘ alkalmazás recovery_codes: VisszaállÃtási kódok biztonsági mentése recovery_codes_regenerated: A visszaállÃtási kódokat sikeresen újrageneráltuk recovery_instructions_html: A visszaállÃtási kódok egyikének segÃtségével tudsz majd belépni, ha elveszÃtenéd a telefonod. <strong>Tartsd biztos helyen a visszaállÃtási kódjaid</strong>! Például nyomtasd ki Å‘ket és tárold a többi fontos iratoddal együtt. - setup: BeállÃtás - wrong_code: A beÃrt kód nem érvényes! A szerver órája és az eszközöd órája szinkronban jár? + webauthn: Biztonsági kulcsok user_mailer: backup_ready: explanation: A Mastodon fiókod teljes mentését kérted. A mentés kész ás letölthetÅ‘! @@ -1289,6 +1368,7 @@ hu: warning: explanation: disable: A fiókod befagyasztott állapotban megtartja minden adatát, de feloldásig nem csinálhatsz vele semmit. + sensitive: A feltöltött és hivatkozott médiatartalmaidat szenzitÃvként kezeljük. silence: A fiókod korlátozott állapotában csak a követÅ‘id láthatják a tülkjeidet, valamint nem kerülsz rá nyilvános idÅ‘vonalakra. Ugyanakkor mások manuálisan még követhetnek. suspend: A fiókodat felfüggesztették, Ãgy minden tülköd és feltöltött fájlod menthetetlenül elveszett errÅ‘l a szerverrÅ‘l és minden olyanról is, ahol voltak követÅ‘id. get_in_touch: Válaszolhatsz erre az emailre, hogy kapcsolatba lépj a %{instance} csapatával. @@ -1297,11 +1377,13 @@ hu: subject: disable: A fiókodat %{acct} befagyasztották none: Figyelmeztetés a %{acct} fióknak + sensitive: A %{acct} fiókod médiatartalmait szenzitÃvnek jelölték silence: A fiókodat %{acct} korlátozták suspend: A fiókodat %{acct} felfüggesztették title: disable: Befagyasztott fiók none: Figyelem + sensitive: Médiatartalmadat szenzitÃvnek jelölték silence: Lekorlátozott fiók suspend: Felfüggesztett fiók welcome: @@ -1322,9 +1404,11 @@ hu: tips: Tippek title: Üdv a fedélzeten, %{name}! users: + blocked_email_provider: Ez az email szolgáltató nem engedélyezett follow_limit_reached: Nem követhetsz több, mint %{limit} embert generic_access_help_html: Nem tudod elérni a fiókodat? SegÃtségért lépj kapcsolatba velünk ezen %{email} invalid_email: A megadott e-mail cÃm helytelen + invalid_email_mx: Az email cÃm nem tűnik létezÅ‘nek invalid_otp_token: Érvénytelen ellenÅ‘rzÅ‘ kód invalid_sign_in_token: Érvénytelen biztonsági kód otp_lost_help_html: Ha mindkettÅ‘t elvesztetted, kérhetsz segÃtséget itt %{email} @@ -1334,3 +1418,20 @@ hu: verification: explanation_html: 'A profilodon <strong>hitelesÃtheted magad, mint az itt található linkek tulajdonosa</strong>. Ehhez a linkelt weboldalnak tartalmaznia kell egy linket vissza a Mastodon profilodra. Ennek <strong>tartalmaznia kell</strong> a <code>rel="me"</code> attribútumot. A link szövege bármi lehet. Itt egy példa:' verification: HitelesÃtés + webauthn_credentials: + add: Biztonsági kulcs hozzáadása + create: + error: A biztonsági kulcs hozzáadása közben hiba történt. Kérlek, próbáld újra. + success: A biztonsági kulcsodat sikeresen felvettük. + delete: Törlés + delete_confirmation: Biztos, hogy le akarod törölni ezt a biztonsági kulcsot? + description_html: Ha engedélyezed a <strong>biztonsági kulcsos hitelesÃtést</strong>, a bejelentkezéshez szükséged lesz az egyik kulcsodra. + destroy: + error: A biztonsági kulcs törlése közben hiba történt. Kérlek, próbáld újra. + success: A biztonsági kulcsodat sikeresen töröltük. + invalid_credential: Érvénytelen biztonsági kulcs + nickname_hint: Ãrd be az új biztonsági kulcsod becenevét + not_enabled: Még nem engedélyezted a WebAuthn-t + not_supported: Ez a böngészÅ‘ nem támogatja a biztonsági kulcsokat + otp_required: A biztonsági kulcsok használatához elÅ‘ször engedélyezd a kétlépcsÅ‘s azonosÃtást. + registered_on: 'Regisztrált ekkor: %{date}' diff --git a/config/locales/hy.yml b/config/locales/hy.yml index 477b0fda214b4821a6743010c9571c0f4488fe2c..0cfae56efd482a1dba4cd6bf0299e42656429097 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -1,17 +1,29 @@ --- hy: about: + about_hashtag_html: ÕÖ€Õ¡Õ¶Ö„ <strong>#%{hashtag}</strong> Õ°Õ¥Õ·Õ©Õ¥Õ£Õ¸Õ¾ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ©Õ©Õ¥Ö€Õ¶ Õ¥Õ¶Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Ö„ ÖƒÕ¸ÕÕ£Õ¸Ö€Õ®Õ¡Õ¯ÖÕ¥Õ¬ Õ¤Ö€Õ¡Õ¶Ö Õ°Õ¥Õ¿ Õ¥Õ©Õ¥ Õ¸Ö‚Õ¶Õ¥Ö„ Õ¸Ö€Õ¥Ö‚Õ§ Õ°Õ¡Õ·Õ«Õ¸Ö‚ Õ¤Õ¡Õ·Õ¿Õ¥Õ¦Õ¥Ö€Ö„Õ¸Ö‚Õ´Ö‰ + about_mastodon_html: Ô±ÕºÕ¡Õ£Õ¡ÕµÕ« Õ½Õ¸ÖÖÕ¡Õ¶ÖÕ¨Ö‰ ÕˆÕ¹ Õ´Õ« Õ£Õ¸Õ¾Õ¡Õ¦Õ¤, Õ¸Õ¹ Õ´Õ« Õ¯Õ¸Ö€ÕºÕ¸Ö€Õ¡Õ¿Õ«Õ¾ Õ¾Õ¥Ö€Õ¡Õ°Õ½Õ¯Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶, Õ§Õ©Õ«Õ¯Õ¡Õ¯Õ¡Õ¶ Õ¤Õ«Õ¦Õ¡ÕµÕ¶, Õ¥Ö‚ Õ¡ÕºÕ¡Õ¯Õ¥Õ¶Õ¿Ö€Õ¸Õ¶Õ¡ÖÕ¸Ö‚Õ´Ö‰ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ¸Ö‚Õ´ Õ¤Õ¸Ö‚ Õ¥Õ½ Ö„Õ¸ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¿Õ§Ö€Õ¨Ö‰ about_this: Õ„Õ¥Ö€ Õ´Õ¡Õ½Õ«Õ¶ active_count_after: Õ¡Õ¯Õ¿Õ«Õ¾ + active_footnote: Ô±Õ´Õ½Õ¥Õ¯Õ¡Õ¶ Õ¡Õ¯Õ¿Õ«Ö‚ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€ (MAU) administered_by: Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ api: API apps: Ô²Õ»Õ»Õ¡ÕµÕ«Õ¶ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€ + apps_platforms: Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ iOS, Android Õ¥Ö‚ Õ¡ÕµÕ¬ Õ¿Õ¡Ö€Õ¢Õ¥Ö€ Õ°Õ¥Õ¶Ö„Õ¥Ö€Õ¸Ö‚Õ´ + browse_directory: ÕŠÖ€ÕºÕ¿Õ«Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ·Õ¿Õ¥Õ´Õ¡Ö€Õ¡Õ¶Õ¨ Õ¥Ö‚ Õ£Õ¿Õ«Ö€ Õ°Õ¥Õ¿Õ¡Ö„Ö€Ö„Õ«Ö€ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö + browse_local_posts: ÕÕ¥Õ½ Õ¡ÕµÕ½ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¸Õ½Ö„Õ¨ + browse_public_posts: Ô´Õ«Õ¿Õ«Ö€ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ« Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¸Õ½Ö„Õ¨ contact: Ô¿Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿ contact_missing: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¾Õ¡Õ® Õ¹Õ§ contact_unavailable: ÕˆÕ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡ discover_users: Ô³Õ¿Õ¶Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¶Õ¥Ö€ documentation: Õ“Õ¡Õ½Õ¿Õ¡Õ©Õ²Õ©Õ¥Ö€ + federation_hint_html: "%{instance} Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¸Ö‚Õ´ Õ°Õ¡Õ·Õ«Ö‚ Õ¢Õ¡ÖÕ¥Õ¬Õ¸Õ¾ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ« ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ«Ö Ö‡ Õ¸Õ¹ Õ´Õ«Õ¡ÕµÕ¶Ö‰" get_apps: Õ“Õ¸Ö€Õ±Õ¥Ö„ Õ¢Õ»Õ»Õ¡ÕµÕ«Õ¶ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ + hosted_on: Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ¡Õ® Õ§ %{domain}Õ¸Ö‚Õ´ + instance_actor_flash: 'Ô±ÕµÕ½ Õ°Õ¡Õ·Õ«Ö‚ Õ¾Õ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Õ¤Õ¥Ö€Õ¡Õ½Õ¡Õ¶ Õ§, Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¨, Õ¡ÕµÕ¬ Õ¸Õ¹ Õ¡Õ¶Õ°Õ¡Õ¿ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚, Õ°Õ¡Õ´Õ¡Ö€Ö‰ Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¸Õ¾, Õ¸Ö‚ Õ¹ÕºÕ§Õ¿Ö„ Õ§ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ«, Õ¥Õ©Õ§ Õ¹Õ§Ö„ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¸Õ²Õ» Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¨, Õ¸Ö€Õ« Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´ ÕºÕ§Õ¿Ö„ Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ§Ö„ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨Ö‰ + +' learn_more: Ô»Õ´Õ¡Õ¶Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶ privacy_policy: Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ see_whats_happening: ÕÕ¥Õ½ Õ«Õ¶Õ¹ Õ¡ Õ¯Õ¡Õ¿Õ¡Ö€Õ¾Õ¸Ö‚Õ´ @@ -20,28 +32,53 @@ hy: status_count_after: one: Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ½ other: Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ½ + status_count_before: ÕˆÕ¾Ö„Õ¥Ö€ Õ£Ö€Õ¥Õ¬ Õ¥Õ¶Õ + tagline: Õ€Õ¥Õ¿Õ¥Ö‚Õ«Ö€ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤ Õ¥Ö‚ Õ£Õ¿Õ«Ö€ Õ¶Õ¸Ö€Õ¥Ö€Õ«Õ¶ + terms: Ô¾Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨ + unavailable_content: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¸Õ² Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶Õ¥Ö€ unavailable_content_description: domain: ÕÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹ + reason: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨Õ + rejecting_media: Ô±ÕµÕ½ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¶Õ¥Ö€Õ« Õ¶Õ«Ö‚Õ©Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ´Õ·Õ¡Õ¯Õ¸Ö‚Õ« Õ¯Õ¡Õ´ ÕºÕ¡Õ°Õ¸Ö‚Õ«Ö‰ Õ‰Õ¥Õ¶ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ« Õ¶Õ¡Ö‡ Õ´Õ¡Õ¶Ö€Õ¡ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ¨, ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬Õ¸Õ¾ Õ«Õ¶Ö„Õ¶Õ¸Ö‚Ö€Õ¸ÕµÕ¶ Õ¡Õ¶ÖÕ¸Ö‚Õ´ Õ¤Õ§ÕºÕ« Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯ Õ¶Õ«Ö‚Õ©Õ¨Ö‰ + rejecting_media_title: Ô¶Õ¿Õ¸Ö‚Õ¡Õ® Õ´Õ¥Õ¤Õ«Õ¡ + silenced: Ô±ÕµÕ½ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ©Õ¡Ö„ÖÕ¸Ö‚Õ¡Õ® Õ¥Õ¶ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ«Ö Õ¥Ö‚ Õ¦Ö€Õ¸ÕµÖÕ¶Õ¥Ö€Õ«Ö, Õ¥Ö‚ Õ¸Õ¹ Õ´Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´ Õ¹Õ« Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¸Ö‚Õ´ Õ¶Ö€Õ¡Õ¶Ö Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ«Ö, Õ¥Õ©Õ§ Õ¶Ö€Õ¡Õ¶Ö Õ¹Õ§Ö„ հետեւում․ + silenced_title: Ô¼Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ® Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶Õ¥Ö€ + suspended: ÕˆÕ¹ Õ´Õ« Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬ Õ¡ÕµÕ½ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶Õ¥Ö€Õ«Ö Õ¹Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¸Ö‚Õ¸Ö‚Õ´, ÕºÕ¡Õ°Õ¸Ö‚Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ ÖƒÕ¸ÕÕ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ¸Ö‚Õ´, Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬ Õ¸Ö€Õ¥Ö‚Õ§ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¯Õ¡Õ´ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¡ÕµÕ½ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ« Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ°Õ¥Õ¿ Õ¡Õ¶Õ°Õ¶Õ¡Ö€ է․ + suspended_title: Ô¿Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¡Õ® Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ«Õ¹Õ¶Õ¥Ö€ + unavailable_content_html: Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¶ Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Ö€Õ¡ÕºÕ§Õ½ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¸Ö‚Õ´ Õ§ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¥Ö‚ Õ·ÖƒÕ¸Ö‚Õ¥Õ¬ Õ¡ÕµÕ¬ Õ¤Õ¡Õ·Õ¶Õ¥Õ¦Õ¥Ö€Ö„Õ« Õ¡ÕµÕ¬ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿Ö‰ ÕÖ€Õ¡Õ¶Ö„ Õ¢Õ¡ÖÕ¡Õ¼Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¶ Õ¥Õ¶, Õ¸Ö€Õ¸Õ¶Ö„ Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ Õ°Õ§Õ¶Ö Õ¡ÕµÕ½ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ user_count_after: one: Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€ other: Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€ user_count_before: Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¥Õ¶ what_is_mastodon: Ô»ÕžÕ¶Õ¹ Õ§ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ accounts: + choices_html: "%{name}-Õ« Õ¨Õ¶Õ¿Ö€Õ¡Õ¶Õ«Õ" + endorsements_hint: ÕŽÕ§Õ¢ Õ«Õ¶Õ¿Õ¥Ö€Ö†Õ§ÕµÕ½Õ«Ö Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö, Õ¸Ö€Õ¸Õ¶Ö Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ½, Õ¥Ö‚ Õ¶Ö€Õ¡Õ¶Ö„ Õ¯Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ¥Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰ + featured_tags_hint: Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ ÕµÕ¡Õ¿Õ¸Ö‚Õ¯ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€, Õ¸Ö€Õ¸Õ¶Ö„ Õ¯Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ¥Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²Ö‰ follow: Õ€Õ¥Õ¿Ö‡Õ¥Õ¬ followers: one: Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤ other: Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€ following: Õ€Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ Õ¥Ö„ + instance_actor_flash: Ô±ÕµÕ½ Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ¾Õ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Õ¤Õ¥Ö€Õ¡Õ½Õ¡Õ¶ Õ§, Õ¸Ö€Õ¨ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÕ¶Õ¸Ö‚Õ´ Õ§ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ¨, Õ¥Ö‚ Õ¸Õ¹ Õ¸Ö€Õ¥Ö‚Õ§ Õ¡Õ¶Õ°Õ¡Õ¿ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Ö‰ Ô±ÕµÕ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¸Õ¾ Õ¥Ö‚ Õ¹ÕºÕ§Õ¿Ö„ Õ§ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ«Ö‰ joined: Õ„Õ«Õ¡ÖÕ¥Õ¬ Õ¥Õ¶ %{date} last_active: Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ©Õ¸Ö‚Õ©Õ¨ + link_verified_on: ÕÕ¸ÕµÕ¶ ÕµÕ²Õ´Õ¡Õ¶ Õ¿Õ«Ö€Õ¡ÕºÕ¥Õ¿Õ¸Ö‚Õ´Õ¨ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ¡Õ® Õ§Õ %{date}ÖŠÕ«Õ¶ media: Õ„Õ¥Õ¤Õ«Õ¡ + moved_html: "%{name} Õ¿Õ¥Õ²Õ¡ÖƒÕ¸ÕÕ¸Ö‚Õ¥Õ¬ Õ§ %{new_profile_link}" + network_hidden: Ô±ÕµÕ½ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§ never_active: ÔµÖ€Õ¢Õ¥Ö„ + nothing_here: Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¢Õ¡Õ¶ Õ¹Õ¯Õ¡Õµ + people_followed_by: Õ„Õ¡Ö€Õ¤Õ«Õ¯, Õ¸Ö€Õ¸Õ¶Ö %{name}Õ¨ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ§ + people_who_follow: Õ„Õ¡Ö€Õ¤Õ«Õ¯, Õ¸Ö€Õ¸Õ¶Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ %{name}Õ«Õ¶ + pin_errors: + following: Ô´Õ¸Ö‚ ÕºÕ§Õ¿Ö„ Õ§ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ½ Õ´Õ¡Ö€Õ¤Õ¸Ö‚Õ¶, Õ¸Ö€Õ«Õ¶ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ ÕÖ€Õ¡ÕÕ¸Ö‚Õ½Õ¥Õ¬ posts: one: Ô¹Õ¸Ö‚Õ© other: Ô¹Õ¸Ö‚Õ©Õ¥Ö€Õ«Ö posts_tab_heading: Ô¹Õ©Õ¥Ö€ posts_with_replies: Ô¹Õ©Õ¥Ö€ Õ¥Ö‚ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¶Õ¥Ö€ + reserved_username: Ô¾Õ¡Õ®Õ¯Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶ Õ¡Ö€Õ¤Õ§Õ¶ Õ¾Õ¥Ö€ÖÕ¸Ö‚Õ¡Õ® Õ§ roles: admin: Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€ bot: Ô²Õ¸Õ¿ @@ -50,13 +87,36 @@ hy: unavailable: ÕŠÖ€Õ¸Ö†Õ«Õ¬Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ« unfollow: Õ‰Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ admin: + account_actions: + action: Ô¿Õ¡Õ¿Õ¡Ö€Õ¥Õ¬ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + title: Ô»Ö€Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ %{acct}-Õ« Õ¾Ö€Õ¡Õµ account_moderation_notes: create: Ô¹Õ¸Õ²Õ¶Õ¥Õ¬ Õ¶Õ·Õ¸Ö‚Õ´ + created_msg: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¸Õ¶ Õ¶Õ¸Õ©Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ½Õ¿Õ¥Õ²Õ®Õ¸Ö‚Õ¥Ö delete: Õ‹Õ¶Õ»Õ¥Õ¬ + destroyed_msg: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¸Õ¶ Õ¶Õ¸Õ©Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¾Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¥Ö accounts: + add_email_domain_block: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨ + approve: Ô¸Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¬ + approve_all: Ô¸Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨ + approved_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¥Ö %{username}ÖŠÕ« Õ£Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ ÕµÕ¡ÕµÕ¿Õ¨ + are_you_sure: ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½ + avatar: Ô±Ö‚Õ¡Õ¿Õ¡Ö€ + by_domain: Ô´Õ¸Õ´Õ§Õ¶ + change_email: + changed_msg: Õ€Õ¡Õ·Õ¸Ö‚Õ« էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö + current_email: Õ†Õ¥Ö€Õ¯Õ¡ÕµÕ«Õ½ էլ․ Õ°Õ¡Õ½ÖÕ§ + label: Õ“Õ¸ÕÕ¥Õ¬ Õ§Õ¬. Õ°Õ¡Õ½ÖÕ§Õ¶ + new_email: Õ†Õ¸Ö€ էլ․ ÖƒÕ¸Õ½Õ¿ + submit: Õ“Õ¸ÕÕ¥Õ¬ Õ§Õ¬. Õ°Õ¡Õ½ÖÕ§Õ¶ + title: Õ“Õ¸ÕÕ¥Õ¬ էլ․ ÖƒÕ¸Õ½Õ¿Õ¨ %{username}Õ« Õ°Õ¡Õ´Õ¡Ö€ + confirm: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ confirmed: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¡Õ® Õ§ confirming: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´ + delete: Õ‹Õ¶Õ»Õ¥Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ deleted: Õ‹Õ¶Õ»Õ¾Õ¡Õ® Õ§ + demote: Ô±Õ½Õ¿Õ«Õ³Õ¡Õ¶Õ¡Õ¦Ö€Õ¯Õ¥Õ¬ + destroyed_msg: "%{username}ÖŠÕ« Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ°Õ¥Ö€Õ©Õ¡Õ£Ö€Õ¸Ö‚Õ¥Õ¬ Õ§ Õ¡Õ¶ÕµÕ¡ÕºÕ¡Õ² Õ»Õ¶Õ»Õ¸Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ« Õ·Õ¡Ö€Ö„Õ¸Ö‚Õ´" disable: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ disable_two_factor_authentication: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ 2FA disabled: Ô±Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§ @@ -64,12 +124,16 @@ hy: domain: Ô´Õ¸Õ´Õ¥Õ¶ edit: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ email: Ô·Õ¬. ÖƒÕ¸Õ½Õ¿ + email_status: Էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ enable: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ enabled: Õ„Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ + enabled_msg: "%{username}ÖŠÕ« Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ½Õ¡Õ¼Õ¥ÖÕ¸Ö‚Õ¥Ö" followers: Õ€Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€ follows: Õ€Õ¥Õ¿Ö‡Õ¸Õ²Õ¶Õ¥Ö€ header: ÕŽÕ¥Ö€Õ¶Õ¡Õ£Õ«Ö€ inbox_url: Õ„Õ¸Ö‚Õ¿Ö„Õ¡ÕµÕ«Õ¶ URL + invite_request_text: Õ„Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¶Õ¥Ö€Õ¨ + invited_by: Õ€Ö€Õ¡Ö‚Õ«Ö€Õ¸Ö‚Õ¥Õ¬ Õ§ ip: IP joined: Õ„Õ«Õ¡ÖÕ¡Õ® Õ§ location: @@ -77,89 +141,525 @@ hy: local: ÕÕ¥Õ²Õ¡ÕµÕ«Õ¶ remote: Õ€Õ¥Õ¼Õ¡Õ¯Õ¡ title: ÕÕ¥Õ²Õ¡Õ¤Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ + login_status: Õ„Õ¸Ö‚Õ¿Ö„Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + media_attachments: Õ„Õ¥Õ¤Õ«Õ¡ Õ¯ÖÕ¸Ö€Õ¤Õ¶Õ¥Ö€ + memorialize: Ô´Õ¡Ö€Õ±Õ¶Õ¥Õ¬ Õ°Õ«Õ·Õ¡Õ¿Õ¡Õ¯Õ¡Ö€Õ¡Õ¶ + memorialized: Õ…Õ«Õ·Õ¥ÖÕ¸Ö‚Õ¡Õ® + memorialized_msg: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² %{username}ÖŠÕ¨ ÖƒÕ¸ÕÕ¸Ö‚Õ¥Ö ÕµÕ«Õ·Õ¡Õ¿Õ¡Õ¯Õ« Õ°Õ¡Õ·Õ¸Ö‚Õ« moderation: active: Ô±Õ¯Õ¿Õ«Õ¾ all: Ô²Õ¸Õ¬Õ¸Ö€Õ¨ pending: ÕÕºÕ¡Õ½Õ¸Ö‚Õ´ + silenced: Ô¼Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ® + suspended: Ô¿Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¡Õ® + title: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ + moderation_notes: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ¶Õ·Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + most_recent_activity: ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¡Õ¯Õ¿Õ«Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + most_recent_ip: ÕŽÕ¥Ö€Õ»Õ«Õ¶ IP + no_account_selected: ÕˆÕ¹ Õ´Õ« Õ°Õ¡Õ·Õ«Ö‚ Õ¹Õ« ÖƒÕ¸ÕÕ¸Ö‚Õ¥Õ¬, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Õ¥Ö‚, Õ¸Õ¹ Õ´Õ¥Õ¯Õ¨ Õ¹Õ« Õ¨Õ¶Õ¿Ö€Õ¸Ö‚Õ¥Õ¬ + no_limits_imposed: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¹Õ¯Õ¡Õ¶ + not_subscribed: Ô²Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ¹Õ§ + pending: ÕÕºÕ¡Õ½Õ¸Ö‚Õ´ Õ§ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ´Õ¡Õ¶ + perform_full_suspension: Ô¿Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ´ + promote: Ô±Õ»Õ¡Õ¯ÖÕ¥Õ¬ + protocol: Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ¯Õ¡Ö€Õ£ public: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ + push_subscription_expires: PuSH Õ¢Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ½ÕºÕ¡Õ¼Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ + redownload: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + redownloaded_msg: "%{username}ÖŠÕ« Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ²Õ¢Õ«Ö‚Ö€Õ«Ö Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥Ö" + reject: Õ„Õ¥Ö€ÕªÕ¥Õ¬ + reject_all: Õ„Õ¥Ö€ÕªÕ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨ + rejected_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¥Ö %{username}ÖŠÕ« Õ£Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ ÕµÕ¡ÕµÕ¿Õ¨ + remove_avatar: Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Ö‚Õ¡Õ¿Õ¡Ö€Õ¨ + remove_header: Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ£Õ¬ÕÕ¡Õ£Õ«Ö€Õ¨ + removed_avatar_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ°Õ¥Õ¼Õ¡ÖÕ¸Ö‚Õ¥Ö %{username}ÖŠÕ« Õ¡Ö‚Õ¡Õ¿Õ¡Ö€Õ¨ + removed_header_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ°Õ¥Õ¼Õ¡ÖÕ¸Ö‚Õ¥Ö %{username}ÖŠÕ« Õ£Õ¬ÕÕ¡Õ¶Õ¯Õ¡Ö€Õ¨ + resend_confirmation: + already_confirmed: Õ•Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¶ Õ¡Ö€Õ¤Õ§Õ¶ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¡Õ® Õ§ + send: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ«Õ´Õ¡Õ¯Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¯Ö€Õ¯Õ«Õ¶ + success: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ«Õ´Õ¡Õ¯Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Ö + reset: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ + reset_password: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¡Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ + resubscribe: Ô¿Ö€Õ¯Õ«Õ¶ Õ¢Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ¥Õ¬ + role: Ô¹Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ + roles: + admin: Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€ + moderator: Õ„Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€ + staff: Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´ + user: OÕ£Õ¿Õ¡Õ¿Õ§Ö€ + search: ÕˆÖ€Õ¸Õ¶Õ¥Õ¬ + search_same_email_domain: Ô±ÕµÕ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€ Õ¶Õ¸ÕµÕ¶ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¤Õ¸Õ´Õ§ÕµÕ¶Õ¸Õ¾ + search_same_ip: Ô±ÕµÕ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€ Õ¶Õ¸ÕµÕ¶ IPÖŠÕ¸Õ¾ + sensitive: Ô¶Õ£Õ¡ÕµÕ¸Ö‚Õ¶ + sensitized: Õ¶Õ·Õ¸Ö‚Õ¥Ö Õ¸Ö€ÕºÕ§Õ½ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡Ö + shared_inbox_url: Ô¸Õ¶Õ¤Õ°Õ¡Õ¶Õ¸Ö‚Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡ÕµÕ«Õ¶ URL + show: + created_reports: Ô¿Õ¡Õ¦Õ´Õ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€ + targeted_reports: Ô±ÕµÕ¬Õ¸Ö Õ¯Õ¸Õ²Õ´Õ«Ö Õ¢Õ¸Õ²Õ¸Ö„Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® + silence: Ô¼Õ¼Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + silenced: Ô¼Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ® + statuses: Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + subscribe: Ô²Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ¥Õ¬ + suspended: Ô¿Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¡Õ® + suspension_irreversible: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¡Õ¶Õ¤Õ¡Ö€Õ± Õ»Õ¶Õ»Õ¸Ö‚Õ¥ÖÕ«Õ¶Ö‰ Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¡ÕºÕ¡Õ¯Õ¡Õ½Õ¥ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨Õ Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¸Õ¾ Õ¡ÕµÕ¶ Õ¯Õ«Ö€Õ¡Õ¼Õ¥Õ¬Õ«, Õ¢Õ¡ÕµÖ Õ¡ÕµÕ¶ Õ¹Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ« Õ¶Õ¡ÕÕ¯Õ«Õ¶ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ + suspension_reversible_hint_html: Õ€Õ¡Õ·Õ«Ö‚Õ¨ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¥Ö, Õ¥Ö‚ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¶ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¡ÕºÕ§Õ½ Õ¯Õ¨ Õ¾Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ« %{date}Õ«Õ¶Ö‰ Õ„Õ«Õ¶Õ¹Õ¥Ö‚ Õ¡ÕµÕ¤, Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¸Ö‚Õ¥Õ¬Õ Õ¡Õ¼Õ¡Õ¶Ö Õ¯Õ¸Õ²Õ´Õ¶Õ¡Õ¯Õ« Õ¡Õ¦Õ¤Õ¥ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ«Ö‰ ÔµÕ©Õ§ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ Õ¾Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ´Õ«Õ¡Õ¶Õ£Õ¡Õ´Õ«Ö, Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¤Õ¡ Õ¡Õ¶Õ¥Õ¬ Õ¶Õ¥Ö€Ö„Õ¥Ö‚Õ¸Ö‚Õ´Ö‰ + time_in_queue: Õ€Õ¥Ö€Õ©Õ¸Ö‚Õ´ Õ§ %{time} + title: Õ€Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€ + unconfirmed_email: Õ‰Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¡Õ® էլ․ Õ°Õ¡Õ½ÖÕ§ + undo_sensitized: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡ÖÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + undo_silenced: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ´Õ¨ + undo_suspension: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ´Õ¨ + unsilenced_msg: "%{username}ÖŠÕ« Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¤Õ¡Ö€Õ±Õ¡Ö‚ Õ¡Õ¶Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯" + unsubscribe: Ô±ÕºÕ¡Õ¢Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ¥Õ¬ + unsuspended_msg: "%{username}ÖŠÕ« Õ°Õ¡Õ·Õ«Ö‚ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¥ÖÖ‰" username: Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ¶Õ¸Ö‚Õ¶ + view_domain: ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Õ´ÖƒÕ¸ÖƒÕ¸Ö‚Õ´Õ¨ warn: Õ†Õ¡ÕÕ¡Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´ web: ÕŽÕ¥Õ¢ + whitelisted: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ°Õ¡Õ´Õ¡Ö€ action_logs: action_types: + assigned_to_self_report: Ô²Õ¸Õ²Õ¸Ö„Õ¥Õ¬ + change_email_user: Õ“Õ¸ÕÕ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ + confirm_user: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ + create_account_warning: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´ + create_announcement: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + create_custom_emoji: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€Õ¨ + create_domain_allow: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + create_domain_block: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ + create_email_domain_block: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ§Õ« Õ¤Õ¸Õ´Õ§ÕµÕ¶Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ + create_ip_block: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ IP Õ¯Õ¡Õ¶Õ¸Õ¶ + demote_user: Ô±Õ½Õ¿Õ«Õ³Õ¡Õ¶Õ¡Õ¦Ö€Õ¯Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ + destroy_announcement: Õ‹Õ¶Õ»Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + destroy_custom_emoji: Õ‹Õ¶Õ»Õ¥Õ¬ Õ§Õ´Õ¸Õ»Õ«Õ¶ + destroy_domain_allow: Õ‹Õ¶Õ»Õ¥Õ¬ Õ¤Õ¸Õ´Õ§Õ¶Õ« Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + destroy_domain_block: Ô±ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¤Õ¸Õ´Õ§Õ¶Õ¨ + destroy_email_domain_block: Ô±ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ էլ․ Õ°Õ¡Õ½ÖÕ§Õ« Õ¤Õ¸Õ´Õ§Õ¶Õ¨ + destroy_ip_block: Õ‹Õ¶Õ»Õ¥Õ¬ IP Õ¯Õ¡Õ¶Õ¸Õ¶Õ¨ + destroy_status: Õ‹Õ¶Õ»Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ disable_2fa_user: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ 2FA + disable_custom_emoji: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€Õ¨ + disable_user: Ô±ÕºÕ¡Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ + enable_custom_emoji: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€Õ¨ + enable_user: Ô±Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ + memorialize_account: Õ…Õ«Õ·Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + promote_user: Ô±Õ»Õ¡Õ¯ÖÕ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ + remove_avatar_user: Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Ö‚Õ¡Õ¿Õ¡Ö€Õ¨ + reopen_report: ÕŽÕ¥Ö€Õ¡Õ¢Õ¡ÖÕ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¨ + reset_password_user: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¡Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ + resolve_report: Ô¼Õ¸Ö‚Õ®Õ¡Ö€Õ¥Õ¬ Õ¦Õ¥Õ¯Õ¸ÕµÖÕ¨ + sensitive_account: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¥Õ¤Õ«Õ¡Õ¶ Õ¶Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡Ö + silence_account: Ô¼Õ¼Õ¥ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + suspend_account: Ô¿Õ¡Õ½Õ¥ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + unassigned_report: Õ€Õ¡Õ¶Õ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¨ + unsensitive_account: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¥Õ¤Õ«Õ¡Õ¶ Õ¹Õ¶Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡Ö + unsilence_account: Ô¼Õ½Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¶ + unsuspend_account: Ô±ÕºÕ¡Õ¯Õ¡Õ½Õ¥ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + update_announcement: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + update_custom_emoji: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ´Õ¸Õ»Õ«Õ¶Õ¥Ö€Õ¨ + update_domain_block: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ + update_status: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ + actions: + assigned_to_self_report: "%{name} Õ¢Õ¸Õ²Õ¸Ö„Õ¥Õ¬ Õ§ %{target} Õ«Ö€Õ¥Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€" + change_email_user: "%{name} ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ§ %{target} Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶" + confirm_user: "%{name} Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ§ %{target} Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶" + create_account_warning: "%{name} Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÖ€Õ¥Õ¬ Õ§ %{target}Õ«Õ¶" + create_announcement: "%{name} Õ½Õ¿Õ¥Õ²Õ®Õ¥Ö Õ¶Õ¸Ö€ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ %{target}" + create_custom_emoji: "%{name} Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ§ Õ¶Õ¸Ö€ Õ§Õ´Õ¸Õ»Õ«Õ %{target}" + create_domain_allow: "%{name} Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡Õ¶ %{target} Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ°Õ¥Õ¿" + create_domain_block: "%{name} Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Ö %{target} Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨" + create_email_domain_block: "%{name} Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ© %{target}" + create_ip_block: "%{name} Õ½Õ¿Õ¥Õ²Õ®Õ¥Ö Õ¯Õ¡Õ¶Õ¸Õ¶ %{target} IPÖŠÕ« Õ°Õ¡Õ´Õ¡Ö€" + demote_user: "%{name} Õ¡Õ½Õ¿Õ«Õ³Õ¡Õ¶Õ¡Õ¦Ö€Õ¯Õ¥Ö Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» %{target}" + destroy_announcement: "%{name} Õ»Õ¶Õ»Õ¥Ö ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ %{target}" + destroy_custom_emoji: "%{name} Õ»Õ¶Õ»Õ¥Õ¬ Õ§ %{target} Õ§Õ´Õ¸Õ»Õ«Õ¶" + destroy_domain_allow: "%{name} Õ¹Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Ö Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡Õ¶ %{target} Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ°Õ¥Õ¿" + destroy_domain_block: "%{name} Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Ö Õ¿Õ«Ö€Õ¸ÕµÕ© %{target}" + destroy_email_domain_block: "%{name} Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ© %{target}" + destroy_ip_block: "%{name} Õ»Õ¶Õ»Õ¥Ö Õ¯Õ¡Õ¶Õ¸Õ¶Õ¨ %{target} IPÖŠÕ« Õ°Õ¡Õ´Õ¡Ö€" + destroy_status: "%{name} Õ»Õ¶Õ»Õ¥Ö %{target}Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´" + disable_2fa_user: "%{name}Õ¨ Õ¯Õ¡Õ½Õ¥ÖÖ€Õ¥Ö 2F ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¨ %{target} Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ°Õ¡Õ´Õ¡Ö€" + disable_custom_emoji: "%{name} Õ¡ÕºÕ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÖ€Õ¥Õ¬ Õ§ %{target} Õ§Õ´Õ¸Õ»Õ«Õ¶" + disable_user: "%{name} Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ§ Õ´Õ¸Ö‚Õ¿Ö„Õ¨ %{target} Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ°Õ¡Õ´Õ¡Ö€" + enable_custom_emoji: "%{name} Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÖ€Õ¥Õ¬ Õ§ %{target} Õ§Õ´Õ¸Õ»Õ«Õ¶" + enable_user: "%{name} Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Ö Õ´Õ¸Ö‚Õ¿Ö„ %{target} Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ°Õ¡Õ´Õ¡Ö€" + memorialize_account: "%{name} Õ¤Õ¡Ö€Õ±Ö€Õ¥Ö %{target}Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¨ ÕµÕ«Õ·Õ¡Õ¿Õ¡Õ¯Õ« Õ§Õ»" + promote_user: "%{name} Õ¡Õ»Õ¡Õ¯ÖÕ¥Ö Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ %{target}" + remove_avatar_user: "%{name} Õ°Õ¥Õ¼Õ¡ÖÖ€Õ¥Ö %{target}Õ« Õ¡Ö‚Õ¡Õ¿Õ¡Ö€Õ¨" + reopen_report: "%{name} Õ¾Õ¥Ö€Õ¡Õ¢Õ¡ÖÕ¥Ö Õ¢Õ¸Õ²Õ¸Ö„ %{target}" + reset_password_user: "%{name} Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Ö Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ %{target}" + resolve_report: "%{name} Õ¬Õ¸Ö‚Õ®Õ¡Ö€Õ¥Ö Õ¢Õ¸Õ²Õ¸Ö„Õ¨ %{target}" + sensitive_account: "%{name}Õ¨ Õ¶Õ·Õ¥Ö %{target}Õ« Õ´Õ¥Õ¤Õ«Õ¡Õ¶ Õ¸Ö€ÕºÕ§Õ½ Õ¦Õ£Õ¡ÕµÕ¸Ö‚Õ¶" + silence_account: "%{name} Õ¬Õ¼Õ¥ÖÖ€Õ¥Ö %{target}Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¨" + suspend_account: "%{name} Õ¬Õ¼Õ¥ÖÖ€Õ¥Ö %{target}Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¨" + unassigned_report: "%{name} Õ¹Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¸Ö‚Õ¡Õ® Õ¢Õ¸Õ²Õ¸Ö„ %{target}" + unsensitive_account: "%{name}Õ¨ Õ°Õ¥Õ¼Õ¡ÖÖ€Õ¥Ö %{target}ÖŠÕ« Õ´Õ¥Õ¤Õ«Õ¡ÕµÕ« Õ¦Õ£Õ¡ÕµÕ¸Ö‚Õ¶ Õ¶Õ·Õ¸Ö‚Õ´Õ¨" + unsilence_account: "%{name}ÖŠÕ¨ Õ°Õ¡Õ¶Õ¥Ö Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ´Õ¨ %{target}ÖŠÕ« Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö" + unsuspend_account: "%{name}Õ¨ Õ¡ÕºÕ¡Õ¯Õ¡Õ½Õ¥ÖÖ€Õ¥Ö %{target}Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¨" + update_announcement: "%{name}Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥Ö %{target}Õ« ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨" + update_custom_emoji: "%{name} Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥Õ¬ Õ§ %{target} Õ§Õ´Õ¸Õ»Õ«Õ¶" + update_domain_block: "%{name}Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥Ö %{target}Õ« Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨" + update_status: "%{name}Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥Ö %{target}Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¨" + deleted_status: "(Õ»Õ¶Õ»Õ¸Ö‚Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´)" + empty: ÕˆÕ¹ Õ´Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¹Õ¯Õ¡ÕµÖ‰ + filter_by_action: Ô¶Õ¿Õ¥Õ¬ Õ¨Õ½Õ¿ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ + filter_by_user: Ô¶Õ¿Õ¥Õ¬ Õ¨Õ½Õ¿ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» + title: ÕÕ¿Õ¸Ö‚Õ£Õ´Õ¡Õ¶ Õ´Õ¡Õ¿Õ¥Õ¡Õ¶ announcements: + destroyed_msg: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ»Õ¶Õ»Õ¸Ö‚Õ¥Ö + edit: + title: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + empty: ÕˆÕ¹ Õ´Õ« ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Ö live: ÕˆÖ‚Õ²Õ«Õ² + new: + create: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + title: Õ†Õ¸Ö€ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + published_msg: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¸Ö‚Õ¥Ö + scheduled_for: ÕŠÕ¬Õ¡Õ¶Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ¡Õ® Õ§ %{time}Õ«Õ¶ + scheduled_msg: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¶Õ¡ÕÕ¡ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¸Ö‚Õ¥Ö Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ´Õ¡Õ¶ + title: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ + unpublished_msg: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¸Ö‚Õ¥Ö + updated_msg: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥Ö custom_emojis: + assign_category: Ô¿ÖÕ¥Õ¬ Õ¯Õ¡Õ¿Õ¥Õ£Õ¸Ö€Õ«Õ¡ + by_domain: ÕÕ«Ö€Õ¸ÕµÕ© + copied_msg: Ô·Õ´Õ¸Õ»Õ«Õ« Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ½Õ¿Õ¥Õ²Õ®Õ¸Ö‚Õ¡Õ® Õ§ copy: ÕŠÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Õ¬ + copy_failed_msg: Õ‰ÕµÕ¡Õ»Õ¸Õ²Ö‚Õ¥Ö Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ§Õ´Õ¸Õ»Õ«Õ« Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Ö…Ö€Õ«Õ¶Õ¡Õ¯ + create_new_category: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€ Õ¯Õ¡Õ¿Õ¥Õ£Õ¸Ö€Õ«Õ¡ + created_msg: Ô·Õ´Õ¸Õ»Õ«Õ¶ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ½Õ¿Õ¥Õ²Õ®Õ¸Ö‚Õ¥Ö delete: Õ‹Õ¶Õ»Õ¥Õ¬ + destroyed_msg: Ô·Õ´Õ¸Õ»Õ«Õ¶ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ»Õ¶Õ»Õ¸Ö‚Õ¥Ö disable: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ + disabled: Ô±Õ¶Õ»Õ¡Õ¿Õ¸Ö‚Õ¡Õ® + disabled_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¥Ö Õ§Õ´Õ¸Õ»Õ«Õ¶ + emoji: Ô¶Õ´Õ¡ÕµÕ¬Õ«Õ¯ + enable: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ + enabled: Õ„Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® + enabled_msg: Õ…Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¥Ö Õ§Õ´Õ¸Õ»Õ«Õ¶ + image_hint: PNG Õ´Õ«Õ¶Õ¹Õ¥Ö‚ 50KB list: Õ‘Õ¡Õ¶Õ¯ + listed: Õ‘Õ¸Ö‚ÖÕ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® + new: + title: Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€ Õ§Õ´Õ¸Õ»Õ« + not_permitted: ÕÕ¸Ö‚Õ¥Õ¡Õ¬ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶ Õ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ©Õ¸ÕµÕ¬Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ overwrite: ÕŽÕ¥Ö€Õ¡Õ£Ö€Õ¥Õ¬ + shortcode: Õ€Õ¡ÕºÕ¡Õ¾Õ¸Ö‚Õ´ + shortcode_hint: Ô±Õ´Õ¥Õ¶Õ¡Ö„Õ«Õ¹Õ¨ 2 Õ¶Õ«Õ·, Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¢Õ¢Õ¥Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¶Õ«Õ·Õ¥Ö€, Õ©Õ¸Ö‚Õ¥Ö€ Õ¥Ö‚ Õ¨Õ¶Õ¤Õ£Õ®Õ«Õ¯Õ¶Õ¥Ö€ + title: ÕÕ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ§Õ´Ö…Õ»Õ«Õ¶Õ¥Ö€ + uncategorized: Õ‰Õ¤Õ¡Õ½Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ¡Õ® + unlist: Ô±ÕºÕ¡ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ´ + unlisted: Ô¾Õ¡Õ®Õ¸Ö‚Õ¯ + update_failed_msg: Ô·Õ´Õ¸Õ»Õ«Õ¶ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥Õ¬ + updated_msg: Ô·Õ´Õ¸Õ»Õ«Õ¶ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¥Ö upload: ÕŽÕ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ + dashboard: + authorized_fetch_mode: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯ + config: Ô¿Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´ + feature_deletions: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¥Õ¼Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ + feature_invites: Õ€Ö€Õ¡Ö‚Õ§Ö€Õ« ÕµÕ²Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + feature_profile_directory: Õ•Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ´Õ¡Õ¿Õ¥Õ¡Õ¶ + feature_registrations: Ô³Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ + feature_relay: Õ–Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ·Õ¥Ö€Õ¿ + feature_spam_check: Õ€Õ¡Õ¯Õ¡-Õ½ÕºÕ¡Õ´ + feature_timeline_preview: Õ€Õ¸Õ½Ö„Õ« Õ¶Õ¡ÕÕ¡Õ¤Õ«Õ¿Õ¸Ö‚Õ´ + features: Õ…Õ¡Õ¿Õ¯Õ¡Õ¶Õ«Õ·Õ¶Õ¥Ö€ + hidden_service: Õ–Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ Õ©Õ¡Ö„Õ¶Õ¸Ö‚Õ¡Õ® Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿ + open_reports: Õ¢Õ¡Ö Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€ + pending_tags: ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¶ Õ½ÕºÕ¡Õ½Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ´Õ¡Õ¶ + pending_users: Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ¶ Õ½ÕºÕ¡Õ½Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ´Õ¡Õ¶ + recent_users: ÕŽÕ¥Ö€Õ»Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ¨ + search: ÕÕ¥Ö„Õ½Õ¿Õ¡ÕµÕ«Õ¶ Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´ + single_user_mode: Õ„Õ§Õ¯ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ¼Õ¥ÕªÕ«Õ´ + software: Ô¾Ö€Õ¡Õ£Ö€Õ¡ÕµÕ«Õ¶ Õ¡ÕºÕ¡Õ°Õ¸Õ¾Õ¸Ö‚Õ´ + space: ÕÕ¡Ö€Õ¡Õ®Ö„Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ + title: Ô³Õ¸Ö€Õ®Õ«Ö„Õ¶Õ¥Ö€Õ« Õ¾Õ¡Õ°Õ¡Õ¶Õ¡Õ¯ + total_users: Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Õ¸Ö‚Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€ + trends: Ô¹Ö€Õ¥Õ¶Õ¤Õ¶Õ¥Ö€ + week_interactions: Õ·Õ¡Õ¢Õ¡Õ©Õ¸Ö‚Õ¡Õµ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ + week_users_active: Õ·Õ¡Õ¢Õ¡Õ©Õ¸Ö‚Õ¡Õµ Õ¡Õ¯Õ¿Õ«Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + week_users_new: Õ·Õ¡Õ¢Õ¡Õ©Õ¸Ö‚Õ¡Õµ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€ + whitelist_mode: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ¼Õ¥ÕªÕ«Õ´ + domain_allows: + add_new: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ°Õ¥Õ¿ + created_msg: ÕÕ«Ö€Õ¸ÕµÕ©Õ¨ ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¸Ö‚Õ¥Ö Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚ + undo: Õ‰Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡Õ¶ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ°Õ¥Õ¿ domain_blocks: + add_new: Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ + created_msg: ÕÕ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶ Õ¨Õ¶Õ©Õ¡ÖÕ¡Ö‚ + destroyed_msg: ÕÕ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ Õ¥Õ¿Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Ö + domain: ÕÕ«Ö€Õ¸ÕµÕ© + edit: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ new: + create: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ severity: noop: ÕˆÕ¹ Õ´Õ« silence: Ô¼Õ¸Ö‚Õ¼ + suspend: Ô¿Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ´ + title: Õ†Õ¸Ö€ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ + private_comment: Õ“Õ¡Õ¯ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + public_comment: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + reject_media: Õ„Õ¥Ö€ÕªÕ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡ Ö†Õ¡ÕµÕ¬Õ¥Ö€Õ¨ + reject_reports: Õ„Õ¥Ö€ÕªÕ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€Õ¨ + rejecting_media: Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ´Õ¥Õ¤Õ«Õ¡ Ö†Õ¡ÕµÕ¬Õ¥Ö€ + rejecting_reports: Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¢Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€ + severity: + silence: Õ¬Õ¼Õ¥ÖÕ¸Ö‚Õ¡Õ® + suspend: Õ¯Õ¡Õ½Õ¥ÖÕ¸Ö‚Õ¡Õ® show: + title: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ %{domain}Õ« Õ°Õ¡Õ´Õ¡Ö€ undo: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ + undo: ÔµÕ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ + view: ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨ email_domain_blocks: add_new: Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€Õ¨ + created_msg: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¥Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ© delete: Õ‹Õ¶Õ»Õ¥Õ¬ + destroyed_msg: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¥Ö Õ§Õ¬â€¤ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ© domain: Ô´Õ¸Õ´Õ¥Õ¶ + empty: ÕˆÕ¹ Õ´Õ« էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¿Õ«Ö€Õ¸ÕµÕ© Õ¡ÕµÕªÕ´ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ¹Õ§Ö‰ + from_html: "%{domain}Õ«Ö" new: create: Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¤Õ¸Õ´Õ¥Õ¶ + title: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¶Õ¸Ö€ Õ¿Õ«Ö€Õ¸ÕµÕ© + title: էլ․ ÖƒÕ¸Õ½Õ¿Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¶Õ¥Ö€ instances: by_domain: Ô´Õ¸Õ´Õ¥Õ¶ + empty: Ô´Õ¸Õ´Õ¥ÕµÕ¶Õ¶Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Õ¬ + known_accounts: + one: "%{count} ÕµÕ¡ÕµÕ¿Õ¶Õ« Õ°Õ¡Õ·Õ«Ö‚" + other: "%{count} ÕµÕ¡ÕµÕ¿Õ¶Õ« Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€" moderation: all: Ô²Õ¸Õ¬Õ¸Ö€Õ¨ limited: ÕÕ¡Õ°Õ¡Õ´Õ¡Õ¶ÖƒÕ¡Õ¯ + title: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ + private_comment: Õ“Õ¡Õ¯ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + public_comment: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + title: Ô´Õ¡Õ·Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ + total_blocked_by_us: Õ„Õ¥Õ¶Ö„ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¥Õ¶Ö„ + total_followed_by_them: Õ†Ö€Õ¡Õ¶Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ + total_followed_by_us: Õ„Õ¥Õ¶Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ + total_reported: Ô²Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€ Õ¶Ö€Õ¡Õ¶Ö Õ´Õ¡Õ½Õ«Õ¶ + total_storage: Õ„Õ¥Õ¤Õ«Õ¡ Õ¯ÖÕ¸Ö€Õ¤Õ¶Õ¥Ö€ + invites: + deactivate_all: Ô±ÕºÕ¡Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ«Õ¶ + filter: + all: Ô²Õ¸Õ¬Õ¸Ö€Õ¨ + available: Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« + expired: ÕÕºÕ¡Õ¼Õ¸Ö‚Õ¡Õ® + title: Ô¶Õ¿Õ«Õ¹ + title: Õ€Ö€Õ¡Ö‚Õ§Ö€Õ¶Õ¥Ö€ + ip_blocks: + add_new: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¯Õ¡Õ¶Õ¸Õ¶ + created_msg: Ô²Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¸Ö‚Õ¥Ö Õ¶Õ¸Ö€ IP Õ¯Õ¡Õ¶Õ¸Õ¶ + delete: Õ‹Õ¶Õ»Õ¥Õ¬ + expires_in: + '1209600': 2 Õ·Õ¡Õ¢Õ¡Õ© + '15778476': 6 Õ¡Õ´Õ«Õ½ + '2629746': 1 Õ¡Õ´Õ«Õ½ + '31556952': 1 Õ¿Õ¡Ö€Õ« + '86400': 1 Ö…Ö€ + '94670856': 3 Õ¿Õ¡Ö€Õ« + new: + title: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€ IP Õ¯Õ¡Õ¶Õ¸Õ¶ + title: IP Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€ + pending_accounts: + title: ÕÕºÕ¡Õ½Õ¸Õ² Õ°Õ¡Õ·Õ«Ö‚Õ¶Õ¥Ö€ (%{count}) + relationships: + title: "%{acct}Õ« ÕµÕ¡Ö€Õ¡Õ¢Õ¥Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€" relays: + add_new: Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€ Õ¾Õ¥Ö€Õ¡Õ°Õ¥Õ¼Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ«Õ¹ + delete: Õ‹Õ¶Õ»Õ¥Õ¬ disable: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ disabled: Ô±Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§ enable: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ enabled: Õ„Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ + save_and_enable: ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ Õ¥Ö‚ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ status: Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + title: ÕŽÕ¥Ö€Õ¡Õ°Õ¥Õ¼Õ¡Ö€Õ±Õ¡Õ¯Õ«Õ¹Õ¶Õ¥Ö€ reports: + account: + notes: + one: "%{count} Õ¶Õ¸Õ©" + other: "%{count} Õ¶Õ¸Õ©Õ¥Ö€" + reports: + one: "%{count} Õ¦Õ¥Õ¯Õ¸ÕµÖ" + other: "%{count} Õ¦Õ¥Õ¯Õ¸ÕµÖ" + action_taken_by: Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬ Õ§ + are_you_sure: ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½ + assign_to_self: Ô»Õ¶Õ± ÕµÕ¡Õ¶Õ±Õ¶Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ¡Õ® + assigned: Õ†Õ·Õ¡Õ¶Õ¡Õ¯Õ¥Õ¬ Õ´Õ¸Õ¤Õ¥Ö€Õ¡Õ¿Õ¸Ö€ comment: none: ÕˆÕ¹ Õ´Õ« + created_at: Ô²Õ¸Õ²Õ¸Ö„Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® + mark_as_resolved: Õ†Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¬Õ¸Ö‚Õ®Õ¸Ö‚Õ¡Õ® + mark_as_unresolved: Õ†Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¹Õ¬Õ¸Ö‚Õ®Õ¸Ö‚Õ¡Õ® notes: create: Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ·Õ¸Ö‚Õ´ delete: Õ‹Õ¶Õ»Õ¥Õ¬ + reopen: ÕŽÕ¥Ö€Õ¡Õ¢Õ¡ÖÕ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¨ + report: 'Ô²Õ¸Õ²Õ¸Ö„ #%{id}' + reported_account: Ô²Õ¸Õ²Õ¸Ö„Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® Õ°Õ¡Õ·Õ«Ö‚ + reported_by: Ô²Õ¸Õ²Õ¸Ö„Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® Õ§ + resolved: Ô¼Õ¸Ö‚Õ®Õ¸Ö‚Õ¡Õ® status: Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + title: Ô²Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€ + unassign: Õ‰Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¥Õ¬ + unresolved: Õ‰Õ¬Õ¸Ö‚Õ®Õ¸Ö‚Õ¡Õ® + updated_at: Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¡Õ® settings: + contact_information: + email: Ô³Õ¸Ö€Õ®Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ¬ÖƒÕ¸Õ½Õ¿ + username: Ô¿Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ« Õ®Õ¡Õ®Õ¯Õ¡Õ¶Õ¸Ö‚Õ¶ + custom_css: + title: ÕÕ¥ÖƒÕ¡Õ¯Õ¡Õ¶ CSS + domain_blocks: + all: Ô²Õ¸Õ¬Õ¸Ö€Õ«Õ¶ + disabled: ÕˆÕ¹ Õ´Õ§Õ¯Õ«Õ¶ + title: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + hero: + title: Õ€Õ¥Ö€Õ¸Õ½Õ« ÕºÕ¡Õ¿Õ¯Õ¥Ö€ + profile_directory: + desc_html: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ«Õ¶ Õ¢Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¸Ö‚Õ¥Õ¬ + title: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶Õ¨ registrations: + closed_message: + desc_html: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Õ¡Ö€Õ¿Õ¡Ö„Õ«Õ¶ Õ§Õ»Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ ÖƒÕ¡Õ¯ Õ¥Õ¶Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¶Õ¡Õ¥Ö‚ HTML Õ©Õ§Õ£Õ¥Ö€ + title: Õ“Õ¡Õ¯ Õ£Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + deletion: + desc_html: Ô²Õ¸Õ¬Õ¸Ö€Õ«Õ¶ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ»Õ¶Õ»Õ¥Õ¬ Õ«Ö€Õ¥Õ¶Ö Õ°Õ¡Õ·Õ«Ö‚Õ¨ + title: Ô²Õ¡ÖÕ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ»Õ¶Õ»Õ¸Ö‚Õ´Õ¨ min_invite_role: disabled: ÕˆÕ¹ Õ¸Ö„ + title: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ°Ö€Õ¡Ö‚Õ§Ö€Õ¶Õ¥Ö€ + registrations_mode: + modes: + approved: Ô³Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´ + none: ÕˆÕ¹ Õ¸Ö„ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥Õ¬ + open: Ô²Õ¸Õ¬Õ¸Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥Õ¬ + title: Ô³Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¡ÕµÕ«Õ¶ Õ¼Õ¥ÕªÕ«Õ´ + show_staff_badge: + desc_html: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ« Õ¶Õ·Õ¡Õ¶Õ¨ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ§Õ»Õ¸Ö‚Õ´ + title: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ« Õ¶Õ·Õ¡Õ¶Õ¨ + site_description: + title: Ô¿Õ¡ÕµÖ„Õ« Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + site_short_description: + title: Ô¿Õ¡ÕµÖ„Õ« Õ°Õ¡Õ¯Õ«Ö€Õ³ Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + site_terms: + desc_html: Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ£Ö€Õ¥Õ¬ Ö„Õ¸ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨, Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ Õ¡ÕµÕ¬ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ HTML Õ©Õ¥Õ£Õ¥Ö€ + site_title: ÕÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¡Õ¶Õ¸Ö‚Õ¶ + thumbnail: + title: Õ€Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ¶Õ¯Õ¡Ö€Õ¨ + title: Ô¿Õ¡ÕµÖ„Õ« Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + trends: + title: Ô¹Ö€Õ¥Õ¶Õ¤Õ¡ÕµÕ«Õ¶ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€ + site_uploads: + delete: Õ‹Õ¶Õ»Õ¥Õ¬ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ¡Õ® Ö†Õ¡ÕµÕ¬Õ¨ + destroyed_msg: Ô¿Õ¡ÕµÖ„Õ« Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ´Õ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ»Õ¶Õ»Õ¸Ö‚Õ¥Ö statuses: + back_to_account: ÕŽÕ¥Ö€Õ¡Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ» batch: delete: Õ‹Õ¶Õ»Õ¥Õ¬ + nsfw_on: Õ†Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ§Õ½ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡Ö deleted: Õ‹Õ¶Õ»Õ¾Õ¡Õ® Õ§ + failed_to_execute: Ô¿Õ¡Õ¿Õ¡Ö€Õ¸Ö‚Õ´Õ¨ Õ±Õ¡ÕÕ¸Õ²Õ¸Ö‚Õ¥Ö + media: + title: Õ„Õ¥Õ¤Õ«Õ¡ + no_media: Õ„Õ¥Õ¤Õ«Õ¡ Õ¹Õ¯Õ¡Õµ + title: Õ•Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + with_media: Õ„Õ¥Õ¤Õ«Õ¡ÕµÕ« Õ°Õ¥Õ¿ tags: context: Õ€Õ¡Õ´Õ¡Õ¿Õ¥Ö„Õ½Õ¿ + last_active: ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¡Õ¯Õ¿Õ«Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + most_popular: Ô±Õ´Õ§Õ¶Õ¡ÕµÕ¡ÕµÕ¿Õ¶Õ« + most_recent: ÕŽÕ¥Ö€Õ»Õ«Õ¶ + name: ÕŠÕ«Õ¿Õ¡Õ¯ + review: ÕŽÕ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ + reviewed: ÕŽÕ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¸Ö‚Õ¡Õ® + title: ÕŠÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€ + trending_right_now: Ô±ÕµÕªÕ´ Õ©Ö€Õ¥Õ¶Õ¤Õ« Õ´Õ§Õ» Õ§ + unique_uses_today: "%{count} Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§ Õ¡ÕµÕ½Ö…Ö€" + unreviewed: ÕŽÕ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¸Ö‚Õ¡Õ® Õ¹Õ§ title: Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Õ¡Ö€ÖÕ«Õ¡ warning_presets: add_new: Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€Õ¨ delete: Õ‹Õ¶Õ»Õ¥Õ¬ + admin_mailer: + new_report: + subject: Õ†Õ¸Ö€ Õ¢Õ¸Õ²Õ¸Ö„ %{instance}Õ« Õ°Õ¡Õ´Õ¡Ö€(#%{id}) + appearance: + advanced_web_interface: ÕÕµÕ¸Ö‚Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ Õ«Õ¶Õ¿Õ¥Ö€Ö†Õ¥ÕµÕ½ + advanced_web_interface_hint: ÔµÕ©Õ§ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¤ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ¬Õ¡ÕµÕ¶Ö„Õ¨, Õ¡ÕºÕ¡ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¸Ö‚Õ¡Õ® Õ¾Õ¥Õ¢ Õ«Õ¶Õ¿Õ¥Ö€Ö†Õ¥ÕµÕ½Õ¸Õ¾ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€ Õ§ Õ§Õ¯Ö€Õ¡Õ¶Õ¨ Õ¢Õ¡ÕªÕ¡Õ¶Õ¥Õ¬ Õ½Õ«Ö‚Õ¶Õ¡Õ¯Õ¶Õ¥Ö€Õ«Õ Õ¦Õ¸Ö‚Õ£Õ¡Õ°Õ¥Õ¼ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¿Õ¡Ö€Õ¢Õ¥Ö€ Õ¿Õ«ÕºÕ« Õ«Õ¶Ö†Õ¸Ö€Õ´Õ¡ÖÕ«Õ¡Õ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¨, Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Ö†Õ¥Õ¤Õ¥Ö€Õ¡ÖÕ¾Õ¡Õ® Õ°Õ¸Õ½Ö„Õ¨, Ö‡ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ©Õ¾Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯ Õ¸Ö‚ Õ°Õ¥Õ·Õ©Õ¥Õ£Ö‰ + animations_and_accessibility: Ô±Õ¶Õ«Õ´Õ¡ÖÕ«Õ¡Õ¶Õ¥Ö€ Õ¥Ö‚ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + confirmation_dialogs: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¶Õ¥Ö€ + discovery: Ô²Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¸Ö‚Õ´ + localization: + body: Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¨ Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Õ¯Õ¡Õ´Õ¡Ö‚Õ¸Ö€Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰ + guide_link: https://crowdin.com/project/mastodon + guide_link_text: Ô±Õ»Õ¡Õ¯ÖÕ¥Õ¬ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨Ö‰ + sensitive_content: Ô¶Õ£Õ¡ÕµÕ¸Ö‚Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + application_mailer: + salutation: "%{name}," + view: Նայել․ + view_profile: Õ†Õ¡ÕµÕ¥Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨ + view_status: Õ†Õ¡ÕµÕ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ + applications: + invalid_url: ÕÖ€Õ¡Õ´Õ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® URL Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ§ + your_token: Õ”Õ¸ Õ´Õ¸Ö‚Õ¿Ö„Õ« Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶ auth: + apply_for_account: Õ€Ö€Õ¡Ö‚Õ§Ö€Õ« Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´ change_password: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ checkbox_agreement_html: ÔµÕ½ Õ°Õ¡Õ´Õ¡Õ±Õ¡ÕµÕ¶ Õ¥Õ´ <a href="%{rules_path}" target="_blank">Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¯Õ¡ÕµÕ¡Õ¶Ö„Õ¶Õ¥Ö€Õ«Õ¶</a> Ö‡ <a href="%{terms_path}" target="_blank">Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ«Õ¶</a> checkbox_agreement_without_rules_html: ÔµÕ½ Õ°Õ¡Õ´Õ¡Õ±Õ¡ÕµÕ¶ Õ¥Õ´ <a href="%{terms_path}" target="_blank">Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ«Õ¶</a> delete_account: Õ‹Õ¶Õ»Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨ + description: + prefix_sign_up: Ô³Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ«Õ›Ö€ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ¸Ö‚Õ´ Õ°Õ¥Õ¶Ö Õ¡ÕµÕ½Ö…Ö€ + forgot_password: Õ„Õ¸Õ¼Õ¡ÖÕ¥ÕžÕ¬ Õ¥Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ login: Õ„Õ¿Õ¶Õ¥Õ¬ logout: Ô´Õ¸Ö‚Ö€Õ½ Õ£Õ¡Õ¬ + migrate_account: ÕÕ¥Õ²Õ¡ÖƒÕ¸ÕÕ¸Ö‚Õ¥Õ¬ Õ¡ÕµÕ¬ Õ°Õ¡Õ·Õ«Ö‚ + or_log_in_with: Ô¿Õ¡Õ´ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Õ¾Õ providers: cas: CAS saml: SAML register: Ô³Ö€Õ¡Õ¶ÖÕ¾Õ¥Õ¬ + registration_closed: "%{instance}Õ¨ Õ¹Õ« Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¸Ö‚Õ´ Õ¶Õ¸Ö€ Õ¡Õ¶Õ¤Õ¡Õ´Õ¶Õ¥Ö€" + reset_password: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¡Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ security: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ + set_new_password: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¥Õ¬ Õ¶Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ setup: title: Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´ + status: + account_status: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + pending: Ô´Õ«Õ´Õ¸Ö‚Õ´Õ¨ ÕºÕ§Õ¿Ö„ Õ§ Ö„Õ¶Õ¶Õ¸Ö‚Õ« Õ´Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ« Õ¯Õ¸Õ²Õ´Õ«Ö, Õ«Õ¶Õ¹Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ´Õ« ÖƒÕ¸Ö„Ö€ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ ÕÕ¬Õ¥Õ¬Ö‰ Ô´Õ«Õ´Õ¸Ö‚Õ´Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´, Õ¯Õ¿Õ¥Õ²Õ¥Õ¯Õ¡ÖÕ¶Õ¥Õ¶Ö„ Õ¶Õ¡Õ´Õ¡Õ¯Õ¸Õ¾Ö‰ authorize_follow: follow: Õ€Õ¥Õ¿Ö‡Õ¥Õ¬ + following: Յաջողութի՜ւն։ Ô´Õ¸Ö‚ Õ¡ÕµÕªÕ´ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ ես․ + post_follow: + close: Ô¿Õ¡Õ´, Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ ÕºÕ¡Ö€Õ¦Õ¡ÕºÕ§Õ½ ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¡ÕµÕ½ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨Ö‰ + return: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ§Õ»Õ¨ + web: Ô±Õ¶ÖÕ¶Õ¥Õ¬ Õ¾Õ§Õ¢Õ«Õ¶ + title: Õ€Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ %{acct} + challenge: + confirm: Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬ + invalid_password: Ô±Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ®Õ¡Õ®Õ¯Õ¡Õ£Õ«Ö€ + prompt: Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ®Õ¡Õ®Õ¯Õ¡Õ£Õ«Ö€Õ¤ + crypto: + errors: + invalid_key: Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Ed25519 Õ¯Õ¡Õ´ Curve25519 Õ¢Õ¡Õ¶Õ¡Õ¬Õ« + invalid_signature: Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Ed25519 Õ¢Õ¡Õ¶Õ¡Õ¬Õ« + date: + formats: + default: "%b %d, %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: + about_x_hours: "%{count}Õª" + about_x_months: "%{count}Õ¡Õ´" + about_x_years: "%{count}Õ¿" + almost_x_years: "%{count}Õ¿" + half_a_minute: Õ€Õ§Õ¶Ö Õ°Õ«Õ´Õ¡ + less_than_x_minutes: "%{count}Õ¡" less_than_x_seconds: Õ€Õ¥Õ¶Ö Õ°Õ«Õ´Õ¡ over_x_years: "%{count}Õ¿" x_days: "%{count}Ö…" @@ -167,25 +667,53 @@ hy: x_months: "%{count}Õ¡" x_seconds: "%{count}Õ¾Ö€Õ¯" deletes: + challenge_not_passed: Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ½Õ¿Õ¸ÕµÕ£ Õ¹Õ§ + confirm_password: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ®Õ¡Õ®Õ¯Õ¡Õ£Õ«Ö€Õ¤ proceed: Õ‹Õ¶Õ»Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨ + success_msg: Õ€Õ¡Õ·Õ«Ö‚Õ¤ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ»Õ¶Õ»Õ¸Ö‚Õ¥Ö + directories: + directory: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶ + explore_mastodon: Ô²Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¥Õ¬ %{title} + domain_validator: + invalid_domain: Õ¡Õ¶Õ¾Õ¡Ö‚Õ§Ö€ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Õ¶Õ¸Ö‚Õ¶ errors: '400': The request you submitted was invalid or malformed. '403': You don't have permission to view this page. - '404': The page you are looking for isn't here. + '404': Ô·Õ»Õ¨, Õ¸Ö€Õ¨ ÖƒÕ¶Õ¿Ö€Õ¸Ö‚Õ´ Õ¥Õ½ Õ£Õ¸ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ«Ö‰ '406': This page is not available in the requested format. '410': The page you were looking for doesn't exist here anymore. '422': - '429': Too many requests - '500': + '429': Õ‰Õ¡ÖƒÕ¡Õ¦Õ¡Õ¶Ö Õ·Õ¡Õ¿ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ + '500': + title: Ô·Õ»Õ¨ Õ³Õ«Õ·Õ¿ Õ¹Õ§ '503': The page could not be served due to a temporary server failure. + existing_username_validator: + not_found: Õ¹ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ¥Ö Õ£Õ¿Õ¶Õ¥Õ¬ Õ¡ÕµÕ½ Õ®Õ¡Õ®Õ¯Õ¡Õ£Ö€Õ¸Õ¾ Õ¬Õ¸Õ¯Õ¡Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» + not_found_multiple: Õ¹ÕµÕ¡Õ»Õ¸Õ²Õ¸Ö‚Õ¥Ö Õ£Õ¿Õ¶Õ¥Õ¬ %{usernames} exports: archive_takeout: date: Ô±Õ´Õ½Õ¡Õ©Õ«Õ¾ download: Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Ö„ ÕÕ¥Ö€ Õ¡Ö€ÕÕ«Õ¾Õ¨ + request: ÕŠÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬ Ö„Õ¸ Õ¡Ö€Ö„Õ«Ö‚Õ¨ size: Õ‰Õ¡ÖƒÕ¨ + blocks: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ + bookmarks: Ô·Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€ csv: CSV + domain_blocks: ÕÕ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€ lists: Õ‘Õ¡Õ¶Õ¯Õ¥Ö€ + mutes: Ô¼Õ¼Õ¥ÖÖ€Õ¥Õ¬ Õ¥Õ½ + storage: Õ„Õ¥Õ¤Õ«Õ¡ ÕºÕ¡Õ°Õ¸Ö + featured_tags: + add_new: Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€Õ¨ filters: + contexts: + account: ÕŠÖ€Õ¸Ö†Õ«Õ¬Õ¶Õ¥Ö€ + home: ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„ + notifications: Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ + public: Õ€Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¥Ö€ + thread: Ô¶Ö€Õ¸ÕµÖÕ¶Õ¥Ö€ + edit: + title: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¦Õ¿Õ«Õ¹Õ¨ index: delete: Õ‹Õ¶Õ»Õ¥Õ¬ title: Õ–Õ«Õ¬Õ¿Ö€Õ¥Ö€ @@ -198,43 +726,130 @@ hy: trending_now: Ô±ÕµÕªÕ´ Õ¡Ö€Õ¤Õ«Õ¡Õ¯Õ¡Õ¶ generic: all: Ô²Õ¸Õ¬Õ¸Ö€Õ¨ + changes_saved_msg: Õ“Õ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ ÕµÕ¡Õ»Õ¸Õ² ÕºÕ¡Õ°Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ copy: ÕŠÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Õ¬ delete: Õ‹Õ¶Õ»Õ¥Õ¬ + order_by: Ô´Õ¡Õ½Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ Õ¨Õ½Õ¿ + save_changes: ÕŠÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ identity_proofs: active: Ô±Õ¯Õ¿Õ«Õ¾ + authorize: Ô±ÕµÕ¸, Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¶Õ¥Õ¬ + authorize_connection_prompt: Õ€Õ¡Ö‚Õ¡Õ½Õ¿Õ¡Õ£Ö€Õ§ÕžÕ¬ Õ¡ÕµÕ½ Õ®Õ¡Õ®Õ¯Õ¡Õ£Ö€Õ´Õ¡Õ¶ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨ + i_am_html: ÔµÕ½ %{username}Õ¶ Õ¥Õ´ %{service}Õ¸Ö‚Õ´Ö‰ + identity: Ô»Õ¶Ö„Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + inactive: ÕˆÕ¹ Õ¡Õ¯Õ¿Õ«Ö‚ + publicize_checkbox: Ô¹Õ©Õ¥Õ¬ սա․ + publicize_toot: 'Ô±ÕºÕ¡ÖÕ¸Ö‚Öուա՜ծ է․ ÔµÕ½%{username} Õ¥Õ´ %{service}ում․ %{url} ' + remove: Õ€Õ¡Õ·Õ¸Ö‚Õ«Ö Õ°Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¡ÕºÕ¡ÖÕ¸ÕµÖÕ¨ + removed: Ô±ÕºÕ¡ÖÕ¸ÕµÖÕ¨ Õ¢Õ¡Ö€Õ¥ÕµÕ¡Õ»Õ¸Õ² Õ°Õ¥Õ¼Õ¡ÖÕ¸Ö‚Õ¥Ö Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö + status: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + view_proof: Õ†Õ¡ÕµÕ¥Õ¬ Õ¡ÕºÕ¡ÖÕ¸ÕµÖÕ¨ imports: + errors: + over_rows_processing_limit: Õ¿Õ¸Õ²Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨ Õ¡Ö‚Õ¥Õ¬Õ«Õ¶ Õ§ Ö„Õ¡Õ¶ %{count}-Õ¨ modes: + merge: Õ„Õ«Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ overwrite: ÕŽÕ¥Ö€Õ¡Õ£Ö€Õ¥Õ¬ + types: + blocking: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯ + bookmarks: Ô·Õ»Õ¡Õ¶Õ«Õ·Õ¥Ö€ + domain_blocking: ÕÕ«Ö€Õ¸ÕµÕ©Õ« Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯ + following: Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯ upload: ÕŽÕ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ invites: + delete: Ô±ÕºÕ¡Õ¡Õ¯Õ¿Õ«Ö‚Õ¡ÖÕ¶Õ¥Õ¬ + expired: ÔºÕ¡Õ´Õ¯Õ¥Õ¿Õ¡Õ¶Ö expires_in: '1800': 30 Ö€Õ¸ÕºÕ¥ '21600': 6 ÕªÕ¡Õ´ - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day + '3600': 1 ÕªÕ¡Õ´ + '43200': 12 ÕªÕ¡Õ´ + '604800': 1 Õ·Õ¡Õ¢Õ¡Õ© + '86400': 1 Ö…Ö€ + expires_in_prompt: ÔµÖ€Õ¢Õ¥Ö„ + generate: Ô³Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ°Ö€Õ¡Ö‚Õ§Ö€Õ« ÕµÕ²Õ¸Ö‚Õ´ + max_uses: + one: "%{count} Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ´" + other: "%{count} Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ´" + max_uses_prompt: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´ Õ¹Õ¯Õ¡Õµ + table: + expires_at: ÕÕºÕ¡Õ¼Ö‚Õ¸Ö‚Õ´ Õ§ + uses: Ô¿Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ´ + title: Õ€Ö€Õ¡Ö‚Õ«Ö€Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö + media_attachments: + validations: + too_many: 4-Õ«Ö Õ¡Ö‚Õ¥Õ¬ Ö†Õ¡ÕµÕ¬ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¯ÖÕ¸Ö‚Õ¥Õ¬ + migrations: + acct: ÕÕ¥Õ²Õ¡ÖƒÕ¸ÕÕ¥Õ¬ Õ¤Õ¥ÕºÕ« + errors: + not_found: Õ¹Õ£Õ¿Õ¶Õ¸Ö‚Õ¥Ö + past_migrations: Õ†Õ¡ÕÕ¸Õ¤ Õ´Õ«Õ£Ö€Õ¡ÖÕ«Õ¡Õ¶Õ¥Ö€Õ¨ + proceed_with_move: ÕÕ¥Õ²Õ¡ÖƒÕ¸ÕÕ¥Õ¬ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ + redirecting_to: Õ”Õ¸ Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ¾Õ¥Ö€Õ¡Õ°Õ¡Õ½ÖÕ¥Õ¡Õ¸Ö€Õ¸Ö‚Õ´ Õ§ %{acct}-Õ«Õ¶ + warning: + followers: Ô±ÕµÕ½ Ö„Õ¡ÕµÕ¬Õ¸Õ¾ Ö„Õ¸ Õ¢Õ¸Õ¬Õ¸Ö€ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ¡ÕµÕ½ Õ°Õ¡Õ·Õ¸Ö‚Õ«Ö Õ¯Õ¨ Õ¿Õ¥Õ²Õ¡ÖƒÕ¸ÕÕ¥Õ½ Õ¤Õ§ÕºÕ« Õ¶Õ¸Ö€Õ¨ + moderation: + title: Õ„Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ notification_mailer: + digest: + title: ÔµÖ€Õ¢ Õ¢Õ¡ÖÕ¡Õ¯Õ¡Õµ Õ§Õ«Ö€... + favourite: + title: Õ†Õ¸Ö€ Õ°Õ¡Ö‚Õ¡Õ¶Õ¸Ö‚Õ´ + follow: + body: "%{name}Õ¨ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ§ Ö„Õ¥Õ¦!" + subject: "%{name}Õ¨ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ§ Ö„Õ¥Õ¦" + title: Õ†Õ¸Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€ + follow_request: + title: Õ†Õ¸Ö€ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖÕ¥Ö€ mention: action: ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬ + notifications: + other_settings: Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¡ÕµÕ¬ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ number: human: decimal_units: + format: "%n %u" units: billion: Õ„Õ¬Ö€ million: Õ„Õ¬Õ¶ quadrillion: Õ”Õ¬Ö€ thousand: Õ€Õ¡Õ¦ trillion: ÕÖ€Õ¬ + otp_authentication: + enable: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ + setup: Ô¿Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ pagination: newer: Ô±Õ¾Õ¥Õ¬Õ« Õ¶Õ¸Ö€ next: Õ€Õ¡Õ»Õ¸Ö€Õ¤ older: Ô±Õ¾Õ¥Õ¬Õ« Õ°Õ«Õ¶ prev: Õ†Õ¡ÕÕ¸Ö€Õ¤ truncate: "…" + polls: + errors: + duration_too_short: Õ·Õ¡Õ¿ Õ¯Õ¡Ö€Õ³ Õ§ preferences: other: Ô±ÕµÕ¬ + posting_defaults: Ô¿Õ¡Õ¶ÕÕ¡Õ¤Õ«Ö€ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + public_timelines: Õ€Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„ + relationships: + activity: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¡Õ¯Õ¿Õ«Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + dormant: Õ‰Õ£Ö…Ö€Õ®Õ¸Õ² + followers: Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€ + following: Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¥Õ½ + invited: Õ€Ö€Õ¡Ö‚Õ«Ö€Õ¸Ö‚Õ¡Õ® Õ§ + last_active: ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¡Õ¯Õ¿Õ«Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + most_recent: ÕŽÕ¥Ö€Õ»Õ«Õ¶ + moved: ÕÕ¥Õ²Õ¡ÖƒÕ¸ÕÕ¸Ö‚Õ¡Õ® + mutual: Õ“Õ¸ÕÕ¡Õ¤Õ¡Ö€Õ± + primary: Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ + relationship: Ô¿Õ¡Õº + remove_selected_domains: Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Õ¤Õ¸Õ´Õ¥ÕµÕ¶Õ¶Õ¥Ö€Õ«Ö + remove_selected_followers: Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ + status: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯ + scheduled_statuses: + too_soon: Õ†Õ¡ÕÕ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® Õ¡Õ´Õ½Õ¡Õ©Õ«Ö‚Õ¨ ÕºÕ§Õ¿Ö„ Õ§ Õ¬Õ«Õ¶Õ« Õ¡ÕºÕ¡Õ£Õ¡ÕµÕ¸Ö‚Õ´ sessions: + activity: ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ©Õ¸Ö‚Õ©Õ¨ browser: Ô´Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹ browsers: alipay: Alipay @@ -254,6 +869,7 @@ hy: safari: Safari uc_browser: UCBrowser weibo: Weibo + description: "%{browser}, %{platform}" ip: IP platforms: adobe_air: Adobe Air @@ -269,14 +885,151 @@ hy: windows_mobile: Windows Mobile windows_phone: Windows Phone revoke: Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ + title: ÕÕ¥Õ½Õ½Õ«Õ¡ settings: account: Õ€Õ¡Õ·Õ«Õ¾ + account_settings: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + appearance: ÕÕ¥Õ½Ö„ + back: ÔµÕ¿ Õ£Õ¶Õ¡Õ¬ Õ´Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶ + delete: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ»Õ¶Õ»Õ¸Ö‚Õ´ + development: Ô¾Ö€Õ¡Õ£Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´ edit_profile: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ ÕºÖ€Õ¸Ö†Õ«Õ¬Õ¨ + export: ÕÕ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¡Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¸Ö‚Õ´ + featured_tags: Ô¸Õ¶Õ¿Ö€Õ¸Ö‚Õ¡Õ® Õ°Õ§Õ·Õ©Õ¥Õ£Õ¥Ö€ + identity_proofs: Ô±Õ¶Õ±Õ« Õ¶Õ¸ÕµÕ¶Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ import: Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ import_and_export: Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¥Õ¬ Ö‡ Õ¡Ö€Õ¿Õ¡Õ°Õ¡Õ¶Õ¥Õ¬ + migrate: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ¿Õ¥Õ²Õ¡ÖƒÕ¸ÕÕ¸Ö‚Õ´ + notifications: Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ + preferences: Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + profile: Õ€Õ¡Õ·Õ«Ö‚ + relationships: Õ€Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Ö‡ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€ + two_factor_authentication: ÔµÖ€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´ + webauthn_authentication: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€ + statuses: + attached: + audio: + one: "%{count} Õ±Õ¡ÕµÕ¶Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶" + other: "%{count} Õ±Õ¡ÕµÕ¶Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶" + image: + one: "%{count} Õ¶Õ¯Õ¡Ö€" + other: "%{count} Õ¶Õ¯Õ¡Ö€" + video: + one: "%{count} Õ¾Õ«Õ¤Õ¥Õ¸" + other: "%{count} Õ¾Õ«Õ¤Õ¥Õ¸" + language_detection: Ô»Õ¶Ö„Õ¶Õ¸Ö‚Ö€Õ¸ÕµÕ¶ Õ³Õ¡Õ¶Õ¡Õ¹Õ¥Õ¬ Õ¬Õ¥Õ¦Õ¸Ö‚Õ¶ + open_in_web: Ô²Õ¡ÖÕ¥Õ¬ Õ¾Õ§Õ¢Õ¸Ö‚Õ´ + over_character_limit: "%{max} Õ¶Õ«Õ·Õ« Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¨ Õ£Õ¥Ö€Õ¡Õ¦Õ¡Õ¶ÖÕ¸Ö‚Õ¡Õ® Õ§" + poll: + total_people: + one: "%{count} Õ´Õ¡Ö€Õ¤" + other: "%{count} Õ´Õ¡Ö€Õ¤Õ«Õ¯" + total_votes: + one: "%{count} Õ±Õ¡ÕµÕ¶" + other: "%{count} Õ±Õ¡ÕµÕ¶Õ¥Ö€" + vote: Õ”Õ¸Ö‚Õ§Õ¡Ö€Õ¯Õ¥Õ¬ + show_more: Ô±Ö‚Õ¥Õ¬Õ«Õ¶ + show_thread: Ô²Õ¡ÖÕ¥Õ¬ Õ·Õ²Õ©Õ¡Õ¶ + sign_in_to_participate: Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ§Ö„Õ Õ¦Ö€Õ¸ÕµÖÕ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ + title: '%{name}: "%{quote}"' + visibilities: + private: Õ„Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ«Õ¶ + private_long: Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ´Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ + public: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ + public_long: ÕÕ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¢Õ¸Õ¬Õ¸Ö€Õ«Õ¶ + unlisted: Ô¾Õ¡Õ®Õ¸Ö‚Õ¯ + unlisted_long: ÕÕ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ¢Õ¸Õ¬Õ¸Ö€Õ«Õ¶, Õ¢Õ¡ÕµÖ Õ¹Õ« ÕµÕ¡ÕµÕ¿Õ¶Ö‚Õ¸Ö‚Õ´ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¥Ö€Õ¸Ö‚Õ´ stream_entries: + pinned: Ô±Õ´Ö€Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ©Õ¸Ö‚Õ© + reblogged: Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ¡Õ® sensitive_content: Ô¿Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + terms: + body_html: | + <h2>Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶</h2> + <p><strong>ÕˆÕ¹ ÕºÕ¡Õ·Õ¿Ö…Õ¶Õ¡Õ¯Õ¡Õ¶, Õ¸Õ¹ Õ«Ö€Õ¡Ö‚Õ¡Õ¯Õ¡Õ¶ Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶</strong></p> + <h3 id="collect">Ô»Õ¶Õ¹ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€ Õ¥Õ¶Ö„ Õ´Õ¥Õ¶Ö„ Õ°Õ¡Ö‚Õ¡Ö„Õ¸Ö‚Õ´</h3> + + <ul> + <li><em>Ô±Õ¼Õ¡Õ»Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¡Ö‚Õ¡Ö„Õ¾Õ¸Õ² Õ¿Ö‚Õ¡Õ¬Õ¶Õ¥Ö€</em>: ÔµÕ©Õ¥ Õ¤Õ¸Ö‚Ö„ Õ£Ö€Õ¡Õ¶ÖÕ¾Õ¥Ö„ Õ§Ö„ Õ¡ÕµÕ½ Õ½Õ¥Ö€Ö‚Õ¥Ö€Õ¸Ö‚Õ´, Õ±Õ¥Õ¦Õ¡Õ¶Õ«Ö Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Õ¬ Ö…Õ£Õ¿Õ¸Ö‚Õ¸Õ²Õ« Õ¡Õ¶Õ¸Ö‚Õ¶, Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§ Ö‡ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰ Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ¶Õ¡Ö‡ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Õ¬ Õ°Õ¡Õ¾Õ¥Õ¬ÕµÕ¡Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€, Õ«Õ¶Õ¹ÕºÕ«Õ½Õ«Ö„ Õ¥Õ¶ Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ¸Õ² Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ Õ¥Ö‚ Õ¯Õ¥Õ¶Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨, Õ¶Õ¡Ö‡ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ£Õ¬ÕÕ¡Õ¶Õ¯Õ¡Ö€ Ö‡ Õ¥Õ¿Õ¶Õ¡Õ¶Õ¡Õ¯Õ¡Ö€Ö‰ Õ•Õ£Õ¿Õ¸Ö‚Õ¸Õ²Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨, Õ¯Õ¥Õ¶Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨, Õ£Õ¬ÕÕ¡Õ¶Õ¯Õ¡Ö€Õ¨ Ö‡ Õ¥Õ¿Õ¶Õ¡Õ¶Õ¯Õ¡Ö€Õ¨ Õ°Õ¡Õ´Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ¥Õ¶ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Ö‰</li> + <li><em>Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¡ÕµÕ¬ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰ </em>: ÕÕ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¡Õ® Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¨ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÕ¸Ö‚Õ¡Õ® Õ§ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ¶Õ¸Ö€Õ¥Õ¶, Õ¶Õ¸ÕµÕ¶Õ¨ Õ³Õ·Õ´Õ¡Ö€Õ«Õ¿ Õ§ Õ¶Õ¡Ö‡ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÔµÖ€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ´ Õ¥Ö„ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶, Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ´Õ¡Õ¶ Õ¡Õ´Õ½Õ¡Õ©Õ«Ö‚Õ¨ Ö‡ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¨, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Ö‡ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ Õ¸Ö€Õ«Ö Õ¡ÕµÕ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§, ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Õ§Ö‰ Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡ Õ¯ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€, Õ«Õ¶Õ¹ÕºÕ«Õ½Õ«Ö„ Õ¥Õ¶ Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¿Õ¥Õ½Õ¡Õ¶Õ«Ö‚Õ©Õ¥Ö€Õ¨Ö‰ Õ€Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Ö‡ Õ®Õ¡Õ®Õ¸Ö‚Õ¯ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ¶Õ¸Ö€Õ¥Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶Ö‰ Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¸Ö‚Õ´ Õ¯ÖÕ¸Ö‚Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¶Õ¸Ö‚ÕµÕ¶ÕºÕ¥Õ½ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ¶Õ¸Ö€Õ¥Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ§Ö‰ ÕÕ¥Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶, Õ«Õ¶Õ¹Õ¨ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ¸Ö€Õ¸Õ· Õ¤Õ§ÕºÖ„Õ¥Ö€Õ¸Ö‚Õ´ Õ¤Ö€Õ¡Õ¶Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¬ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€ Ö‡ ÕºÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¶Õ¿Õ¥Õ²Ö‰ ÔµÖ€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ»Õ¶Õ»Õ¸Ö‚Õ´ Õ§Ö„ Õ±Õ¥Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ½Õ¡ Õ¶Õ¸Ö‚ÕµÕ¶ÕºÕ¥Õ½ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶Ö‰ Õ„Õ¥Õ¯ Õ¡ÕµÕ¬ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ°Õ¡Ö‚Õ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ´Õ«Õ·Õ¿ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ§Ö‰</li> + <li><em>Õ€Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¡Õ® Ö‡ Õ´Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨</em>: Ô²Õ¸Õ¬Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Ö‡ Õ´Õ·Õ¡Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Ö€Õ¡ÕµÖ‰ Õ„Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ´Õ«Õ¡ÕµÕ¶ Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Ö‡ Õ¡ÕµÕ¶ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«Õ¶ Õ¸Õ¾Ö„Õ¥Ö€ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ§Õ», Õ«Õ½Õ¯ Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¥ÖÕ¸Ö‚Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ´Õ«Õ¡ÕµÕ¶ Õ¤Ö€Õ¡Õ¶Õ¸Ö‚Õ´ Õ¶Õ·Õ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«Õ¶Ö‰ ÕˆÖ€Õ¸Õ· Õ¤Õ§ÕºÖ„Õ¥Ö€Õ¸Ö‚Õ´ Õ¤Õ¡ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ¡ÕµÕ¤ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¬ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€ Ö‡ ÕºÕ¡Õ¿Õ³Õ¥Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Õ¡ÕµÕ¶Õ¿Õ¥Õ²Ö‰ Õ„Õ¥Õ¶Ö„ Õ¢Õ¡Ö€Õ¥ÕÕ«Õ²Õ³ Õ»Õ¡Õ¶Ö„ Õ¥Õ¶ Õ£Õ¸Ö€Õ®Õ¡Õ¤Ö€Õ¸Ö‚Õ´ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ¡ÕµÕ¤ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ´Õ¸Ö‚Õ¿Ö„Õ¨ Õ´Õ«Õ¡ÕµÕ¶ Õ¬Õ«Õ¡Õ¦Ö…Ö€Õ¸Ö‚Õ¡Õ® Õ¡Õ¶Õ±Õ¡Õ¶Ö, Õ¢Õ¡ÕµÖ Õ¡ÕµÕ¬ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ±Õ¡ÕÕ¸Õ²Õ¥Õ¬ Õ¤Ö€Õ¡ Õ¯Õ¡Õ¿Õ¡Ö€Õ¸Ö‚Õ´Õ¨Ö‰ Ô±ÕµÕ¤ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾ Õ¯Õ¡Ö€Ö‡Õ¸Ö€ Õ§ Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¥Õ¬ Õ¡ÕµÕ¶ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ¨ Õ¸Ö€Õ«Õ¶ Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ¿Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ¶Ö‰ Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Ö Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ¶Õ¸Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ«Õ¶Ö„Õ¶Õ¸Ö‚Ö€Õ¸ÕµÕ¶ Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¬Õ¸Ö‚ Ö‡ Õ´Õ¥Ö€ÕªÕ¥Õ¬Õ¸Ö‚ Õ¨Õ¶Õ¿Ö€Õ¡Õ¶Ö„Õ¨Ö‰ <em>Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ ÕµÕ«Õ·Õ¥Õ¬, Õ¸Ö€ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¸Ö‚Õ¶ Ö‡ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ½Õ¿Õ¡ÖÕ¸Õ² Õ½Õ¥Ö€Õ¾Õ¥Ö€ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¤Õ«Õ¿Õ¥Õ¬ Õ¡ÕµÕ¤ Õ¿Õ¥Õ½Õ¡Õ¯ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</em>, Õ«Õ½Õ¯ Õ½Õ¿Õ¡ÖÕ¸Õ²Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ§Õ¯Ö€Õ¡Õ¶Õ¡Õ°Õ¡Õ¶Õ¥Õ¬, ÕºÕ¡Õ¿Õ³Õ§Õ¶Õ¥Õ¬ Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¥Ö€Õº Õ¾Õ¥Ö€Õ¡Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ¤Ö€Õ¡Õ¶Ö„Ö‰<em>Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ¸Õ¾ Õ´Õ« Õ¯Õ«Õ½Õ¾Õ¥Ö„ Õ¸Ö€Ö‡Õ§ Õ¾Õ¿Õ¡Õ¶Õ£Õ¡Ö‚Õ¸Ö€ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢Ö‰ </em></li> + <li><em>IP Õ°Õ¡Õ½ÖÕ§Õ¶Õ¥Ö€ Ö‡ Õ¡ÕµÕ¬ Õ´Õ¥Õ¿Õ¡Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€</em>: ÔµÖ€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ´Õ¸Ö‚Õ¿Ö„ Õ§Ö„ Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´, Õ´Õ¥Õ¶Ö„ ÕºÕ¡Õ°Õ¸Ö‚Õ´ Õ¥Õ¶ Õ±Õ¥Ö€ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ IP Õ°Õ¡Õ½ÖÕ§Õ¶, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Ö‡ Õ¦Õ¶Õ¶Õ¡Ö€Õ¯Õ«Õ¹Õ« Õ¿Õ¥Õ½Õ¡Õ¯Õ¨Ö‰ Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¥Õ¶Õ¸Ö‚Õ´ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ´Õ¸Ö‚Õ¿Ö„Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ½Õ¥Õ½Õ½Õ«Õ¡Õ¶Õ¥Ö€Õ« Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ´Õ¡Õ¶ Ö‡ Õ´Õ¡Ö€Õ´Õ¡Õ¶ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰ ÕŽÕ¥Ö€Õ»Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¡Õ® IP Õ°Õ¡Õ½ÖÕ§Õ¶ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¶Õ¹Ö‡ 12 Õ¡Õ´Õ«Õ½ ÕªÕ¡Õ´Õ¯Õ§Õ¿Õ¸Õ¾Ö‰ Õ„Õ¥Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶Ö„ Õ¶Õ¡Ö‡ ÕºÕ¡Õ°Õ¥Õ¬ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶Õ« Õ¶Õ«Õ·Ö„Õ¥Ö€Õ¨, Õ¸Ö€Õ¨ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ«Õ¶ Õ¡Ö€Õ¸Ö‚Õ¡Õ® Õ«Ö‚Ö€Õ¡Ö„Õ¡Õ¶Õ¹Õ«Ö‚Ö€ Õ°Õ¡Ö€ÖÕ´Õ¡Õ¶ IP Õ°Õ¡Õ½ÖÕ§Õ¶Ö‰</li> + </ul> + + <hr class="spacer" /> + + <h3 id="use"> Ô»Õ¶Õ¹ÕºÕ§Õ½ Õ¥Õ¶Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</h3> + + <p>Õ‘Õ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬, Õ¸Ö€Õ¨ Õ´Õ¥Õ¶Ö„ Õ°Õ¡Ö‚Õ¡Ö„Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ±Õ¥Õ¦Õ¶Õ«Ö Õ¯Õ¡Ö€Õ¸Õ² Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¡ÕµÕ¬ Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¸Õ¾Õ</p> + + <ul> + <li>Õ„Õ¡Õ¿Õ¸Ö‚ÖÕ¥Õ¬Õ¸Ö‚ Õ„Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ« Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¡Õ¼Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨Ö‰ Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ ÖƒÕ¸ÕÕ£Õ¸Ö€Õ®Õ¡Õ¯ÖÕ¥Õ¬ Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ°Õ¥Õ¿ Ö‡ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Õ±Õ¥Ö€ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ´Õ«Õ¡ÕµÕ¶ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚Ö ÕµÕ¥Õ¿Õ¸ÕµÖ‰ Õ•Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¤Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¶Ö€Õ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Õ¯ÖÕ¸Ö‚Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö‰</li> + <li>Õ†ÕºÕ¡Õ½Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ´Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ«Õ¶Ö‰ Õ•Ö€Õ«Õ¶Õ¡Õ¯Õ Õ°Õ¡Õ´Õ¥Õ´Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ±Õ¥Ö€ IP Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¡ÕµÕ¬ Õ¡Ö€Õ¤Õ¥Õ¶ ÕµÕ¡ÕµÕ¿Õ¶Õ« Õ°Õ¡Õ½ÖÕ§Õ« Õ°Õ¥Õ¿Õ Õ¢Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¥Õ¬Õ¸Ö‚ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ«Ö ÕÕ¸Ö‚Õ½Õ¡ÖƒÕ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ ÕÕ¡ÕÕ¿Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¤Õ¥ÕºÖ„Õ¥Ö€Õ¨ Ö‰</li> + <li>ÕÕ¥Ö€ Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¡Õ® Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¥Õ¬ Õ±Õ¥Õ¦ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¥Õ¬Õ¸Ö‚, Õ¡ÕµÕ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶ÖÕ Õ±Õ¥Ö€ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ°Õ¥Õ¿ ÖƒÕ¸ÕÕ£Õ¸Ö€Õ®Õ¡Õ¯ÖÕ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ¡Õ´ Õ±Õ¥Õ¦ Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¡Õ® Õ¶Õ¡Õ´Õ¡Õ¯Õ« Õ´Õ¡Õ½Õ«Õ¶ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¥Õ¬Õ¸Ö‚, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Ö‡ Õ°Õ¡ÕµÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Õ¶ Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ ÕµÕ¡ÕµÕ¿Õ¥Ö€Õ«Õ¶ Õ¸Ö‚ Õ°Õ¡Ö€ÖÕ¥Ö€Õ«Õ¶ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰</li> + </ul> + + <hr class="spacer" /> + + <h3 id="protect"> Ô»Õ¶Õ¹ÕºÕ¥Õ½ Õ¥Õ¶Ö„ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶</h3> + + <p>Õ„Õ¥Õ¶Ö„ Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¿Õ¡Ö€Õ¢Õ¥Ö€ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ´Õ«Õ»Õ¸ÖÕ¶Õ¥Ö€Õ« ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨, Õ¥Ö€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¸Ö‚Õ´, Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Õ¤Õ«Õ¿Õ¸Ö‚Õ´ Õ§Õ£ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨Ö‰ Ô» Õ©Õ«Ö‚Õ½ Õ´Õ¶Õ¡ÖÕ¡Õ® Õ¢Õ¡Õ¶Õ¥Ö€Õ«, Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ« Õ½Õ¥Õ½Õ½Õ«Õ¡Õ¶, Õ«Õ¶Õ¹ÕºÕ§Õ½ Õ¶Õ¡Ö‡ Õ±Õ¥Ö€ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Ö‡ API Õ´Õ«Õ»Ö‡ Õ¿Ö€Õ¡Ö†Õ«Õ¯Õ¨ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ SSL-Õ¸Õ¾, Õ«Õ½Õ¯ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÕºÕ¡Õ¿Õ¡Õ°Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¾Õ¡Õ® Õ§ Õ´Õ«Õ¡Õ¯Õ¸Õ²Õ´Õ¡Õ¶Õ« Õ¡Õ¬Õ£Õ¸Ö€Õ«Õ©Õ´Õ¸Õ¾Ö‰ Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ¥Ö€Õ¯Õ¡Õ½Õ¿Õ«Õ³Õ¡Õ¶ Õ«Õ¶Ö„Õ¶Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´Õ¨, Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¸Ö‚Õ¿Ö„Õ¨ Õ¡Ö‚Õ¥Õ¬Õ« ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¸Ö‚Õ¡Õ® Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰</p> + + <hr class="spacer" /> + + <h3 id="data-retention">ÕÕ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ´Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨</h3> + + <p>Õ„Õ¥Õ¶Ö„ Õ£Õ¸Ö€Õ®Õ¡Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¢Õ¡Ö€Õ¥ÕÕ«Õ²Õ³ Õ»Õ¡Õ¶Ö„Õ</p> + + <ul> + <li>ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶Õ« Õ¶Õ«Õ·Ö„Õ¥Ö€Õ¨Õ Õ¡ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ«Õ¶ Õ¡Ö€Õ¸Ö‚Õ¡Õ® Õ¢Õ¸Õ¬Õ¸Ö€ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« IP Õ°Õ¡Õ½ÖÕ§Õ¶Õ¥Ö€Õ¸Õ¾, Õ¡ÕµÕ¶Ö„Õ¡Õ¶Õ¸Õ¾ Õ¸Ö€Ö„Õ¡Õ¶Õ¸Õ¾ Õ¶Õ´Õ¡Õ¶ Õ¶Õ«Õ·Ö„Õ¥Ö€Õ¨ ÕºÕ¡Õ°Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶, Õ¸Õ¹ Õ¡Ö‚Õ¥Õ¬ Ö„Õ¡Õ¶ 90 Ö…Ö€ ÕªÕ¡Õ´Õ¯Õ§Õ¿Õ¸Õ¾Ö‰</li> + <li>ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ« Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¥Õ¿ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ¡Õ® IP Õ°Õ¡Õ½ÖÕ§Õ¶Õ¥Ö€Õ¨, Õ¸Õ¹ Õ¡Ö‚Õ¥Õ¬ Ö„Õ¡Õ¶ 12 Õ¡Õ´Õ«Õ½ ÕªÕ¡Õ´Õ¯Õ§Õ¿Õ¸Õ¾Ö‰</li> + </ul> + + <p>Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡ÕµÖ Õ¶Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¸Ö‚ Õ±Õ¥Ö€ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÕºÕ¡Õ¿Õ³Õ§Õ¶Õ Õ¶Õ¥Ö€Õ¡Õ¼Õ¥Õ¡Õ¬ Õ±Õ¥Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ´Õ¥Õ¤Õ«Õ¡ Õ¯ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ£Õ¬ÕÕ¡Õ¶Õ¯Õ¡Ö€Õ¨ Ö‡ Õ¥Õ¿Õ¶Õ¡Õ¶Õ¯Õ¡Ö€Õ¨Ö‰</p> + + <p>Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ¨Õ¶Õ¤Õ´Õ«Õ·Õ¿ Õ»Õ¶Õ»Õ¥Õ¬ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¨ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯</p> + + <hr class="spacer"/> + + <h3 id="cookies">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ§Ö„ Õ¡Ö€Õ¤ÕµÕ¸ÕžÖ„ Õ©ÕÕ¸Ö‚Õ¯Õ¶Õ¥Ö€</h3> + + <p>Ô±ÕµÕ¸Ö‰ Ô¹ÕÕ¸Ö‚Õ¯Õ¶Õ¥Ö€Õ¨ ÖƒÕ¸Ö„Ö€ Ö†Õ¡ÕµÕ¬Õ¥Ö€ Õ¥Õ¶ Õ¸Ö€Õ¨ Õ¯Õ¡ÕµÖ„Õ¨ Õ¯Õ¡Õ´ Õ¶Ö€Õ¡Õ¶ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ´Õ¡Õ¿Õ¸Ö‚ÖÕ¸Õ²Õ¨ ÖƒÕ¸ÕÕ¡Õ¶ÖÕ¸Ö‚Õ´ Õ§ Õ±Õ¥Ö€ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¹Õ« Õ¯Õ¸Õ·Õ¿ Õ½Õ¯Õ¡Ö‚Õ¡Õ¼Õ¡Õ¯Õ«Õ¶ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¹Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ (Õ±Õ¥Ö€ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶)Ö‰ Ô¹ÕÕ¸Ö‚Õ¯Õ¶Õ¥Ö€Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶ Õ³Õ¡Õ¶Õ¡Õ¹Õ¥Õ¬Õ¸Ö‚ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¨, Ö‡ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¡Õ® Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´Õ Õ¶Õ¸ÕµÕ¶Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ¡ÕµÕ¶ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¥Õ¿Ö‰ + + Õ„Õ¥Õ¶Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ©ÕÕ¸Ö‚Õ¯Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¯Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Ö‡ ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ±Õ¥Ö€ Õ¶Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ¨ Õ¡ÕºÕ¡Õ£Õ¡Õµ Õ¡ÕµÖÕ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰</p> + + <hr class="spacer" /> + + <h3 id="disclose"> Ô²Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¸Ö‚Õ´ Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ¥Ö€Õ«Õ¶ </h3> + + <p>Õ„Õ¥Õ¶Ö„ Õ¹Õ¥Õ¶Ö„ Õ¾Õ¡Õ³Õ¡Õ¼Õ¸Ö‚Õ´, ÖƒÕ¸ÕÕ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´, Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ Õ¯Õ¥Ö€Õº ÖƒÕ¸ÕÕ¡Õ¶ÖÕ¸Ö‚Õ´ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¶Õ¸ÕµÕ¶Õ¡ÖÕ¶Õ¸Õ² Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ¥Ö€Õ«Õ¶Ö‰ ÕÕ¡ Õ¹Õ« Õ¶Õ¥Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¾Õ½Õ¿Õ¡Õ°Õ¥Õ¬Õ« Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ¥Ö€Õ«Õ¶ Õ¸Ö€Õ¸Õ¶Ö„ Ö…Õ£Õ¿Õ¶Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¯Õ¡ÕµÖ„Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ´Õ¡Õ¶, Õ´Õ¥Ö€ Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¶Õ¥Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ®Õ¡Õ¾Õ¡Õ¬Õ´Õ¡Õ¶, Õ¯Õ¡Õ´ Õ±Õ¥Õ¦ Õ®Õ¡Õ¼Õ¡ÕµÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€, Õ¡ÕµÕ¶Ö„Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¸Ö€Ö„Õ¡Õ¶ Õ¡ÕµÕ¤ Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ¥Ö€Õ¨ Õ°Õ¡Õ´Õ¡Õ±Õ¡ÕµÕ¶ Õ¥Õ¶ Õ£Õ¡Õ²Õ¿Õ¶Õ« ÕºÕ¡Õ°Õ¥Õ¬ Õ¡ÕµÕ¤ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Õ„Õ¥Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶Ö„ Õ¶Õ¡Ö‡ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ¶Õ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¸Ö‚Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¥Ö€Õ¢ Õ°Õ¡Ö‚Õ¡Õ¿Õ¡ÖÕ¡Õ® Õ¥Õ¶Ö„ Õ¸Ö€ Õ¤Ö€Õ¡ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Ö…Ö€Õ§Õ¶Ö„Õ« ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¶Õ¥Ö€Õ« Õ¯Õ¡Õ¿Õ¡Ö€Õ´Õ¡Õ¶, Õ¯Õ¡Õ´ Õ¯Õ¡ÕµÖ„Õ« Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ«Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€, Õ¯Õ¡Õ´ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ´Õ¥Ö€ Õ¯Õ¡Õ´ Õ¡ÕµÕ¬Õ¸Ö Õ«Ö€Õ¡Ö‚Õ¸Ö‚Õ¶Ö„Õ¶Õ¥Ö€Õ¨, Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¯Õ¡Õ´ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰</p> + + <p>ÕÕ¥Ö€ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ¥Õ¬ ÖÕ¡Õ¶ÖÕ« Õ´Õ«Ö‚Õ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰ ÕÕ¥Ö€ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Ö‡ Õ´Õ«Õ¡ÕµÕ¶ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¶ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¶ Õ¸Ö€Õ¿Õ¥Õ² Õ£Ö€Õ¡Õ¶ÖÕ¡Õ® Õ¥Õ¶ Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ¨, Ö‡ Õ°Õ¡Õ½ÖÕ¥Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ°Õ¡Õ½ÖÕ§Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ« Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¶, Õ¡ÕµÕ¶ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´ Õ¥Ö€Õ¢ Õ¡ÕµÕ¤ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ°Õ¡Õ½ÖÕ§Õ¡Õ¿Õ§Ö€Õ¥Ö€Õ¨ Õ£Õ¿Õ¶Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ«Ö Õ¿Õ¡Ö€Õ¢Õ¥Ö€ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Ö€Õ¡ÕµÖ‰</p> + + <p>ÔµÖ€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ©Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¸Ö‚Õ´ Õ§Ö„ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ«Ö‚Õ¨, Õ¯Õ¡ÕÕ¸Ö‚Õ¡Õ® Õ©Õ¸Ö‚ÕµÕ¬Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ·Ö€Õ»Õ¡Õ¶Õ¡Õ¯Õ«Ö, Õ¡ÕµÕ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ´Õ¸Ö‚Õ¿Ö„ Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ«Ö‚ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¡Õ¶Õ¨, Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Õ²Õ¶Õ¥Ö€Õ« ÖÕ¡Õ¶Õ¯Õ«Õ¶, Õ±Õ¥Ö€ Õ°Õ¥Õ¿Ö‡Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Ö ÖÕ¡Õ¶Õ¯Õ«Õ¶, ÖÕ¡Õ¶Õ¯Õ¥Ö€Õ«Õ¶, Õ±Õ¥Ö€ Õ¢Õ¸Õ¬Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Õ¶, Ö‡ Õ±Õ¥Ö€ Õ°Õ¡Ö‚Õ¡Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Õ¶Ö‰ Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ¨ Õ¥Ö€Õ¢Õ¥Ö„ Õ¹Õ¥Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ´Õ¸Ö‚Õ¿Ö„ Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ°Õ¡Õ½ÖÕ§Õ«Õ¶ Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ«Õ¶Ö‰</p> + + <hr class="spacer" /> + + <h3 id="children">Ô¿Õ¡ÕµÖ„Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´Õ¨ Õ¥Ö€Õ¥ÕÕ¡Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö</h3> + + <p>ÔµÕ©Õ§ Õ¡ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ£Õ¿Õ¶Õ¸Ö‚Õ´ Õ§ ÔµÕ„-Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ ÔµÕÔ³-Õ¸Ö‚Õ´. Õ„Õ¥Ö€ Õ¯Õ¡ÕµÖ„Õ¨, Õ¡Ö€Õ¿Õ¡Õ¤Ö€Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ¨ Ö‡ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¶Õ¡ÕÕ¡Õ¿Õ¥Õ½Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ 16 Õ¿Õ¡Ö€Õ«Õ¶ Õ¬Ö€Õ¡ÖÕ¡Õ® Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€: ÔµÕ©Õ§ Õ±Õ¥Ö€ 16 Õ¿Õ¡Ö€Õ¥Õ¯Õ¡Õ¶Õ¨ Õ¹Õ« Õ¬Ö€Õ¡ÖÕ¥Õ¬, Õ¡ÕºÕ¡ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬Õ¸Õ¾ GDPR (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">General Data Protection Regulation</a>) ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¶Õ¥Ö€Õ«Õ¶Õ Õ´Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ§Ö„ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨Ö‰</p> + + <p>ÔµÕ©Õ§ Õ¡ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ£Õ¿Õ¶Ö‚Õ¸Ö‚Õ´ Õ§ Ô±Õ„Õ†-Õ¸Ö‚Õ´. Õ„Õ¥Ö€ Õ¯Õ¡ÕµÖ„Õ¨, Õ¡Ö€Õ¿Õ¡Õ¤Ö€Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ¨ Ö‡ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¶Õ¡ÕÕ¡Õ¿Õ¥Õ½Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ 13 Õ¿Õ¡Ö€Õ«Õ¶ Õ¬Ö€Õ¡ÖÕ¡Õ® Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€: ÔµÕ©Õ§ Õ±Õ¥Ö€ 16 Õ¿Õ¡Ö€Õ¥Õ¯Õ¡Õ¶Õ¨ Õ¹Õ« Õ¬Ö€Õ¡ÖÕ¥Õ¬, Õ¡ÕºÕ¡ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬Õ¸Õ¾ COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Children's Online Privacy Protection Act</a>) ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¶Õ¥Ö€Õ«Õ¶Õ Õ´Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ§Ö„ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨Ö‰ + + <p>Ô±ÕµÕ¬ Õ¥Ö€Õ¯Ö€Õ¶Õ¥Ö€Õ« Õ«Ö€Õ¡Ö‚Õ¡Õ½Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ·Ö€Õ»Õ¡Õ¶Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Ö…Ö€Õ§Õ¶Ö„Õ« ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¸Ö‚Õ¥Õ¬Ö‰</p> + + <hr class="spacer" /> + + <h3 id="changes">Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</h3> + + <p>ÔµÕ©Õ§ Õ´Õ¥Õ¶Ö„ Õ¸Ö€Õ¸Õ·Õ¥Õ¶Ö„ ÖƒÕ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ´Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨, Õ¡ÕºÕ¡ Õ¡ÕµÕ¤ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¥Õ¶Ö„ Õ¡ÕµÕ½ Õ§Õ»Õ¸Ö‚Õ´Ö‰ </p> + + <p>Ô±ÕµÕ½ ÖƒÕ¡Õ½Õ¿Õ¡Õ©Õ¸Ö‚Õ²Õ©Õ¨ Õ¬Õ«Õ¡Õ¦Ö…Ö€Õ¸Ö‚Õ¡Õ® Õ§ CC-BY-SA Õ¬Õ«ÖÕ¥Õ¶Õ¦Õ«Õ¡ÕµÕ¸Õ¾Ö‰ ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ´Õ¨Õ 7-Õ¨ Õ´Õ¡Ö€Õ¿Õ« 2018</p> + + <p>Õ“Õ¸ÕÕ¡Õ¼Õ¶Õ¸Ö‚Õ¡Õ® Õ§ <a href="https://github.com/discourse/discourse">Discourse-Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ«Ö</a>.</p> + + <p><strong>ÕˆÕ¹ ÕºÕ¡Õ·Õ¿Ö…Õ¶Õ¡Õ¯Õ¡Õ¶, Õ¸Õ¹ Õ«Ö€Õ¡Ö‚Õ¡Õ¯Õ¡Õ¶ Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¸Ö‚Õ©Õ«Ö‚Õ¶</strong></p> themes: + contrast: Mastodon (Õ¢Õ¡Ö€Õ±Ö€ Õ¯Õ¸Õ¶Õ¿Ö€Õ¡Õ½Õ¿Õ¸Õ¾) default: Mastodon (Õ„Õ¸Ö‚Õ£) mastodon-light: Mastodon (Ô¼Õ¸Ö‚Õ½Õ¡Õ¾Õ¸Ö€) time: @@ -284,14 +1037,50 @@ hy: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: + add: Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ disable: Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ - enable: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ - setup: Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ + disabled_success: ÔµÖ€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ¡Õ¶Õ»Õ¸Ö‚Õ¡Õ® Õ§ + edit: Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ + enabled: ÔµÖ€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§ + enabled_success: ÔµÖ€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ§ + generate_recovery_codes: ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€ + lost_recovery_codes: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ Õ°Õ¥Õ¼Õ¡ÕÖ…Õ½Õ« Õ¯Õ¸Ö€Õ½Õ¿Õ« Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´Ö‰ ÔµÕ©Õ§ Õ¯Õ¸Ö€ÖÖ€Õ¥Õ¬ Õ¥Õ½ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨, Õ¡ÕµÕ½Õ¿Õ¥Õ² Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€Õ¥Ö€Õ¨Ö‰ Õ†Õ¡ÕÕ¯Õ«Õ¶ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨ Õ¯Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¶Ö‰ + methods: ÔµÖ€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¶Õ¥Ö€ + otp: Õ†Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® + recovery_codes: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€ + recovery_codes_regenerated: ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¥Ö€Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ½Õ¿Õ¥Õ²Õ®Õ¸Ö‚Õ¥Õ¬ Õ¥Õ¶ + webauthn: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€ user_mailer: + sign_in_token: + title: Õ„Õ¸Ö‚Õ¿Ö„Õ« ÖƒÕ¸Ö€Õ± warning: + get_in_touch: Ô¿Õ¡Ö€Õ¸Õ² Õ§Ö„ Õ¯Õ¡ÕºÕ¸Ö‚Õ¥Õ¬ %{instance} Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¦Õ´Õ« Õ°Õ¥Õ¿ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬Õ¸Õ¾ Õ¡ÕµÕ½ Õ¶Õ¡Õ´Õ¡Õ¯Õ«Õ¶Ö‰ + statuses: Õ„Õ¡Õ½Õ¶Õ¡Ö‚Õ¸Ö€Õ¡ÕºÕ§Õ½, Õ´Õ«Õ¡ÕµÕ¶Õ title: none: Ô¶Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´ + sensitive: Õ„Õ¥Õ¤Õ«Õ¡Ö†Õ¡ÕµÕ¬Õ¨ ÕºÕ«Õ¿Õ¡Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§ Õ¸Ö€ÕºÕ§Õ½ Õ¦Õ£Õ¡ÕµÕ¸Ö‚Õ¶Ö‰ + suspend: Õ€Õ¡Õ·Õ«Ö‚Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ§ welcome: + edit_profile_action: Ô¿Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + final_action: ÕÕ¯Õ½Õ¥Õ¬ Õ©Õ©Õ¥Õ¬ + final_step: 'ÕÕ¯Õ½Õ«Ö€ Õ©Õ©Õ¥Õ›Õ¬Ö‰ Ô±Õ¶Õ£Õ¡Õ´ Õ¡Õ¼Õ¡Õ¶Ö Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ« Ö„Õ¸ Õ°Õ¡Õ¶Ö€Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¥Ö€Ö‡Õ¡Õ¬ Õ¸Ö‚Ö€Õ«Õ·Õ¶Õ¥Ö€Õ« Õ´Ö…Õ¿, Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Õ°Õ¥Õ·Õ©Õ¥Õ£Õ¥Ö€Õ¸Ö‚Õ´Ö‰ Ô¹Õ§ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¡Õ½, Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ ÕµÕ¡ÕµÕ¿Õ¶Õ¥Õ¬ Ö„Õ¸ Õ´Õ¡Õ½Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Õ¾ #Õ¥Õ½Õ¶Õ¸Ö€Õ¥Õ¯Õ¥Õ´ Õ°Õ¥Õ·Õ©Õ¥Õ£Õ¨Ö‰' + review_preferences_action: Õ“Õ¸ÖƒÕ¸ÕÕ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + subject: Ô²Õ¡Ö€Õ« Õ£Õ¡Õ¬Õ¸Ö‚Õ½Õ¿ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶ + tip_federated_timeline: Ô´Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ Õ¥Ö€Ö‡Õ¸Ö‚Õ´ Õ§ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ« ÖÕ¡Õ¶ÖÕ¨Ö‰ Ô²Õ¡ÕµÖ Õ¡ÕµÕ¶ Õ¶Õ¥Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¶ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«Õ¶ Õ¸Ö€Õ¸Õ¶Ö Õ¢Õ¡ÕªÕ¡Õ¶Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ¥Õ¶ Õ±Õ¥Ö€ Õ°Õ¡Ö€Ö‡Õ¡Õ¶Õ¶Õ¥Ö€, Õ¡ÕµÕ¤ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾ Õ¡ÕµÕ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ¸Õ¹ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¡Õ¯Õ¡Õ¶Ö‰ + tip_following: Ô´Õ¸Ö‚ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ§Õ½ Ö„Õ¸ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ¡Õ¤Õ´Õ«Õ¶(Õ¶Õ¥Ö€)Õ«Õ¶ Õ¬Õ¼Õ¥Õ¬Õ¡ÕµÕ¶Ö‰ Ô±ÕµÕ¬ Õ°Õ¥Õ¿Õ¡Ö„Ö€Ö„Õ«Ö€ Õ¡Õ¶Õ±Õ¡Õ¶Ö Õ£Õ¿Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Õ Õ©Õ¥Ö€Õ©Õ«Ö€ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡Õ¶ Ö‡ Õ¤Õ¡Õ·Õ¶Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¥Ö€Õ¨Ö‰ + tip_local_timeline: ÕÕ¥Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ Õ¥Ö€Ö‡Õ¸Ö‚Õ´ Õ¥Õ¶ %{instance} Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Õ†Ö€Õ¡Õ¶Ö„ Ö„Õ¸ Õ°Õ¡Õ¶Õ£Õ¸ÕµÖÕ« Õ°Õ¡Ö€Ö‡Õ¡Õ¶Õ¶Õ¥Ö€Õ¶ Õ¥Õ¶Ö‰ tips: Õ€Õ¸Ö‚Õ·Õ¸Ö‚Õ´Õ¶Õ¥Ö€ + users: + blocked_email_provider: ÕÕ¸Ö‚ÕµÕ¶ Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¸Õ²Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¾Õ¡Õ® Õ§ + invalid_email: Էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¡Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ§ + invalid_email_mx: Ô±ÕµÕ½ Õ°Õ¡Õ½ÖÕ§Õ¶ Õ¯Õ¡Ö€Õ®Õ¥Õ½ Õ©Õ§ Õ£Õ¸ÕµÕ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ« + invalid_otp_token: Ô±Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ 2F Õ¯Õ¸Õ¤ + invalid_sign_in_token: Ô±Õ¶Õ¾Õ¡Ö‚Õ¥Ö€ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¯Õ¸Õ¤ + signed_in_as: Õ„Õ¸Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬ որպէս․ verification: + explanation_html: ÕŠÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ« ÕµÕ²Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¯Õ¡Ö€Õ¥Õ¬Õ« Õ§ Õ¾Õ¡Ö‚Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬Ö‰ Ô±Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Õ¸Ö€ ÕµÕ²Õ¸Ö‚Õ¡Õ® Õ¯Õ¡ÕµÖ„Õ¨ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ« ÕµÕ¥Õ¿Õ¡Õ¤Õ¡Ö€Õ± ÕµÕ²Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ´Õ¡Õ½Õ¿Õ¡Õ¤Õ¸Õ¶Õ« Õ§Õ»Õ«Õ¶, Õ¸Ö€Õ¨ <strong>ÕºÕ§Õ¿Ö„ Õ§</strong> Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡Õµ <code>rel="me"</code> Õ¶Õ«Õ·Ö„Õ¨Ö‰ Õ…Õ²Õ´Õ¡Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¯Õ¡Ö€Ö‡Õ¸Ö€ Õ¹Õ§Ö‰ Õ•Ö€Õ«Õ¶Õ¡Õ¯Õ verification: ÕÕ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´ + webauthn_credentials: + delete: Õ‹Õ¶Õ»Õ¥Õ¬ + not_enabled: WebAuthn-Õ¨ Õ¤Õ¥Õ¼ Õ´Õ«Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ¹Õ§ + registered_on: Ô³Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥Õ¬ Õ§ %{date} diff --git a/config/locales/id.yml b/config/locales/id.yml index ad18cefb77e8f8484721306929da531235a3b82e..bf63f62a48a4b54d823e574615a25c0e13bba719 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1,7 +1,7 @@ --- id: about: - about_hashtag_html: Ini adalah toot public yang ditandai dengan <strong>#%{hashtag}</strong>. Anda bisa berinteraksi dengan mereka jika anda memiliki akun dimanapun di fediverse. + about_hashtag_html: Ini adalah toot publik yang ditandai dengan <strong>#%{hashtag}</strong>. Anda bisa berinteraksi dengan mereka jika anda memiliki akun dimanapun di fediverse. about_mastodon_html: Mastodon adalah sebuah jejaring sosial <em>terbuka, open-source</em. Sebuah alternatif <em>desentralisasi</em> dari platform komersial, menjauhkan anda resiko dari sebuah perusahaan yang memonopoli komunikasi anda. Pilih server yang anda percayai — apapun yang anda pilih, anda tetap dapat berinteraksi dengan semua orang. Semua orang dapat menjalankan server Mastodon sendiri dan berpartisipasi dalam <em>jejaring sosial</em> dengan mudah. about_this: Tentang server ini active_count_after: aktif @@ -21,7 +21,9 @@ id: federation_hint_html: Dengan akun di %{instance} Anda dapat mengikuti orang di server Mastodon mana pun dan di luarnya. get_apps: Coba aplikasi mobile hosted_on: Mastodon dihosting di %{domain} - instance_actor_flash: Akun ini adalah aktor virtual yang dipakai untuk merepresentasikan server, bukan pengguna individu. Ini dipakai untuk tujuan federasi dan jangan diblokir kecuali Anda ingin memblokir seluruh instansi, yang seharusnya Anda pakai blokir domain. + instance_actor_flash: 'Akun ini adalah aktor virtual yang dipakai untuk merepresentasikan server, bukan pengguna individu. Ini dipakai untuk tujuan federasi dan jangan diblokir kecuali Anda ingin memblokir seluruh instansi, yang seharusnya Anda pakai blokir domain. + +' learn_more: Pelajari selengkapnya privacy_policy: Kebijakan Privasi see_whats_happening: Lihat apa yang sedang terjadi @@ -37,8 +39,11 @@ id: domain: Server reason: Alasan rejecting_media: 'Berkas media dari server ini tak akan diproses dan disimpan, dan tak akan ada gambar kecil yang ditampilkan, perlu klik manual utk menuju berkas asli:' + rejecting_media_title: Media yang disaring silenced: 'Pos dari server ini akan disembunyikan dari linimasa publik dan percakapan, dan takkan ada notifikasi yang dibuat dari interaksi pengguna mereka, kecuali Anda mengikuti mereka:' + silenced_title: Server yang dibisukan suspended: 'Takkan ada data yang diproses, disimpan, dan ditukarkan dari server ini, sehingga interaksi atau komunikasi dengan pengguna dari server ini tak mungkin dilakukan:' + suspended_title: Server yang ditangguhkan unavailable_content_html: Mastodon umumnya mengizinkan Anda untuk melihat konten dan berinteraksi dengan pengguna dari server lain di fediverse. Ini adalah pengecualian yang dibuat untuk beberapa server. user_count_after: other: pengguna @@ -52,6 +57,7 @@ id: followers: other: Pengikut following: Mengikuti + instance_actor_flash: Akun ini adalah aktor virtual yang merepresentasikan server itu sendiri dan bukan pengguna individu. Ini dipakai untuk tujuan gabungan dan seharusnya tidak ditangguhkan. joined: Bergabung pada %{date} last_active: terakhir aktif link_verified_on: Kepemilikan tautan ini telah dicek pada %{date} @@ -86,9 +92,10 @@ id: delete: Hapus destroyed_msg: Catatan moderasi berhasil dihapus! accounts: - add_email_domain_block: Masukkan domain surel ke daftar hitam + add_email_domain_block: Masukkan domain email ke daftar hitam approve: Terima approve_all: Terima semua + approved_msg: Berhasil menerima pendaftaran %{username} are_you_sure: Anda yakin? avatar: Avatar by_domain: Domian @@ -102,8 +109,10 @@ id: confirm: Konfirmasi confirmed: Dikonfirmasi confirming: Mengkonfirmasi + delete: Hapus data deleted: Terhapus demote: Turunkan + destroyed_msg: Data %{username} masuk antrean untuk dihapus segera disable: Nonaktifkan disable_two_factor_authentication: Nonaktifkan 2FA disabled: Dinonaktifkan @@ -114,10 +123,12 @@ id: email_status: Status Email enable: Aktifkan enabled: Diaktifkan + enabled_msg: Berhasil mencairkan akun %{username} followers: Pengikut follows: Mengikut header: Tajuk inbox_url: URL Kotak masuk + invite_request_text: Alasan bergabung invited_by: Diundang oleh ip: IP joined: Bergabung @@ -129,6 +140,8 @@ id: login_status: Status login media_attachments: Lampiran media memorialize: Ubah menjadi memoriam + memorialized: Dikenang + memorialized_msg: Berhasil mengubah akun %{username} menjadi akun memorial moderation: active: Aktif all: Semua @@ -149,10 +162,14 @@ id: public: Publik push_subscription_expires: Langganan PuSH telah kadaluarsa redownload: Muat ulang profil + redownloaded_msg: Berhasil menyegarkan profil %{username} dari asal reject: Tolak reject_all: Tolak semua + rejected_msg: Berhasil menolak permintaan pendaftaran %{username} remove_avatar: Hapus avatar remove_header: Hapus header + removed_avatar_msg: Berhasil menghapus gambar avatar %{username} + removed_header_msg: Berhasil menghapus gambar header %{username} resend_confirmation: already_confirmed: Pengguna ini sudah dikonfirmasi send: Kirim ulang email konfirmasi @@ -167,8 +184,10 @@ id: staff: Staf user: Pengguna search: Cari - search_same_email_domain: Pengguna lain dengan domain surel yang sama + search_same_email_domain: Pengguna lain dengan domain email yang sama search_same_ip: Pengguna lain dengan IP yang sama + sensitive: Sensitif + sensitized: ditandai sebagai sensitif shared_inbox_url: URL kotak masuk bersama show: created_reports: Laporan yang dibuat oleh akun ini @@ -178,65 +197,82 @@ id: statuses: Status subscribe: Langganan suspended: Disuspen + suspension_irreversible: Data akun ini telah dihapus secara permanen. Anda dapat mengaktifkan akun agar tetap bisa dipakai lagi tapi data sebelumnya tidak dapat dikembalikan. + suspension_reversible_hint_html: Akun telah ditangguhkan, dan data akan dihapus total pada %{date}. Sebelum tanggal tersebut, akun dapat dikembalikan tanpa efek apapun. Jika Anda ingin menghapus segera semua data, Anda dapat melakukan sesuai keterangan di bawah. time_in_queue: Menunggu dalam antrean %{time} title: Akun unconfirmed_email: Email belum dikonfirmasi + undo_sensitized: Batalkan sensitif undo_silenced: Undo mendiamkan undo_suspension: Undo suspen + unsilenced_msg: Berhasil membuka batasan akun %{username} unsubscribe: Berhenti langganan + unsuspended_msg: Berhasil membuka penangguhan akun %{username} username: Nama pengguna + view_domain: Tampilkan ringkasan domain warn: Beri Peringatan web: Web whitelisted: Masuk daftar putih action_logs: action_types: - change_email_user: Ubah Surel untuk Pengguna + assigned_to_self_report: Berikan laporan + change_email_user: Ubah Email untuk Pengguna confirm_user: Konfirmasi Pengguna create_account_warning: Buat Peringatan create_announcement: Buat Pengumuman create_custom_emoji: Buat Emoji Khusus create_domain_allow: Buat Izin Domain create_domain_block: Buat Blokir Domain - create_email_domain_block: Buat Surel Blokir Domain + create_email_domain_block: Buat Email Blokir Domain + create_ip_block: Buat aturan IP demote_user: Turunkan Pengguna destroy_announcement: Hapus Pengumuman destroy_custom_emoji: Hapus Emoji Khusus destroy_domain_allow: Hapus Izin Domain destroy_domain_block: Hapus Blokir Domain - destroy_email_domain_block: Hapus surel blokir domain + destroy_email_domain_block: Hapus email blokir domain + destroy_ip_block: Hapus aturan IP destroy_status: Hapus Status disable_2fa_user: Nonaktifkan 2FA disable_custom_emoji: Nonaktifkan Emoji Khusus disable_user: Nonaktifkan Pengguna enable_custom_emoji: Aktifkan Emoji Khusus enable_user: Aktifkan Pengguna + memorialize_account: Kenang Akun promote_user: Promosikan Pengguna remove_avatar_user: Hapus Avatar reopen_report: Buka Lagi Laporan reset_password_user: Atur Ulang Kata sandi + resolve_report: Selesaikan Laporan + sensitive_account: Tandai media di akun Anda sebagai sensitif silence_account: Bisukan Akun suspend_account: Tangguhkan Akun + unassigned_report: Batalkan Pemberian Laporan + unsensitive_account: Batalkan tanda media di akun Anda dari sensitif unsilence_account: Lepas Status Bisu Akun unsuspend_account: Lepas Status Tangguh Akun update_announcement: Perbarui Pengumuman update_custom_emoji: Perbarui Emoji Khusus + update_domain_block: Perbarui Blokir Domain update_status: Perbarui Status actions: assigned_to_self_report: "%{name} menugaskan laporan %{target} kpd dirinya sendiri" - change_email_user: "%{name} mengubah alamat surel pengguna %{target}" - confirm_user: "%{name} mengonfirmasi alamat surel pengguna %{target}" + change_email_user: "%{name} mengubah alamat email pengguna %{target}" + confirm_user: "%{name} mengonfirmasi alamat email pengguna %{target}" create_account_warning: "%{name} mengirim peringatan untuk %{target}" create_announcement: "%{name} membuat pengumuman baru %{target}" create_custom_emoji: "%{name} mengunggah emoji baru %{target}" create_domain_allow: "%{name} memasukkan ke daftar putih domain %{target}" create_domain_block: "%{name} memblokir domain %{target}" - create_email_domain_block: "%{name} memasukkan ke daftar hitam domain surel %{target}" + create_email_domain_block: "%{name} memblokir domain email %{target}" + create_ip_block: "%{name} membuat aturan untuk IP %{target}" demote_user: "%{name} menurunkan pengguna %{target}" destroy_announcement: "%{name} menghapus pengumuman %{target}" destroy_custom_emoji: "%{name} menghapus emoji %{target}" destroy_domain_allow: "%{name} menghapus domain %{target} dari daftar putih" destroy_domain_block: "%{name} membuka blokir domain %{target}" - destroy_email_domain_block: "%{name} memasukkan ke daftar putih surel domain %{target}" + destroy_email_domain_block: "%{name} membuka blokir domain email %{target}" + destroy_ip_block: "%{name} menghapus aturan untuk IP %{target}" destroy_status: "%{name} menghapus status %{target}" disable_2fa_user: "%{name} mematikan syarat dua faktor utk pengguna %{target}" disable_custom_emoji: "%{name} mematikan emoji %{target}" @@ -249,13 +285,16 @@ id: reopen_report: "%{name} membuka ulang laporan %{target}" reset_password_user: "%{name} mereset kata sandi pengguna %{target}" resolve_report: "%{name} menyelesaikan laporan %{target}" + sensitive_account: "%{name} menandai media %{target} sebagai sensitif" silence_account: "%{name} membungkam akun %{target}" suspend_account: "%{name} menangguhkan akun %{target}" unassigned_report: "%{name} tidak menugaskan laporan %{target}" + unsensitive_account: "%{name} membatalkan tanda media %{target} sebagai sensitif" unsilence_account: "%{name} menghapus bungkaman akun %{target}" unsuspend_account: "%{name} menghapus penangguhan akun %{target}" update_announcement: "%{name} memperbarui pengumuman %{target}" update_custom_emoji: "%{name} memperbarui emoji %{target}" + update_domain_block: "%{name} memperbarui blokir domain untuk %{target}" update_status: "%{name} memperbarui status %{target}" deleted_status: "(status dihapus)" empty: Log tidak ditemukan. @@ -299,6 +338,7 @@ id: listed: Terdaftar new: title: Tambah emoji kustom baru + not_permitted: Anda tidak diizinkan untuk melakukan tindakan ini overwrite: Timpa shortcode: Kode pendek shortcode_hint: Sedikitnya 2 karakter, hanya karakter alfanumerik dan garis bawah @@ -383,19 +423,20 @@ id: view: Lihat blokir domain email_domain_blocks: add_new: Tambah baru - created_msg: Berhasil menambahkan domain surel ke daftar hitam + created_msg: Berhasil memblokir domain email delete: Hapus - destroyed_msg: Berhasil menghapus domain surel dari daftar hitam + destroyed_msg: Berhasil membuka blokiran domain email domain: Domain - empty: Tidak ada domain surel yang masuk daftar hitam. + empty: Tidak ada domain email yang diblokir. from_html: dari %{domain} new: create: Tambah domain - title: Entri daftar hitam surel baru - title: Daftar hitam surel + title: Blokir domain email baru + title: Domain email terblokir instances: by_domain: Domain delivery_available: Pengiriman tersedia + empty: Domain tidak ditemukan. known_accounts: other: "%{count} akun yang dikenal" moderation: @@ -418,6 +459,21 @@ id: expired: Kedaluwarsa title: Saring title: Undang + ip_blocks: + add_new: Buat aturan + created_msg: Berhasil menambah aturan IP baru + delete: Hapus + expires_in: + '1209600': 2 minggu + '15778476': 6 bulan + '2629746': 1 bulan + '31556952': 1 tahun + '86400': 1 hari + '94670856': 3 tahun + new: + title: Buat aturan IP baru + no_ip_block_selected: Tak ada aturan IP yang berubah karena tak ada yang dipilih + title: Aturan IP pending_accounts: title: Akun tertunda (%{count}) relationships: @@ -455,6 +511,8 @@ id: comment: none: Tidak ada created_at: Dilaporkan + forwarded: Diteruskan + forwarded_to: Diteruskan ke %{domain} mark_as_resolved: Tandai telah diseleseikan mark_as_unresolved: Tandai belum terselesaikan notes: @@ -498,6 +556,7 @@ id: domain_blocks_rationale: title: Tampilkan alasan enable_bootstrap_timeline_accounts: + desc_html: Buat pengguna baru mengikuti akun yang sudah dipilih agar beranda mereka tidak kosong title: Aktifkan opsi ikuti otomatis untuk pengguna baru hero: desc_html: Ditampilkan di halaman depan. Direkomendasikan minimal 600x100px. Jika tidak diatur, kembali ke server gambar kecil @@ -524,6 +583,9 @@ id: min_invite_role: disabled: Tidak ada satu pun title: Izinkan undangan oleh + require_invite_text: + desc_html: Saat pendaftaran harus disetujui manual, buat input teks "Mengapa Anda ingin bergabung?" sebagai hal wajib bukan opsional + title: Pengguna baru harus memasukkan alasan bergabung registrations_mode: modes: approved: Persetujuan diperlukan untuk mendaftar @@ -621,6 +683,7 @@ id: add_new: Buat alias created_msg: Berhasil membuat alias baru. Sekarang Anda dapat memulai pindah dari akun lama. deleted_msg: Berhasil menghapus alias. Pindah dari akun tersebut ke sini tidak akan lagi bisa dilakukan. + empty: Anda tidak memiliki alias. hint_html: Jika Anda ingin pindah dari akun lain ke sini, Anda dapat membuat alias, yang dilakukan sebelum Anda setuju dengan memindah pengikut dari akun lama ke akun sini. Aksi ini <strong>tidak berbahaya dan tidak bisa dikembalikan</strong>. <strong>Pemindahan akun dimulai dari akun lama</strong>. remove: Hapus tautan alias appearance: @@ -662,8 +725,11 @@ id: prefix_sign_up: Daftar ke Mastodon hari ini! suffix: Dengan sebuah akun, Anda dapat mengikuti orang, mengirim pembaruan, dan bertukar pesan dengan pengguna dari server Mastodon mana pun dan lainnya! didnt_get_confirmation: Tidak menerima petunjuk konfirmasi? + dont_have_your_security_key: Tidak memiliki kunci keamanan? forgot_password: Lupa kata sandi? invalid_reset_password_token: Token reset kata sandi tidak valid atau kedaluwarsa. Silakan minta yang baru. + link_to_otp: Masukkan kode dua-faktor dari ponsel Anda atau dari kode pemulihan + link_to_webauth: Gunakan perangkat kunci keamanan Anda login: Masuk logout: Keluar migrate_account: Pindah ke akun berbeda @@ -679,16 +745,18 @@ id: security: Identitas set_new_password: Tentukan kata sandi baru setup: - email_below_hint_html: Jika alamat surel di bawah tidak benar, Anda dapat menggantinya di sini dan menerima konfirmasi surel baru. - email_settings_hint_html: Konfirmasi surel telah dikirim ke %{email}. Jika alamat surel tidak benar, Anda dapat mengubahnya di setelan akun. + email_below_hint_html: Jika alamat email di bawah tidak benar, Anda dapat menggantinya di sini dan menerima email konfirmasi baru. + email_settings_hint_html: Email konfirmasi telah dikirim ke %{email}. Jika alamat email tidak benar, Anda dapat mengubahnya di pengaturan akun. title: Atur status: account_status: Status akun - confirming: Menunggu konfirmasi surel diselesaikan. + confirming: Menunggu konfirmasi email diselesaikan. functional: Akun Anda kini beroperasi penuh. - pending: Lamaran Anda sedang ditinjau oleh staf kami. Ini mungkin butuh beberapa waktu. Anda akan menerima sebuah surel jika lamaran Anda diterima. + pending: Permintaan Anda sedang ditinjau oleh staf kami. Ini mungkin butuh beberapa waktu. Anda akan menerima email jika permintaan Anda diterima. redirecting_to: Akun Anda tidak aktif karena sekarang dialihkan ke %{acct}. + too_fast: Formulir dikirim terlalu cepat, coba lagi. trouble_logging_in: Kesulitan masuk? + use_security_key: Gunakan kunci keamanan authorize_follow: already_following: Anda sudah mengikuti akun ini already_requested: Anda sudah mengirimkan permintaan untuk mengikuti akun tersebut @@ -706,9 +774,14 @@ id: hint_html: "<strong>Tip:</strong> Kami tidak akan meminta kata sandi Anda lagi untuk beberapa jam ke depan." invalid_password: Kata sandi tidak valid prompt: Konfirmasi kata sandi untuk melanjutkan + crypto: + errors: + invalid_key: bukan kunci Ed25519 atau Curve25519 yang valid + invalid_signature: bukan tanda tangan Ed25519 yang valid date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}j" @@ -733,9 +806,9 @@ id: before: 'Sebelum melanjutkan, silakan baca catatan ini dengan hati-hati:' caches: Konten yang telah tersimpan di server lain mungkin akan tetap di sana data_removal: Kiriman Anda dan data lainnya akan dihapus secara permanen - email_change_html: Anda dapat <a href="%{path}">mengubah alamat surel Anda</a> tanpa perlu menghapus akun - email_contact_html: Jika pesan belum diterima, Anda dapat mengirim surel <a href="mailto:%{email}">%{email}</a> sebagai bantuan - email_reconfirmation_html: Jika Anda tidak menerima konfirmasi surel, <a href="%{path}">Anda dapat memintanya lagi</a> + email_change_html: Anda dapat <a href="%{path}">mengubah alamat email Anda</a> tanpa perlu menghapus akun + email_contact_html: Jika pesan belum diterima, Anda dapat mengirim email ke <a href="mailto:%{email}">%{email}</a> untuk mencari bantuan + email_reconfirmation_html: Jika Anda tidak menerima email konfirmasi, <a href="%{path}">Anda dapat memintanya lagi</a> irreversible: Anda tidak akan bisa lagi mengembalikan atau mengaktifkan kembali akun Anda more_details_html: Lebih detailnya, lihat <a href="%{terms_path}">kebijakan privasi</a>. username_available: Nama pengguna Anda akan tersedia lagi @@ -773,6 +846,7 @@ id: request: Meminta arsip Anda size: Ukuran blocks: Anda blokir + bookmarks: Markah csv: CSV domain_blocks: Blokir domain lists: Daftar @@ -834,9 +908,13 @@ id: inactive: Tidak aktif publicize_checkbox: 'Dan toot ini:' publicize_toot: 'Terbukti! Saya adalah %{username} di %{service}: %{url}' + remove: Hapus bukti dari akun + removed: Berhasil menghapus bukti dari akun status: Status verifikasi view_proof: Lihat bukti imports: + errors: + over_rows_processing_limit: berisi lebih dari %{count} baris modes: merge: Gabung merge_long: Pertahankan rekaman yang sudah ada dan buat baru @@ -846,6 +924,7 @@ id: success: Data anda berhasil diupload dan akan diproses sesegera mungkin types: blocking: Daftar diblokir + bookmarks: Markah domain_blocking: Daftar blokir domain following: Daftar diikuti muting: Daftar didiamkan @@ -899,6 +978,7 @@ id: on_cooldown: Anda baru saja memindahkan akun Anda. Fungsi ini akan tersedia kembali %{count} hari lagi. past_migrations: Migrasi lampau proceed_with_move: Pindahkan pengikut + redirected_msg: Akun Anda sedang dialihkan ke %{acct}. redirecting_to: Akun Anda dialihkan ke %{acct}. set_redirect: Atur peralihan warning: @@ -912,6 +992,10 @@ id: redirect: Pemberitahuan peralihan akan dimunculkan pada akun profil Anda dan akun akan dikecualikan dari pencarian moderation: title: Moderasi + move_handler: + carry_blocks_over_text: Pengguna ini pindah dari %{acct}, yang telah Anda blokir sebelumnya. + carry_mutes_over_text: Pengguna ini pindah dari %{acct}, yang telah Anda bisukan sebelumnya. + copy_account_note_text: 'Pengguna ini pindah dari %{acct}, ini dia pesan Anda sebelumnya tentang mereka:' notification_mailer: digest: action: Lihat semua notifikasi @@ -945,7 +1029,7 @@ id: subject: "%{name} mem-boost status anda" title: Boost baru notifications: - email_events: Event untuk notifikasi surel + email_events: Event untuk notifikasi email email_events_hint: 'Pilih event yang ingin Anda terima notifikasinya:' other_settings: Pengaturan notifikasi lain number: @@ -958,6 +1042,14 @@ id: quadrillion: Kdt thousand: Rb trillion: T + otp_authentication: + code_hint: Masukkan kode yang dibuat oleh aplikasi autentikator sebagai konfirmasi + description_html: Jika Anda mengaktifkan <strong>autentikasi dua-faktor</strong> menggunakan aplikasi autentikator, Anda membutuhkan ponsel untuk masuk akun, yang akan membuat token untuk dimasukkan. + enable: Aktifkan + instructions_html: "<strong>Pindai kode QR ini dengan Google Authenticator anda atau aplikasi TOTP lainnya di ponsel anda</strong>. Mulai sekarang, aplikasi tersebut akan membuat token yang bisa anda gunakan untuk masuk akun." + manual_instructions: 'Jika anda tidak bisa memindai kode QR dan harus memasukkannya secara manual, ini dia kode rahasia yang harus dimasukkan:' + setup: Persiapan + wrong_code: Kode yang dimasukkan tidak cocok! Apakah waktu server dan waktu di ponsel sudah benar? pagination: newer: Lebih baru next: Selanjutnya @@ -986,6 +1078,7 @@ id: relationships: activity: Aktivitas akun dormant: Terbengkalai + follow_selected_followers: Ikuti pengikut yang dipilih followers: Pengikut following: Mengikuti invited: Diundang @@ -1082,10 +1175,13 @@ id: profile: Profil relationships: Ikuti dan pengikut two_factor_authentication: Autentikasi Two-factor + webauthn_authentication: Kunci keamanan spam_check: spam_detected: Ini adalah laporan otomatis. Spam terdeteksi. statuses: attached: + audio: + other: "%{count} audio" description: 'Terlampir: %{attached}' image: other: "%{count} gambar" @@ -1112,6 +1208,8 @@ id: other: "%{count} memilih" vote: Memilih show_more: Tampilkan selengkapnya + show_newer: Tampilkan lebih baru + show_older: Tampilkan lebih lama show_thread: Tampilkan utas sign_in_to_participate: Masuk untuk mengikuti percakapan title: '%{name}: "%{quote}"' @@ -1129,6 +1227,87 @@ id: tags: does_not_match_previous_name: tidak cocok dengan nama sebelumnya terms: + body_html: | + <h2>Privacy Policy</h2> + <h3 id="collect">What information do we collect?</h3> + + <ul> + <li><em>Basic account information</em>: If you register on this server, you may be asked to enter a username, an e-mail address and a password. You may also enter additional profile information such as a display name and biography, and upload a profile picture and header image. The username, display name, biography, profile picture and header image are always listed publicly.</li> + <li><em>Posts, following and other public information</em>: The list of people you follow is listed publicly, the same is true for your followers. When you submit a message, the date and time is stored as well as the application you submitted the message from. Messages may contain media attachments, such as pictures and videos. Public and unlisted posts are available publicly. When you feature a post on your profile, that is also publicly available information. Your posts are delivered to your followers, in some cases it means they are delivered to different servers and copies are stored there. When you delete posts, this is likewise delivered to your followers. The action of reblogging or favouriting another post is always public.</li> + <li><em>Direct and followers-only posts</em>: All posts are stored and processed on the server. Followers-only posts are delivered to your followers and users who are mentioned in them, and direct posts are delivered only to users mentioned in them. In some cases it means they are delivered to different servers and copies are stored there. We make a good faith effort to limit the access to those posts only to authorized persons, but other servers may fail to do so. Therefore it's important to review servers your followers belong to. You may toggle an option to approve and reject new followers manually in the settings. <em>Please keep in mind that the operators of the server and any receiving server may view such messages</em>, and that recipients may screenshot, copy or otherwise re-share them. <em>Do not share any dangerous information over Mastodon.</em></li> + <li><em>IPs and other metadata</em>: When you log in, we record the IP address you log in from, as well as the name of your browser application. All the logged in sessions are available for your review and revocation in the settings. The latest IP address used is stored for up to 12 months. We also may retain server logs which include the IP address of every request to our server.</li> + </ul> + + <hr class="spacer" /> + + <h3 id="use">What do we use your information for?</h3> + + <p>Any of the information we collect from you may be used in the following ways:</p> + + <ul> + <li>To provide the core functionality of Mastodon. You can only interact with other people's content and post your own content when you are logged in. For example, you may follow other people to view their combined posts in your own personalized home timeline.</li> + <li>To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.</li> + <li>The email address you provide may be used to send you information, notifications about other people interacting with your content or sending you messages, and to respond to inquiries, and/or other requests or questions.</li> + </ul> + + <hr class="spacer" /> + + <h3 id="protect">How do we protect your information?</h3> + + <p>We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm. You may enable two-factor authentication to further secure access to your account.</p> + + <hr class="spacer" /> + + <h3 id="data-retention">What is our data retention policy?</h3> + + <p>We will make a good faith effort to:</p> + + <ul> + <li>Retain server logs containing the IP address of all requests to this server, in so far as such logs are kept, no more than 90 days.</li> + <li>Retain the IP addresses associated with registered users no more than 12 months.</li> + </ul> + + <p>You can request and download an archive of your content, including your posts, media attachments, profile picture, and header image.</p> + + <p>You may irreversibly delete your account at any time.</p> + + <hr class="spacer"/> + + <h3 id="cookies">Do we use cookies?</h3> + + <p>Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.</p> + + <p>We use cookies to understand and save your preferences for future visits.</p> + + <hr class="spacer" /> + + <h3 id="disclose">Do we disclose any information to outside parties?</h3> + + <p>We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.</p> + + <p>Your public content may be downloaded by other servers in the network. Your public and followers-only posts are delivered to the servers where your followers reside, and direct messages are delivered to the servers of the recipients, in so far as those followers or recipients reside on a different server than this.</p> + + <p>When you authorize an application to use your account, depending on the scope of permissions you approve, it may access your public profile information, your following list, your followers, your lists, all your posts, and your favourites. Applications can never access your e-mail address or password.</p> + + <hr class="spacer" /> + + <h3 id="children">Site usage by children</h3> + + <p>If this server is in the EU or the EEA: Our site, products and services are all directed to people who are at least 16 years old. If you are under the age of 16, per the requirements of the GDPR (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">General Data Protection Regulation</a>) do not use this site.</p> + + <p>If this server is in the USA: Our site, products and services are all directed to people who are at least 13 years old. If you are under the age of 13, per the requirements of COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Children's Online Privacy Protection Act</a>) do not use this site.</p> + + <p>Law requirements can be different if this server is in another jurisdiction.</p> + + <hr class="spacer" /> + + <h3 id="changes">Changes to our Privacy Policy</h3> + + <p>If we decide to change our privacy policy, we will post those changes on this page.</p> + + <p>This document is CC-BY-SA. It was last updated March 7, 2018.</p> + + <p>Originally adapted from the <a href="https://github.com/discourse/discourse">Discourse privacy policy</a>.</p> title: "%{instance} Ketentuan Layanan dan Kebijakan Privasi" themes: contrast: Mastodon (Kontras tinggi) @@ -1139,42 +1318,50 @@ id: default: "%d %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Masukkan kode yang dibuat oleh app autentikator sebagai konfirmasi - description_html: Jika anda menaktifkan ototentikasi dua faktor, saat login anda harus menggunakan telepon anda untuk membuat token supaya anda bisa masuk. + add: Tambah disable: Matikan - enable: Aktifkan + disabled_success: Autentikasi dua-faktor berhasil dinonaktifkan + edit: Edit enabled: Otentifikasi dua faktor aktif enabled_success: Ototentikasi dua faktor telah diaktifkan generate_recovery_codes: Buat Kode Pemulihan - instructions_html: "<strong>Pindai kode QR ini pada Otentikator Google anda atau aplikasi TOTP lainnya di telepon anda</strong>. Mulai sekarang, aplikasi tersebut akan membuat token yang bisa anda gunakan untuk login." lost_recovery_codes: Kode pemulihan bisa anda gunakan untuk mendapatkan kembali akses pada akun anda jika anda kehilangan handphone anda. Jika anda kehilangan kode pemulihan, anda bisa membuatnya ulang disini. Kode pemulihan anda yang lama tidak akan bisa digunakan lagi. - manual_instructions: 'Jika anda tidak bisa memindai kode QR dan harus memasukkannya secara manual, ini dia kode yang harus dimasukkan:' + methods: Metode dua-faktor + otp: Aplikasi autentikator recovery_codes: Kode pemulihan cadangan recovery_codes_regenerated: Kode Pemulihan berhasil dibuat ulang recovery_instructions_html: Jika anda kehilangan akses pada handphone anda, anda bisa menggunakan kode pemulihan dibawah ini untuk mendapatkan kembali akses pada akun anda. Simpan kode pemulihan anda baik-baik, misalnya dengan mencetaknya atau menyimpannya bersama dokumen penting lainnya. - setup: Persiapan - wrong_code: Kode yang dimasukkan tidak cocok! Apa waktu server dan waktu di handphone sudah cocok? + webauthn: Kunci keamanan user_mailer: backup_ready: explanation: Cadangan penuh akun Mastodon Anda sudah dapat diunduh! subject: Arsip Anda sudah siap diunduh title: Ambil arsip + sign_in_token: + details: 'Ini dia rincian usaha masuk akun:' + explanation: 'Kami mendeteksi usaha masuk ke akun Anda dari alamat IP tak dikenal. Jika ini Anda, mohon masukkan kode keamanan di bawah pada halaman masuk:' + further_actions: 'Jika ini bukan Anda, mohon ganti kata sandi dan aktifkan autentikasi dua-faktor pada akun Anda. Anda bisa melakukannya di sini:' + subject: Harap konfirmasi usaha masuk akun + title: Usaha masuk akun warning: explanation: disable: Saat akun Anda beku, data Anda tetap utuh. Anda tidak akan dapat melakukan apa-apa sampai akun Anda tidak lagi dikunci. + sensitive: Berkas media dan media tertaut yang Anda unggah akan dianggap sebagai sensitif. silence: Saat akun Anda dibatasi, hanya akun yang Anda ikuti yang dapat melihat toot Anda di server ini. Akun Anda mungkin akan dikecualikan dari daftar publik. Akun lain dapat mengikuti akun Anda secara manual. suspend: Akun Anda telah ditangguhkan. Semua toot dan media yang Anda unggah dihapus secara permanen dari server ini, dan server tempat Anda memiliki pengikut. - get_in_touch: Anda dapat membalas surel ini untuk menghubungi pengurus %{instance}. + get_in_touch: Anda dapat membalas email ini untuk menghubungi pengurus %{instance}. review_server_policies: Tinjau kebijakan server statuses: 'Khususnya untuk:' subject: disable: Akun Anda %{acct} telah dibekukan none: Peringatan untuk %{acct} + sensitive: Postingan media akun Anda %{acct} telah ditandai sebagai sensitif silence: Akun Anda %{acct} telah dibatasi suspend: Akun Anda %{acct} telah ditangguhkan title: disable: Akun dibekukan none: Peringatan + sensitive: Media Anda telah ditandai sebagai sensitif silence: Akun dibatasi suspend: Akun ditangguhkan welcome: @@ -1186,7 +1373,7 @@ id: full_handle: Penanganan penuh Anda full_handle_hint: Ini yang dapat Anda sampaikan kepada teman agar mereka dapat mengirim pesan atau mengikuti Anda dari server lain. review_preferences_action: Ubah preferensi - review_preferences_step: Pastikan Anda telah mengatur preferensi Anda, seperti surel untuk menerima pesan, atau tingkat privasi bawaan untuk kiriman Anda. Jika Anda tidak alergi dengan gerakan gambar, Anda dapat mengaktifkan opsi mainkan otomatis GIF. + review_preferences_step: Pastikan Anda telah mengatur preferensi Anda, seperti email untuk menerima pesan, atau tingkat privasi bawaan untuk postingan Anda. Jika Anda tidak alergi dengan gerakan gambar, Anda dapat mengaktifkan opsi mainkan otomatis GIF. subject: Selamat datang di Mastodon tip_federated_timeline: Linimasa gabungan adalah ruang yang menampilkan jaringan Mastodon. Tapi ini hanya berisi tetangga orang-orang yang Anda ikuti, jadi tidak sepenuhnya komplet. tip_following: Anda secara otomatis mengikuti admin server. Untuk mencari akun-akun yang menarik, silakan periksa linimasa lokal dan gabungan. @@ -1195,12 +1382,34 @@ id: tips: Tips title: Selamat datang, %{name}! users: + blocked_email_provider: Layanan email ini tidak diizinkan follow_limit_reached: Anda tidak dapat mengikuti lebih dari %{limit} orang + generic_access_help_html: Mengalami masalah saat akses akun? Anda mungkin perlu menghubungi %{email} untuk mencari bantuan invalid_email: Alamat email tidak cocok + invalid_email_mx: Alamat email ini sepertinya tidak ada invalid_otp_token: Kode dua faktor tidak cocok + invalid_sign_in_token: Kode keamanan tidak valid otp_lost_help_html: Jika Anda kehilangan akses keduanya, Anda dapat menghubungi %{email} - seamless_external_login: Anda masuk via layanan eksternal, sehingga setelan kata sandi dan surel tidak tersedia. + seamless_external_login: Anda masuk via layanan eksternal, sehingga pengaturan kata sandi dan email tidak tersedia. signed_in_as: 'Masuk sebagai:' + suspicious_sign_in_confirmation: Anda terlihat belum pernah masuk dari perangkat ini, dan sudah lama Anda tidak masuk akun, sehingga kami mengirim kode keamanan ke alamat email Anda untuk mengonfirmasi bahwa ini adalah Anda. verification: explanation_html: 'Anda dapat <strong>memverifikasi diri Anda sebagai pemiliki tautan pada metadata profil</strong>. Situsweb yang ditautkan haruslah berisi tautan ke profil Mastodon Anda. Tautan tersebut <strong>harus</strong> memiliki atribut <code>rel="me"</code>. Isi teks tautan tidaklah penting. Ini contohnya:' verification: Verifikasi + webauthn_credentials: + add: Tambahkan kunci keamanan baru + create: + error: Terjadi masalah saat menambahkan kunci keamanan. Silakan coba lagi. + success: Kunci keamanan Anda berhasil ditambahkan. + delete: Hapus + delete_confirmation: Yakin ingin menghapus kunci keamanan ini? + description_html: Jika Anda mengaktifkan <strong>autentikasi kunci keamanan</strong>, proses masuk Anda akan memerlukan salah satu kunci keamanan Anda. + destroy: + error: Terjadi masalah saat menghapus kunci keamanan Anda. Silakan coba lagi. + success: Kunci keamanan Anda berhasil dihapus. + invalid_credential: Kunci keamanan tidak valid + nickname_hint: Masukkan panggilan kunci keamanan baru Anda + not_enabled: Anda belum mengaktifkan WebAuthn + not_supported: Peramban ini tidak mendukung kunci keamanan + otp_required: Untuk menggunakan kunci keamanan harap aktifkan autentikasi dua-faktor. + registered_on: Terdaftar pada %{date} diff --git a/config/locales/io.yml b/config/locales/io.yml index 0b09134bb651b5e965756f30e05b7a9011724306..a99c4a96652d389be08f0652bb129084348e8c1b 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -98,14 +98,6 @@ io: blocking: Listo de blokusiti following: Listo de sequati upload: Kargar - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day notification_mailer: digest: body: Yen mikra rezumo di to, depos ke tu laste vizitis en %{since} @@ -159,11 +151,8 @@ io: reblogged: diskonocigita sensitive_content: Titiliva kontenajo two_factor_authentication: - description_html: Se tu posibligas <strong>dufaktora autentikigo</strong>, tu bezonos tua poshtelefonilo por enirar, nam ol kreos nombri, quin tu devos enskribar. disable: Extingar - enable: Acendar generate_recovery_codes: Generate Recovery Codes - instructions_html: "<strong>Skanez ta QR-kodexo per Google Authenticator o per simila apliko di tua poshtelefonilo</strong>. De lore, la apliko kreos nombri, quin tu devos enskribar." recovery_instructions_html: If you ever lose access to your phone, you can use one of the recovery codes below to regain access to your account. Keep the recovery codes safe, for example by printing them and storing them with other important documents. users: invalid_email: La retpost-adreso ne esas valida diff --git a/config/locales/is.yml b/config/locales/is.yml index 1da4b69cdbe838c19a820b31a57cbcc4b4850b92..2d6102d98dee3ce2446fefeb848d0b977de46861 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -60,10 +60,11 @@ is: one: fylgjandi other: fylgjendur following: Fylgist með + instance_actor_flash: Þessi notandaaðgangur er sýndarnotandi sem stendur fyrir sjálfan netþjóninn en ekki neinn einstakling. Hann er notaður við skýjasambandsmiðlun og ætti ekki að setja hann à bið eða banna. joined: Gerðist þátttakandi %{date} last_active: sÃðasta virkni link_verified_on: Eignarhald á þessum tengli var athugað þann %{date} - media: Myndskrár + media: Myndefni moved_html: "%{name} hefur verið færður à %{new_profile_link}:" network_hidden: Þessar upplýsingar ekki tiltækar never_active: Aldrei @@ -98,6 +99,7 @@ is: add_email_domain_block: Útiloka tölvupóstlén approve: Samþykkja approve_all: Samþykkja allt + approved_msg: Tókst að samþykkja skráningu fyrir %{username} are_you_sure: Ertu viss? avatar: Auðkennismynd by_domain: Lén @@ -111,8 +113,10 @@ is: confirm: Staðfesta confirmed: Staðfest confirming: Staðfesti + delete: Eyða gögnum deleted: Eytt demote: Lækka à tign + destroyed_msg: Gögn notandans %{username} eru núna à bið eftir að vera endanlega eytt disable: Gera óvirkt disable_two_factor_authentication: Gera tveggja-þátta auðkenningu óvirka disabled: Óvirkt @@ -123,10 +127,12 @@ is: email_status: Staða tölvupósts enable: Virkja enabled: Virkt + enabled_msg: Tókst að affrysta aðgang notandans %{username} followers: Fylgjendur follows: Fylgist með header: Haus inbox_url: Slóð á innhólf + invite_request_text: Ãstæður fyrir þátttöku invited_by: Boðið af ip: IP-vistfang joined: Gerðist þátttakandi @@ -138,6 +144,8 @@ is: login_status: Staða innskráningar media_attachments: Myndaviðhengi memorialize: Breyta à minningargrein + memorialized: Breytt à minningargrein + memorialized_msg: Tókst að breyta %{username} à minningaraðgang moderation: active: Virkur all: Allt @@ -158,10 +166,14 @@ is: public: Opinber push_subscription_expires: PuSH-áskrift rennur út redownload: Endurlesa notandasnið + redownloaded_msg: Tókst að endurlesa notandasnið %{username} úr upphaflegu sniði reject: Hafna reject_all: Hafna öllu + rejected_msg: Tókst að hafna skráningu fyrir %{username} remove_avatar: Fjarlægja auðkennismynd remove_header: Fjarlægja haus + removed_avatar_msg: Tókst að fjarlægja auðkennismynd notandans %{username} + removed_header_msg: Tókst að fjarlægja forsÃðumynd notandans %{username} resend_confirmation: already_confirmed: Þessi notandi hefur þegar verið staðfestur send: Senda staðfestingartölvupóst aftur @@ -178,6 +190,8 @@ is: search: Leita search_same_email_domain: Aðra notendur með sama tölvupóstlén search_same_ip: Aðrir notendur með sama IP-vistfang + sensitive: Viðkvæmt + sensitized: merkt sem viðkvæmt shared_inbox_url: Slóð á sameiginlegt innhólf show: created_reports: Gerðar kærur @@ -187,13 +201,19 @@ is: statuses: Stöðufærslur subscribe: Gerast áskrifandi suspended: à bið + suspension_irreversible: Gögnunum á þessum notandaaðgangi hefur verið eytt óafturkræft. Þú getur tekið aðganginn úr bið svo hægt sé að nota hann, en það mun ekki endurheimta neitt af þeim gögnum sem á honum voru áður. + suspension_reversible_hint_html: Notandaaðgangurin hefur verið settur à biðstöðu og gögnunum á honum verður eytt að fullu þann %{date}. Þangað til væri hægt að endurheimta aðganginn úr bið án nokkurra breytinga. Ef þú vilt eyða öllum gögnum af honum strax, geturðu gert það hér fyrir neðan. time_in_queue: BÃður à biðröð %{time} title: Notandaaðgangar unconfirmed_email: Óstaðfestur tölvupóstur + undo_sensitized: Afturkalla merkingu sem viðkvæmt undo_silenced: Hætta að hylja undo_suspension: Taka úr bið + unsilenced_msg: Tókst að fjarlægja takmarkanir af notandaaðgangnum fyrir %{username} unsubscribe: Taka úr áskrift + unsuspended_msg: Tókst að taka notandaaðganginn fyrir %{username} úr bið username: Notandanafn + view_domain: Skoða yfirlit fyrir lén warn: Aðvara web: Vefur whitelisted: à lista yfir leyft @@ -208,12 +228,14 @@ is: create_domain_allow: Búa til lén leyft create_domain_block: Búa til lén bannað create_email_domain_block: Búa til tölvupóstfang bannað + create_ip_block: Búa til IP-reglu demote_user: Lækka notanda à tign destroy_announcement: Eyða tilkynningu destroy_custom_emoji: Eyða sérsniðnu tjáningartákni destroy_domain_allow: Eyða léni leyft destroy_domain_block: Eyða léni bannað destroy_email_domain_block: Eyða tölvupóstfangi bannað + destroy_ip_block: Eyða IP-reglu destroy_status: Eyða stöðufærslu disable_2fa_user: Gera tveggja-þátta auðkenningu óvirka disable_custom_emoji: Gera sérsniðið tjáningartákn óvirkt @@ -226,13 +248,16 @@ is: reopen_report: Enduropna kæru reset_password_user: Endurstilla lykilorð resolve_report: Leysa kæru + sensitive_account: Merkja myndefni á aðgangnum þÃnum sem viðkvæmt silence_account: Hylja notandaaðgang suspend_account: Setja notandaaðgang à bið unassigned_report: Aftengja úthlutun kæru + unsensitive_account: Afmerkja myndefni á aðgangnum þÃnum sem viðkvæmt unsilence_account: Hætta að hylja notandaaðgang unsuspend_account: Taka notandaaðgang úr bið update_announcement: Uppfæra tilkynningu update_custom_emoji: Uppfæra sérsniðið tjáningartákn + update_domain_block: Uppfæra útilokun léns update_status: Uppfæra stöðufærslu actions: assigned_to_self_report: "%{name} úthlutaði skýrslu %{target} til sÃn" @@ -244,12 +269,14 @@ is: create_domain_allow: "%{name} setti lén %{target} á lista yfir leyft" create_domain_block: "%{name} útilokaði lénið %{target}" create_email_domain_block: "%{name} setti póstlén %{target} á lista yfir bannað" + create_ip_block: "%{name} bjó til reglu fyrir IP-vistfangið %{target}" demote_user: "%{name} lækkaði notandann %{target} à tign" destroy_announcement: "%{name} eyddi auglýsingu %{target}" destroy_custom_emoji: "%{name} henti út tjáningartákninu %{target}" destroy_domain_allow: "%{name} fjarlægði lén %{target} af lista yfir leyft" destroy_domain_block: "%{name} aflétti útilokun af léninu %{target}" destroy_email_domain_block: "%{name} setti póstlén %{target} á lista yfir leyft" + destroy_ip_block: "%{name} eyddi reglu fyrir IP-vistfangið %{target}" destroy_status: "%{name} fjarlægði stöðufærslu frá %{target}" disable_2fa_user: "%{name} gerði tveggja-þátta auðkenningu óvirka fyrir notandann %{target}" disable_custom_emoji: "%{name} gerði tjáningartáknið %{target} óvirkt" @@ -262,13 +289,16 @@ is: reopen_report: "%{name} enduropnaði skýrslu %{target}" reset_password_user: "%{name} endurstillti lykilorð fyrir notandann %{target}" resolve_report: "%{name} leysti skýrslu %{target}" + sensitive_account: "%{name} merkti myndefni frá %{target} sem viðkvæmt" silence_account: "%{name} gerði notandaaðganginn %{target} hulinn" suspend_account: "%{name} setti notandaaðganginn %{target} à bið" unassigned_report: "%{name} fjarlægði úthlutun af skýrslu %{target}" + unsensitive_account: "%{name} afmerkti myndefni frá %{target} sem viðkvæmt" unsilence_account: "%{name} hætti að hylja notandaaðganginn %{target}" unsuspend_account: "%{name} tók notandaaðganginn %{target} úr bið" update_announcement: "%{name} uppfærði auglýsingu %{target}" update_custom_emoji: "%{name} uppfærði tjáningartákn %{target}" + update_domain_block: "%{name} uppfærði útilokun lénsins %{target}" update_status: "%{name} uppfærði stöðufærslu frá %{target}" deleted_status: "(eydd stöðufærsla)" empty: Engar atvikaskrár fundust. @@ -372,6 +402,8 @@ is: silence: Hylja suspend: Setja à bið title: Ný útilokun á léni + obfuscate: Gera heiti léns ólæsilegt + obfuscate_hint: Gera heiti léns ólæsilegt að hluta à listanum ef auglýsing er virk fyrir lista yfir takmarkanir léna private_comment: Einkaathugasemd private_comment_hint: Athugasemd um þessa útilokun á léni til innanhússnotkunar fyrir umsjónarmenn. public_comment: Opinber athugasemd @@ -411,6 +443,7 @@ is: instances: by_domain: Lén delivery_available: Afhending er til taks + empty: Engin lén fundust. known_accounts: one: "%{count} þekktur notandaaðgangur" other: "%{count} þekktir notendaaðgangar" @@ -434,6 +467,21 @@ is: expired: Útrunnið title: SÃa title: Boðsgestir + ip_blocks: + add_new: Búa til reglu + created_msg: Tókst að búa til nýja IP-reglu + delete: Eyða + expires_in: + '1209600': 2 vikur + '15778476': 6 mánuðir + '2629746': 1 mánuður + '31556952': 1 ár + '86400': 1 dagur + '94670856': 3 ár + new: + title: Búa til nýja IP-reglu + no_ip_block_selected: Engum IP-reglum var breytt þvà ekkert var valið + title: IP-reglur pending_accounts: title: Notendaaðgangar à bið (%{count}) relationships: @@ -473,6 +521,8 @@ is: comment: none: Ekkert created_at: Tilkynnt + forwarded: Ãframsent + forwarded_to: Ãframsent á %{domain} mark_as_resolved: Merkja sem leyst mark_as_unresolved: Merkja sem óleyst notes: @@ -516,6 +566,7 @@ is: domain_blocks_rationale: title: Birta röksemdafærslu enable_bootstrap_timeline_accounts: + desc_html: Láta nýja notendur sjálfkrafa fylgjast með uppsettum aðgöngum svo að heimastreymi þeirra byrji ekki autt title: Virkja sjálfgefnar fylgnistillingar fyrir nýja notendur hero: desc_html: Birt á forsÃðunni. Mælt með að hún sé a.m.k. 600×100 mynddÃlar. Þegar þetta er ekki stillt, er notuð smámynd netþjónsins @@ -542,6 +593,9 @@ is: min_invite_role: disabled: Enginn title: Leyfa boð frá + require_invite_text: + desc_html: Þegar nýskráningar krefjast handvirks samþykkis, skal gera "Hvers vegna viltu taka þátt?" boðstexta að skyldu fremur en valkvæðan + title: Krefja nýja notendur um að fylla út boðstexta registrations_mode: modes: approved: Krafist er samþykkt nýskráningar @@ -681,8 +735,11 @@ is: prefix_sign_up: Skráðu þig á Mastodon strax à dag! suffix: Með notandaaðgangi geturðu fylgst með fólki, sent inn stöðufærslur og skipst á skilaboðum við notendur á hvaða Mastodon-vefþjóni sem er, auk margs fleira! didnt_get_confirmation: Fékkstu ekki leiðbeiningar um hvernig eigi að staðfesta aðganginn? + dont_have_your_security_key: Ertu ekki með öryggislykilinn þinn? forgot_password: Gleymdirðu lykilorðinu? invalid_reset_password_token: Teikn fyrir endurstillingu lykilorðs er ógilt eða útrunnið. Biddu um nýtt teikn. + link_to_otp: Settu inn tveggja-þátta kóða úr farsÃmanum þÃnum eða endurheimtukóða + link_to_webauth: Notaðu tæki með öryggislykli login: Skrá inn logout: Skrá út migrate_account: Færa á annan notandaaðgang @@ -707,7 +764,9 @@ is: functional: Notandaaðgangurinn þinn er með fulla virkni. pending: Umsóknin þÃn bÃður eftir að starfsfólkið okkar fari yfir hana. Það gæti tekið nokkurn tÃma. Þú munt fá tölvupóst ef umsóknin er samþykkt. redirecting_to: Notandaaðgangurinn þinn er óvirkur vegna þess að hann endurbeinist á %{acct}. + too_fast: Innfyllingarform sent inn of hratt, prófaðu aftur. trouble_logging_in: Vandræði við að skrá inn? + use_security_key: Nota öryggislykil authorize_follow: already_following: Þú ert að þegar fylgjast með þessum aðgangi already_requested: Þú ert þegar búin/n að senda fylgjendabeiðni á þennan notanda @@ -732,6 +791,7 @@ is: date: formats: default: "%d. %b, %Y" + with_month_name: "%d. %B, %Y" datetime: distance_in_words: about_x_hours: "%{count}kl." @@ -796,6 +856,7 @@ is: request: Biddu um safnskrána þÃna size: Stærð blocks: Þú útilokar + bookmarks: Bókamerki csv: CSV domain_blocks: Útilokanir á lénum lists: Listar @@ -863,6 +924,8 @@ is: status: Staða sannvottunar view_proof: Skoða sönnun imports: + errors: + over_rows_processing_limit: inniheldur meira en %{count} raðir modes: merge: Sameina merge_long: Halda fyrirliggjandi færslum og bæta við nýjum @@ -872,6 +935,7 @@ is: success: Það tókst að senda inn gögnin þÃn og verður unnið með þau þegar færi gefst types: blocking: Listi yfir útilokanir + bookmarks: Bókamerki domain_blocking: Listi yfir útilokanir léna following: Listi yfir þá sem fylgst er með muting: Listi yfir þagganir @@ -992,6 +1056,14 @@ is: quadrillion: qi. thousand: þús trillion: tr. + otp_authentication: + code_hint: Settu inn kóðann sem auðkenningarforritið útbjó til staðfestingar + description_html: Ef þú virkjar <strong>tveggja-þátta auðkenningu</strong> með auðkenningarforriti, mun innskráning krefjast þess að þú hafir sÃmann þinn við hendina, með honum þarf að útbúa öryggisteikn sem þú þarft að setja inn. + enable: Virkja + instructions_html: "<strong>Skannaðu þennar QR-kóða inn à Google Authenticator eða álÃka TOTP-forrit á sÃmanum þÃnum</strong>. Héðan à frá mun það forrit útbúa teikn sem þú verður að setja inn til að geta skráð þig inn." + manual_instructions: 'Ef þú getur ekki skannað QR-kóðann og verður að setja hann inn handvirkt, þá er hér leyniorðið á textaformi:' + setup: Setja upp + wrong_code: Kóðinn sem þú settir inn er ógildur! Eru klukkur netþjónsins og tækisins réttar? pagination: newer: Nýrra next: Næsta @@ -1020,6 +1092,7 @@ is: relationships: activity: Virkni aðgangs dormant: Sofandi + follow_selected_followers: Fylgjast með völdum fylgjendum followers: Fylgjendur following: Fylgist með invited: Boðið @@ -1115,7 +1188,8 @@ is: preferences: Kjörstillingar profile: Notandasnið relationships: Fylgist með og fylgjendur - two_factor_authentication: Teggja-þátta auðkenning + two_factor_authentication: Tveggja-þátta auðkenning + webauthn_authentication: Öryggislyklar spam_check: spam_detected: Þetta er sjálfvirk kæra. Ruslpóstur hefur fundist. statuses: @@ -1154,6 +1228,8 @@ is: other: "%{count} atkvæði" vote: Greiða atkvæði show_more: Sýna meira + show_newer: Sýna nýrri + show_older: Sýna eldri show_thread: Birta þráð sign_in_to_participate: Skráðu þig inn til að taka þátt à samtalinu title: "%{name}: „%{quote}‟" @@ -1262,21 +1338,20 @@ is: default: "%d. %b, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Settu inn kóðann sem auðkenningarforritið útbjó til staðfestingar - description_html: Ef þú virkjar <strong>tvÃþátta auðkenningu</strong> mun innskráning krefjast þess að þú hafir sÃmann þinn við hendina, með honum þarf að útbúa öryggisteikn sem þú þarft að setja inn. + add: Bæta við disable: Gera óvirkt - enable: Virkja + disabled_success: Það tókst að gera tveggja-þátta auðkenningu óvirka + edit: Breyta enabled: Tveggja-þátta auðkenning er virk enabled_success: Það tókst að virkja tveggja-þátta auðkenningu generate_recovery_codes: Útbúa endurheimtukóða - instructions_html: "<strong>Skannaðu þennar QR-kóða inn à Google Authenticator eða álÃka TOTP-forrit á sÃmanum þÃnum</strong>. Héðan à frá mun það forrit útbúa teikn sem þú verður að setja inn til að geta skráð þig inn." lost_recovery_codes: Endurheimtukóðar gera þér kleift að fá aftur samband við notandaaðganginn þinn ef þú tapar sÃmanum þÃnum. Ef þú aftur hefur tapað endurheimtukóðunum, geturðu endurgert þá hér. Gömlu endurheimtukóðarnir verða þá ógiltir. - manual_instructions: 'Ef þú getur ekki skannað QR-kóðann og verður að setja hann inn handvirkt, þá er hér leyniorðið á textaformi:' + methods: Tveggja-þátta auðkenningaraðferðir + otp: Auðkenningarforrit recovery_codes: Kóðar fyrir endurheimtingu öryggisafrits recovery_codes_regenerated: Það tókst að endurgera endurheimtukóða recovery_instructions_html: Ef þú tapar sÃmanum þÃnum geturðu notað einn af endurheimtukóðunum hér fyrir neðan til að fá aftur samband við notandaaðganginn þinn. <strong>Geymdu endurheimtukóðana á öruggum stað</strong>. Sem dæmi gætirðu prentað þá út og geymt með öðrum mikilvægum skjölum. - setup: Setja upp - wrong_code: Kóðinn sem þú settir inn er ógildur! Eru klukkur netþjónsins og tækisins réttar? + webauthn: Öryggislyklar user_mailer: backup_ready: explanation: Þú baðst um fullt öryggisafrit af Mastodon notandaaðgangnum þÃnum. Það er núna tilbúið til niðurhals! @@ -1291,6 +1366,7 @@ is: warning: explanation: disable: à meðan aðgangurinn þinn er frystur, eru gögn aðgangsins ósnert, en þú getur ekki framkvæmt neinar aðgerðir fyrr en honum hefur verið aflæst. + sensitive: Innsent myndefni sem þú sendir inn og tengt myndefni verður farið með sem viðkvæmt efni. silence: à meðan aðgangurinn þinn er takmarkaður, mun aðeins fólk sem þegar fylgist með þér sjá tÃstin þÃn á þessum vefþjóni, auk þess sem lokað gæti verið á þig á ýmsum opinberum listum. Aftur á móti geta aðrir gerst fylgjendur þÃnir handvirkt. suspend: Aðgangurinn þinn hefur verið settur à biðstöðu, öll þÃn tÃst og innsent myndefni hafa verið óafturkræft fjarlægð af þessum vefþjóni, sem og af þeim vefþjónum þar sem þú áttir þér fylgjendur. get_in_touch: Þú getur svarað þessum tölvupósti til að setja þig à samband við umsjónarmenn %{instance}. @@ -1299,11 +1375,13 @@ is: subject: disable: Notandaaðgangurinn þinn %{acct} hefur verið frystur none: Aðvörun fyrir %{acct} + sensitive: Myndefni sent frá %{acct} aðgangnum þÃnum hefur verið merkt sem viðkvæmt silence: Notandaaðgangurinn þinn %{acct} hefur verið takmarkaður suspend: Notandaaðgangurinn þinn %{acct} hefur verið settur à bið title: disable: Notandaaðgangur frystur none: Aðvörun + sensitive: Myndefnið þitt hefur verið merkt sem viðkvæmt silence: Notandaaðgangur takmarkaður suspend: Notandaaðgangur à bið welcome: @@ -1324,9 +1402,11 @@ is: tips: Ãbendingar title: Velkomin/n um borð, %{name}! users: + blocked_email_provider: Þessi tölvupóstþjónusta er ekki leyfileg follow_limit_reached: Þú getur ekki fylgst með fleiri en %{limit} aðilum generic_access_help_html: Vandamál við að tengjast aðgangnum þÃnum? Þú getur sett þig à samband við %{email} til að fá aðstoð invalid_email: Tölvupóstfangið er ógilt + invalid_email_mx: Tölvupóstfangið virðist ekki vera til invalid_otp_token: Ógildur tveggja-þátta kóði invalid_sign_in_token: Ógildur öryggiskóði otp_lost_help_html: Ef þú hefur misst aðganginn að hvoru tveggja, geturðu sett þig à samband við %{email} @@ -1336,3 +1416,20 @@ is: verification: explanation_html: 'Þú getur <strong>vottað að þú sért eigandi og ábyrgur fyrir tenglunum à lýsigögnum notandasniðsins þÃns</strong>. Til að það virki, þurfa vefsvæðin sem vÃsað er à að innihalda tengil til baka à Mastodon-notandasniðið. Tengillinn sem vÃsar til baka <strong>verður</strong> að vera með <code>rel="me"</code> eigindi. Textinn à tenglinum skiptir ekki máli. Hérna er dæmi:' verification: Sannprófun + webauthn_credentials: + add: Bæta við nýjum öryggislykli + create: + error: Það kom upp villa við að bæta við öryggislyklinum þÃnum. Reyndu aftur. + success: Tókst að bæta við öryggislyklinum þÃnum. + delete: Eyða + delete_confirmation: Ertu viss um að þú viljir eyða þessum öryggislykli? + description_html: Ef þú virkjar <strong>auðkenningu með öryggislykli</strong> mun innskráning krefjast þess að þú einn af öryggislyklunum þÃnum. + destroy: + error: Það kom upp villa við að eyða öryggislyklinum þÃnum. Reyndu aftur. + success: Tókst að eyða öryggislyklinum þÃnum. + invalid_credential: Ógildur öryggislykill + nickname_hint: Settu inn stuttnefni fyrir nýja öryggislykilinn þinn + not_enabled: Þú hefur ennþá ekki virkjað WebAuthn + not_supported: Þessi vafri styður ekki öryggislykla + otp_required: Til að nota öryggislykla skaltu fyrst virkja tveggja-þátta auðkenningu. + registered_on: Nýskráður %{date} diff --git a/config/locales/it.yml b/config/locales/it.yml index 30c7e3c66f09bdef9066ea57fc5bf679d65ac8b4..1e0ab42f09a26bcb4998cce9199a8b45f45ae852 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -60,6 +60,7 @@ it: one: Seguace other: Seguaci following: Segui + instance_actor_flash: Questo account è un attore virtuale usato per rappresentare il server stesso e non un singolo utente. Viene utilizzato per scopi federativi e non dovrebbe essere sospeso. joined: Dal %{date} last_active: ultima attività link_verified_on: La proprietà di questo link è stata controllata il %{date} @@ -98,6 +99,7 @@ it: add_email_domain_block: Inserisci il dominio email nella blacklist approve: Approva approve_all: Approva tutto + approved_msg: Richiesta di registrazione di %{username} approvata are_you_sure: Sei sicuro? avatar: Immagine di profilo by_domain: Dominio @@ -111,8 +113,10 @@ it: confirm: Conferma confirmed: Confermato confirming: Confermando + delete: Elimina dati deleted: Cancellato demote: Declassa + destroyed_msg: I dati di %{username} sono ora in coda per essere eliminati tra poco disable: Disabilita disable_two_factor_authentication: Disabilita l'autenticazione a due fattori disabled: Disabilitato @@ -123,10 +127,12 @@ it: email_status: Stato email enable: Abilita enabled: Abilitato + enabled_msg: L'account di %{username} è stato scongelato followers: Follower follows: Segue header: Intestazione inbox_url: URL inbox + invite_request_text: Motivi per l'iscrizione invited_by: Invitato da ip: IP joined: Iscritto da @@ -138,6 +144,8 @@ it: login_status: Stato login media_attachments: Media allegati memorialize: Trasforma in memoriam + memorialized: Memorializzato + memorialized_msg: Hai trasformato %{username} in un account commemorativo moderation: active: Attivo all: Tutto @@ -158,10 +166,14 @@ it: public: Pubblico push_subscription_expires: Sottoscrizione PuSH scaduta redownload: Aggiorna avatar + redownloaded_msg: Il profilo di %{username} è stato aggiornato dall'origine reject: Rifiuta reject_all: Rifiuta tutto + rejected_msg: Richiesta di registrazione di %{username} rifiutata remove_avatar: Rimuovi avatar remove_header: Rimuovi intestazione + removed_avatar_msg: Immagine dell'avatar di %{username} eliminata + removed_header_msg: Immagine di intestazione di %{username} eliminata resend_confirmation: already_confirmed: Questo utente è già confermato send: Reinvia email di conferma @@ -178,6 +190,8 @@ it: search: Cerca search_same_email_domain: Altri utenti con lo stesso dominio e-mail search_same_ip: Altri utenti con lo stesso IP + sensitive: Sensibile + sensitized: contrassegnato come sensibile shared_inbox_url: URL Inbox Condiviso show: created_reports: Rapporti creati da questo account @@ -187,13 +201,19 @@ it: statuses: Stati subscribe: Sottoscrivi suspended: Sospeso + suspension_irreversible: I dati di questo account sono stati cancellati in modo irreversibile. È possibile annullare la sospensione dell'account per renderlo utilizzabile, ma non recupererà alcuno dei dati precedenti. + suspension_reversible_hint_html: L'account è stato sospeso e i dati saranno completamente eliminati il %{date}. Fino ad allora, l'account può essere ripristinato senza effetti negativi. Se si desidera eliminare immediatamente tutti i dati dell'account, è possibile farlo qui sotto. time_in_queue: Attesa in coda %{time} title: Account unconfirmed_email: Email non confermata + undo_sensitized: Annulla sensibile undo_silenced: Rimuovi silenzia undo_suspension: Rimuovi sospensione + unsilenced_msg: Sono stati tolti i limiti dell'account di %{username} unsubscribe: Annulla l'iscrizione + unsuspended_msg: È stata eliminata la sospensione dell'account di %{username} username: Nome utente + view_domain: Visualizza riepilogo per dominio warn: Avverti web: Web whitelisted: Nella whitelist @@ -208,12 +228,14 @@ it: create_domain_allow: Crea permesso di dominio create_domain_block: Crea blocco di dominio create_email_domain_block: Crea blocco dominio e-mail + create_ip_block: Crea regola IP demote_user: Degrada l'utente destroy_announcement: Cancella annuncio destroy_custom_emoji: Cancella emoji personalizzata destroy_domain_allow: Cancella permesso di dominio destroy_domain_block: Cancella blocco di dominio destroy_email_domain_block: Cancella blocco dominio e-mail + destroy_ip_block: Elimina regola IP destroy_status: Cancella stato disable_2fa_user: Disabilita l'autenticazione a due fattori disable_custom_emoji: Disabilita emoji personalizzata @@ -226,13 +248,16 @@ it: reopen_report: Riapri report reset_password_user: Reimposta password resolve_report: Risolvi report + sensitive_account: Contrassegna il media nel tuo profilo come sensibile silence_account: Silenzia account suspend_account: Sospendi account unassigned_report: Disassegna report + unsensitive_account: Deseleziona il media nel tuo profilo come sensibile unsilence_account: De-silenzia account unsuspend_account: Annulla la sospensione dell'account update_announcement: Aggiorna annuncio update_custom_emoji: Aggiorna emoji personalizzata + update_domain_block: Aggiorna blocco di dominio update_status: Aggiorna stato actions: assigned_to_self_report: "%{name} ha assegnato il rapporto %{target} a se stesso" @@ -244,12 +269,14 @@ it: create_domain_allow: "%{name} ha messo il dominio %{target} nella whitelist" create_domain_block: "%{name} ha bloccato il dominio %{target}" create_email_domain_block: "%{name} ha messo il dominio email %{target} nella blacklist" + create_ip_block: "%{name} ha creato la regola per l'IP %{target}" demote_user: "%{name} ha degradato l'utente %{target}" destroy_announcement: "%{name} ha eliminato l'annuncio %{target}" destroy_custom_emoji: "%{name} ha distrutto l'emoji %{target}" destroy_domain_allow: "%{name} ha tolto il dominio %{target} dalla whitelist" destroy_domain_block: "%{name} ha sbloccato il dominio %{target}" destroy_email_domain_block: "%{name}ha messo il dominio email %{target} nella whitelist" + destroy_ip_block: "%{name} ha eliminato la regola per l'IP %{target}" destroy_status: "%{name} ha eliminato lo status di %{target}" disable_2fa_user: "%{name} ha disabilitato l'obbligo dei due fattori per l'utente %{target}" disable_custom_emoji: "%{name} ha disabilitato l'emoji %{target}" @@ -262,13 +289,16 @@ it: reopen_report: "%{name} ha riaperto il rapporto %{target}" reset_password_user: "%{name} ha reimpostato la password dell'utente %{target}" resolve_report: "%{name} ha risolto il rapporto %{target}" + sensitive_account: "%{name} ha contrassegnato il media di %{target} come sensibile" silence_account: "%{name} ha silenziato l'account di %{target}" suspend_account: "%{name} ha sospeso l'account di %{target}" unassigned_report: "%{name} report non assegnato %{target}" + unsensitive_account: "%{name} ha deselezionato il media di %{target} come sensibile" unsilence_account: "%{name} ha de-silenziato l'account di %{target}" unsuspend_account: "%{name} ha annullato la sospensione dell'account di %{target}" update_announcement: "%{name} ha aggiornato l'annuncio %{target}" update_custom_emoji: "%{name} ha aggiornato l'emoji %{target}" + update_domain_block: "%{name} ha aggiornato il blocco di dominio per %{target}" update_status: "%{name} stato aggiornato da %{target}" deleted_status: "(stato cancellato)" empty: Nessun log trovato. @@ -372,6 +402,8 @@ it: silence: Silenzia suspend: Sospendi title: Nuovo blocco dominio + obfuscate: Nascondi nome di dominio + obfuscate_hint: Nascondere parzialmente il nome di dominio, se è abilitata la visualizzazione pubblica dell'elenco delle limitazioni di dominio private_comment: Commento privato private_comment_hint: Commento su questa limitazione di dominio per uso interno da parte dei moderatori. public_comment: Commento pubblico @@ -411,6 +443,7 @@ it: instances: by_domain: Dominio delivery_available: Distribuzione disponibile + empty: Nessun dominio trovato. known_accounts: one: "%{count} account noto" other: "%{count} account noti" @@ -434,6 +467,21 @@ it: expired: Scaduto title: Filtro title: Inviti + ip_blocks: + add_new: Crea regola + created_msg: Nuova regola IP aggiunta + delete: Elimina + expires_in: + '1209600': 2 settimane + '15778476': 6 mesi + '2629746': 1 mese + '31556952': 1 anno + '86400': 1 giorno + '94670856': 3 anni + new: + title: Crea una nuova regola IP + no_ip_block_selected: Nessuna regola IP è stata modificata poiché nessuna è stata selezionata + title: Regole IP pending_accounts: title: Account in attesa (%{count}) relationships: @@ -473,6 +521,8 @@ it: comment: none: Nessuno created_at: Segnalato + forwarded: Inoltrato + forwarded_to: Inoltrato a %{domain} mark_as_resolved: Segna come risolto mark_as_unresolved: Segna come non risolto notes: @@ -516,6 +566,7 @@ it: domain_blocks_rationale: title: Mostra motivazione enable_bootstrap_timeline_accounts: + desc_html: I nuovi utenti seguiranno automaticamente gli account configurati, in modo che il loro home feed all'inizio non sia vuoto title: Abilita seguiti predefiniti per i nuovi utenti hero: desc_html: Mostrata nella pagina iniziale. Almeno 600x100 px consigliati. Se non impostata, sarà usato il thumbnail del server @@ -542,6 +593,9 @@ it: min_invite_role: disabled: Nessuno title: Permetti inviti da + require_invite_text: + desc_html: Quando le iscrizioni richiedono l'approvazione manuale, rendere la richiesta “Perché si desidera iscriversi?†obbligatoria invece che opzionale + title: Richiedi ai nuovi utenti di rispondere alla richiesta di motivazione per l'iscrizione registrations_mode: modes: approved: Approvazione richiesta per le iscrizioni @@ -683,8 +737,11 @@ it: prefix_sign_up: Iscriviti oggi a Mastodon! suffix: Con un account, sarai in grado di seguire le persone, pubblicare aggiornamenti e scambiare messaggi con gli utenti da qualsiasi server di Mastodon e altro ancora! didnt_get_confirmation: Non hai ricevuto le istruzioni di conferma? + dont_have_your_security_key: Non hai la tua chiave di sicurezza? forgot_password: Hai dimenticato la tua password? invalid_reset_password_token: Il token di reimpostazione della password non è valido o è scaduto. Per favore richiedine uno nuovo. + link_to_otp: Inserisci un codice a due fattori dal tuo telefono o un codice di recupero + link_to_webauth: Usa il tuo dispositivo chiave di sicurezza login: Entra logout: Esci da Mastodon migrate_account: Sposta ad un account differente @@ -709,7 +766,9 @@ it: functional: Il tuo account è pienamente operativo. pending: La tua richiesta è in attesa di esame da parte del nostro staff. Potrebbe richiedere un po' di tempo. Riceverai una e-mail se la richiesta è approvata. redirecting_to: Il tuo account è inattivo perché attualmente reindirizza a %{acct}. + too_fast: Modulo inviato troppo velocemente, riprova. trouble_logging_in: Problemi di accesso? + use_security_key: Usa la chiave di sicurezza authorize_follow: already_following: Stai già seguendo questo account already_requested: Hai già mandato una richiesta di seguire questo account @@ -734,6 +793,7 @@ it: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count} ore" @@ -798,6 +858,7 @@ it: request: Chiedi il tuo archivio size: Dimensioni blocks: Stai bloccando + bookmarks: Segnalibri csv: CSV domain_blocks: Blocchi di dominio lists: Liste @@ -865,6 +926,8 @@ it: status: Stato della verifica view_proof: Vedi prova imports: + errors: + over_rows_processing_limit: contiene più di %{count} righe modes: merge: Fondi merge_long: Mantieni record esistenti e aggiungine di nuovi @@ -874,6 +937,7 @@ it: success: Le tue impostazioni sono state importate correttamente e verranno applicate in breve tempo types: blocking: Lista dei bloccati + bookmarks: Segnalibri domain_blocking: Lista dei domini bloccati following: Lista dei seguiti muting: Lista dei silenziati @@ -994,6 +1058,14 @@ it: quadrillion: P thousand: k trillion: T + otp_authentication: + code_hint: Inserisci il codice generato dall'app di autenticazione per confermare + description_html: Se abiliti <strong>l'autenticazione a due fattori</strong> utilizzando un'app di autenticazione, per accedere sarà necessario essere in possesso del telefono, che genererà dei codici per l'accesso. + enable: Abilita + instructions_html: "<strong>Scansiona questo codice QR in Google Authenticator o in un'applicazione TOTP simile sul tuo telefono</strong>. D'ora in poi, quell'app genererà i codici che dovrai inserire quando accedi." + manual_instructions: 'Se non riesci a scansionare il codice QR e hai bisogno di inserirlo manualmente, questo è il codice segreto in chiaro:' + setup: Configura + wrong_code: Il codice inserito non è valido! Controlla che l'ora del server e l'ora del dispositivo siano esatte. pagination: newer: Più recente next: Avanti @@ -1022,6 +1094,7 @@ it: relationships: activity: Attività dell'account dormant: Dormiente + follow_selected_followers: Segui i seguaci selezionati followers: Seguaci following: Seguiti invited: Invitato @@ -1118,6 +1191,7 @@ it: profile: Profilo relationships: Follows e followers two_factor_authentication: Autenticazione a due fattori + webauthn_authentication: Chiavi di sicurezza spam_check: spam_detected: Questo è un rapporto automatico. È stato rilevato dello spam. statuses: @@ -1156,6 +1230,8 @@ it: other: "%{count} voti" vote: Vota show_more: Mostra di più + show_newer: Mostra più nuovi + show_older: Mostra più vecchi show_thread: Mostra thread sign_in_to_participate: Accedi per partecipare alla conversazione title: '%{name}: "%{quote}"' @@ -1267,21 +1343,20 @@ it: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Inserisci il codice generato dalla tua app di autenticazione - description_html: Se abiliti <strong>l'autorizzazione a due fattori</strong>, entrare nel tuo account ti richiederà di avere vicino il tuo telefono, il quale ti genererà un codice per eseguire l'accesso. + add: Aggiungi disable: Disabilita - enable: Abilita + disabled_success: Autenticazione a due fattori disattivata + edit: Modifica enabled: È abilitata l'autenticazione a due fattori enabled_success: Autenticazione a due fattori attivata con successo generate_recovery_codes: Genera codici di recupero - instructions_html: "<strong>Scannerizza questo QR code con Google Authenticator o un'app TOTP simile sul tuo telefono</strong>. Da ora in poi, quell'applicazione genererà codici da inserire necessariamente per eseguire l'accesso." lost_recovery_codes: I codici di recupero ti permettono di accedere al tuo account se perdi il telefono. Se hai perso i tuoi codici di recupero, puoi rigenerarli qui. Quelli vecchi saranno annullati. - manual_instructions: 'Se non puoi scannerizzare il QR code e hai bisogno di inserirlo manualmente, questo è il codice segreto in chiaro:' + methods: Metodi a due fattori + otp: App di autenticazione recovery_codes: Codici di recupero del backup recovery_codes_regenerated: I codici di recupero sono stati rigenerati recovery_instructions_html: Se perdi il telefono, puoi usare uno dei codici di recupero qui sotto per riottenere l'accesso al tuo account. <strong>Conserva i codici di recupero in un posto sicuro</strong>. Ad esempio puoi stamparli e conservarli insieme ad altri documenti importanti. - setup: Configura - wrong_code: Il codice inserito non è corretto! Assicurati che l'orario del server e l'orario del dispositivo siano corretti. + webauthn: Chiavi di sicurezza user_mailer: backup_ready: explanation: Hai richiesto un backup completo del tuo account Mastodon. È pronto per essere scaricato! @@ -1296,6 +1371,7 @@ it: warning: explanation: disable: Mentre il tuo account è congelato, i tuoi dati dell'account rimangono intatti, ma non potrai eseguire nessuna azione fintanto che non viene sbloccato. + sensitive: I tuoi file multimediali caricati e multimedia collegati saranno trattati come sensibili. silence: Mentre il tuo account è limitato, solo le persone che già ti seguono possono vedere i tuoi toot su questo server, e potresti essere escluso da vari elenchi pubblici. Comunque, altri possono manualmente seguirti. suspend: Il tuo account è stato sospeso, e tutti i tuoi toot ed i tuoi file media caricati sono stati irreversibilmente rimossi da questo server, e dai server dove avevi dei seguaci. get_in_touch: Puoi rispondere a questa email per entrare in contatto con lo staff di %{instance}. @@ -1304,11 +1380,13 @@ it: subject: disable: Il tuo account %{acct} è stato congelato none: Avviso per %{acct} + sensitive: Il multimedia in pubblicazione del tuo profilo %{acct} è stato contrassegnato come sensibile silence: Il tuo account %{acct} è stato limitato suspend: Il tuo account %{acct} è stato sospeso title: disable: Account congelato none: Avviso + sensitive: Il tuo multimedia è stato contrassegnato come sensibile silence: Account limitato suspend: Account sospeso welcome: @@ -1329,9 +1407,11 @@ it: tips: Suggerimenti title: Benvenuto a bordo, %{name}! users: + blocked_email_provider: Questo provider di posta non è consentito follow_limit_reached: Non puoi seguire più di %{limit} persone generic_access_help_html: Problemi nell'accesso al tuo account? Puoi contattare %{email} per assistenza invalid_email: L'indirizzo email inserito non è valido + invalid_email_mx: L'indirizzo e-mail non sembra esistere invalid_otp_token: Codice d'accesso non valido invalid_sign_in_token: Codice di sicurezza non valido otp_lost_help_html: Se perdessi l'accesso ad entrambi, puoi entrare in contatto con %{email} @@ -1341,3 +1421,20 @@ it: verification: explanation_html: 'Puoi <strong>certificare te stesso come proprietario dei link nei metadati del tuo profilo</strong>. Per farlo, il sito a cui punta il link deve contenere un link che punta al tuo profilo Mastodon. Il link di ritorno <strong>deve</strong> avere l''attributo <code>rel="me"</code>. Il testo del link non ha importanza. Ecco un esempio:' verification: Verifica + webauthn_credentials: + add: Aggiungi una nuova chiave di sicurezza + create: + error: Si è verificato un problema durante l'aggiunta della chiave di sicurezza. Dovresti riprovare. + success: La chiave di sicurezza è stata aggiunta. + delete: Cancella + delete_confirmation: Sei sicuro di voler cancellare questa chiave di sicurezza? + description_html: Se abiliti <strong>l'autenticazione con chiave di sicurezza</strong>, per accedere sarà necessario utilizzare una delle tue chiavi di sicurezza. + destroy: + error: Si è verificato un problema durante la cancellazione della chiave di sicurezza. Dovresti riprovare. + success: La chiave di sicurezza è stata cancellata. + invalid_credential: Chiave di sicurezza non valida + nickname_hint: Inserisci il soprannome della tua nuova chiave di sicurezza + not_enabled: Non hai ancora abilitato WebAuthn + not_supported: Questo browser non supporta le chiavi di sicurezza + otp_required: Per utilizzare le chiavi di sicurezza, prima abilita l'autenticazione a due fattori. + registered_on: Registrato il %{date} diff --git a/config/locales/ja.yml b/config/locales/ja.yml index fb6255546776a958d6a417f58dcd95b20f5f3cec..1b5eeec8d20eb77e02a4ac6bd95d426a8c86d090 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -21,7 +21,9 @@ ja: federation_hint_html: "%{instance} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã²ã¨ã¤ã§ã©ã‚“ãªMastodon互æ›ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚‚フォãƒãƒ¼ã§ãã‚‹ã§ã—ょã†ã€‚" get_apps: モãƒã‚¤ãƒ«ã‚¢ãƒ—リを試㙠hosted_on: Mastodon hosted on %{domain} - instance_actor_flash: ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ã‚µãƒ¼ãƒãƒ¼ãã®ã‚‚ã®ã‚’示ã™ä»®æƒ³çš„ãªã‚‚ã®ã§ã€ç‰¹å®šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’示ã™ã‚‚ã®ã§ã¯ã‚りã¾ã›ã‚“。ã“れã¯ã‚µãƒ¼ãƒãƒ¼ã®é€£åˆã®ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚サーãƒãƒ¼å…¨ä½“をブãƒãƒƒã‚¯ã™ã‚‹ã¨ãã¯ã€ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ブãƒãƒƒã‚¯ã›ãšã«ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ãƒ–ãƒãƒƒã‚¯ã‚’使用ã—ã¦ãã ã•ã„。 + instance_actor_flash: 'ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ã‚µãƒ¼ãƒãƒ¼ãã®ã‚‚ã®ã‚’示ã™ä»®æƒ³çš„ãªã‚‚ã®ã§ã€ç‰¹å®šã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’示ã™ã‚‚ã®ã§ã¯ã‚りã¾ã›ã‚“。ã“れã¯ã‚µãƒ¼ãƒãƒ¼ã®é€£åˆã®ãŸã‚ã«ä½¿ç”¨ã•れã¾ã™ã€‚サーãƒãƒ¼å…¨ä½“をブãƒãƒƒã‚¯ã™ã‚‹ã¨ãã¯ã€ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ブãƒãƒƒã‚¯ã›ãšã«ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ãƒ–ãƒãƒƒã‚¯ã‚’使用ã—ã¦ãã ã•ã„。 + +' learn_more: ã‚‚ã£ã¨è©³ã—ã privacy_policy: プライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ see_whats_happening: やりã¨ã‚Šã‚’見ã¦ã¿ã‚‹ @@ -55,6 +57,7 @@ ja: followers: other: フォãƒãƒ¯ãƒ¼ following: フォãƒãƒ¼ä¸ + instance_actor_flash: ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ã€å€‹ã€…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã¯ãªãã€ã‚µãƒ¼ãƒãƒ¼è‡ªä½“を表ã™ãŸã‚ã«ä½¿ç”¨ã•れる仮想ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã™ã€‚ 連åˆã®ãŸã‚ã«ä½¿ç”¨ã•れるãŸã‚ã€åœæ¢ã—ãªã„ã§ä¸‹ã•ã„。 joined: "%{date} ã«ç™»éŒ²" last_active: æœ€å¾Œã®æ´»å‹• link_verified_on: ã“ã®ãƒªãƒ³ã‚¯ã®æ‰€æœ‰æ¨©ã¯ %{date} ã«ç¢ºèªã•れã¾ã—㟠@@ -92,6 +95,7 @@ ja: add_email_domain_block: メールドメインブãƒãƒƒã‚¯ã«è¿½åŠ approve: æ‰¿èª approve_all: ã™ã¹ã¦æ‰¿èª + approved_msg: "%{username} ã®ç™»éŒ²ç”³è«‹ã‚’承èªã—ã¾ã—ãŸ" are_you_sure: 本当ã«å®Ÿè¡Œã—ã¾ã™ã‹ï¼Ÿ avatar: アイコン by_domain: ドメイン @@ -105,8 +109,10 @@ ja: confirm: ç¢ºèª confirmed: ç¢ºèªæ¸ˆã¿ confirming: 確èªä¸ + delete: データを削除ã™ã‚‹ deleted: 削除済㿠demote: 陿 ¼ + destroyed_msg: "%{username} ã®ãƒ‡ãƒ¼ã‚¿ã¯å®Œå…¨ã«å‰Šé™¤ã•れるよã†ç™»éŒ²ã•れã¾ã—ãŸ" disable: 無効化 disable_two_factor_authentication: 二段階èªè¨¼ã‚’無効ã«ã™ã‚‹ disabled: 無効 @@ -117,10 +123,12 @@ ja: email_status: メールアドレスã®çŠ¶æ…‹ enable: 有効化 enabled: 有効 + enabled_msg: "%{username} ã®ç„¡åŠ¹åŒ–ã‚’è§£é™¤ã—ã¾ã—ãŸ" followers: フォãƒãƒ¯ãƒ¼æ•° follows: フォãƒãƒ¼æ•° header: ヘッダー inbox_url: Inbox URL + invite_request_text: æ„æ°—込㿠invited_by: 招待ã—ãŸäºº ip: IP joined: 登録日 @@ -132,6 +140,8 @@ ja: login_status: ãƒã‚°ã‚¤ãƒ³ media_attachments: 添付ã•れãŸãƒ¡ãƒ‡ã‚£ã‚¢ memorialize: 追悼アカウント化 + memorialized: 追悼化済㿠+ memorialized_msg: "%{username} を追悼アカウント化ã—ã¾ã—ãŸ" moderation: active: アクティブ all: ã™ã¹ã¦ @@ -152,10 +162,14 @@ ja: public: パブリック push_subscription_expires: PuSHè³¼èªæœŸé™ redownload: プãƒãƒ•ィールを更新 + redownloaded_msg: "%{username} ã®ãƒ—ãƒãƒ•ィールをæ£å¸¸ã«æ›´æ–°ã—ã¾ã—ãŸ" reject: å´ä¸‹ reject_all: ã™ã¹ã¦å´ä¸‹ + rejected_msg: "%{username} ã®ç™»éŒ²ç”³è«‹ã‚’å´ä¸‹ã—ã¾ã—ãŸ" remove_avatar: アイコンを削除 remove_header: ヘッダーを削除 + removed_avatar_msg: "%{username} ã®ã‚¢ãƒã‚¿ãƒ¼ç”»åƒã‚’削除ã—ã¾ã—ãŸ" + removed_header_msg: "%{username} ã®ãƒ˜ãƒƒãƒ€ãƒ¼ç”»åƒã‚’削除ã—ã¾ã—ãŸ" resend_confirmation: already_confirmed: メールアドレスã¯ç¢ºèªæ¸ˆã¿ã§ã™ send: 確èªãƒ¡ãƒ¼ãƒ«ã‚’å†é€ @@ -172,6 +186,8 @@ ja: search: 検索 search_same_email_domain: åŒã˜ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’使用ã—ã¦ã„るユーザー search_same_ip: åŒã˜ IP ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’検索 + sensitive: é–²è¦§æ³¨æ„ + sensitized: é–²è¦§æ³¨æ„æ¸ˆã¿ shared_inbox_url: Shared inbox URL show: created_reports: ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ä½œã‚‰ã‚ŒãŸé€šå ± @@ -181,13 +197,19 @@ ja: statuses: トゥート数 subscribe: è³¼èªã™ã‚‹ suspended: åœæ¢æ¸ˆã¿ + suspension_irreversible: ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‡ãƒ¼ã‚¿ã¯å‰Šé™¤ã•ã‚Œå…ƒã«æˆ»ã›ãªããªã‚Šã¾ã™ã€‚後日アカウントã®å‡çµã‚’解除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ãŒãƒ‡ãƒ¼ã‚¿ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。 + suspension_reversible_hint_html: アカウントã¯åœæ¢ã•れã¦ãŠã‚Šã€ãƒ‡ãƒ¼ã‚¿ã¯ %{date} ã«å®Œå…¨ã«å‰Šé™¤ã•れã¾ã™ã€‚ãれã¾ã§ã¯ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’å…ƒã«æˆ»ã™ã“ã¨ãŒã§ãã¾ã™ã€‚今ã™ã完全ã«å‰Šé™¤ã—ãŸã„å ´åˆã¯ä»¥ä¸‹ã‹ã‚‰è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚ time_in_queue: "%{time} å¾…ã¡" title: アカウント unconfirmed_email: 確èªå¾…ã¡ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ + undo_sensitized: 閲覧注æ„ã‹ã‚‰æˆ»ã™ undo_silenced: サイレンスã‹ã‚‰æˆ»ã™ undo_suspension: åœæ¢ã‹ã‚‰æˆ»ã™ + unsilenced_msg: "%{username} ã®ã‚µã‚¤ãƒ¬ãƒ³ã‚¹è§£é™¤ã«æˆåŠŸã—ã¾ã—ãŸ" unsubscribe: è³¼èªã®è§£é™¤ + unsuspended_msg: "%{username} ã®ç„¡åŠ¹åŒ–ã‚’è§£é™¤ã—ã¾ã—ãŸ" username: ユーザーå + view_domain: ãƒ‰ãƒ¡ã‚¤ãƒ³ã®æ¦‚è¦ã‚’表示 warn: è¦å‘Š web: Web whitelisted: 連åˆè¨±å¯æ¸ˆã¿ @@ -202,31 +224,36 @@ ja: create_domain_allow: 連åˆã‚’è¨±å¯ create_domain_block: ドメインブãƒãƒƒã‚¯ã‚’ä½œæˆ create_email_domain_block: メールドメインブãƒãƒƒã‚¯ã‚’ä½œæˆ + create_ip_block: IPãƒ«ãƒ¼ãƒ«ã‚’ä½œæˆ demote_user: ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’é™æ ¼ destroy_announcement: ãŠçŸ¥ã‚‰ã›ã‚’削除 destroy_custom_emoji: カスタム絵文å—を削除 destroy_domain_allow: 連åˆè¨±å¯ã‚’外㙠destroy_domain_block: ドメインブãƒãƒƒã‚¯ã‚’削除 destroy_email_domain_block: メールドメインブãƒãƒƒã‚¯ã‚’削除 + destroy_ip_block: IPルールを削除 destroy_status: トゥートを削除 disable_2fa_user: 二段階èªè¨¼ã‚’無効化 disable_custom_emoji: カスタム絵文å—を無効化 disable_user: ユーザーを無効化 enable_custom_emoji: カスタム絵文å—を有効化 enable_user: ユーザーを有効化 - memorialize_account: 追悼アカウント + memorialize_account: 追悼アカウント化 promote_user: ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’æ˜‡æ ¼ remove_avatar_user: アイコンを削除 reopen_report: é€šå ±ã‚’å†åº¦é–‹ã reset_password_user: パスワードをリセット resolve_report: é€šå ±ã‚’è§£æ±ºæ¸ˆã¿ã«ã™ã‚‹ + sensitive_account: アカウントã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’閲覧注æ„ã«ãƒžãƒ¼ã‚¯ silence_account: アカウントをサイレンス suspend_account: ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’åœæ¢ unassigned_report: é€šå ±ã®æ‹…当を解除 + unsensitive_account: アカウントã®ãƒ¡ãƒ‡ã‚£ã‚¢ã®é–²è¦§æ³¨æ„マークを解除 unsilence_account: アカウントã®ã‚µã‚¤ãƒ¬ãƒ³ã‚¹ã‚’解除 unsuspend_account: アカウントã®åœæ¢ã‚’解除 update_announcement: ãŠçŸ¥ã‚‰ã›ã‚’æ›´æ–° update_custom_emoji: カスタム絵文å—ã‚’æ›´æ–° + update_domain_block: ドメインブãƒãƒƒã‚¯ã‚’æ›´æ–° update_status: トゥートを更新 actions: assigned_to_self_report: "%{name} ã•ã‚“ãŒé€šå ± %{target} ã‚’è‡ªèº«ã®æ‹…当ã«å‰²ã‚Šå½“ã¦ã¾ã—ãŸ" @@ -238,12 +265,14 @@ ja: create_domain_allow: "%{name} ã•ん㌠%{target} ã®é€£åˆã‚’許å¯ã—ã¾ã—ãŸ" create_domain_block: "%{name} ã•ã‚“ãŒãƒ‰ãƒ¡ã‚¤ãƒ³ %{target} をブãƒãƒƒã‚¯ã—ã¾ã—ãŸ" create_email_domain_block: "%{name} ã•ん㌠%{target} をメールドメインブãƒãƒƒã‚¯ã«è¿½åŠ ã—ã¾ã—ãŸ" + create_ip_block: "%{name} ã•ん㌠IP %{target} ã®ãƒ«ãƒ¼ãƒ«ã‚’作æˆã—ã¾ã—ãŸ" demote_user: "%{name} ã•ん㌠%{target} ã•ã‚“ã‚’é™æ ¼ã—ã¾ã—ãŸ" destroy_announcement: "%{name} ã•ã‚“ãŒãŠçŸ¥ã‚‰ã› %{target} を削除ã—ã¾ã—ãŸ" destroy_custom_emoji: "%{name} ã•ã‚“ãŒã‚«ã‚¹ã‚¿ãƒ çµµæ–‡å— %{target} を削除ã—ã¾ã—ãŸ" destroy_domain_allow: "%{name} ã•ん㌠%{target} ã®é€£åˆè¨±å¯ã‚’外ã—ã¾ã—ãŸ" destroy_domain_block: "%{name} ã•ã‚“ãŒãƒ‰ãƒ¡ã‚¤ãƒ³ %{target} ã®ãƒ–ãƒãƒƒã‚¯ã‚’外ã—ã¾ã—ãŸ" destroy_email_domain_block: "%{name} ã•ん㌠%{target} をメールドメインブãƒãƒƒã‚¯ã‹ã‚‰å¤–ã—ã¾ã—ãŸ" + destroy_ip_block: "%{name} ã•ん㌠IP %{target} ã®ãƒ«ãƒ¼ãƒ«ã‚’削除ã—ã¾ã—ãŸ" destroy_status: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ãƒˆã‚¥ãƒ¼ãƒˆã‚’削除ã—ã¾ã—ãŸ" disable_2fa_user: "%{name} ã•ん㌠%{target} ã•ã‚“ã®äºŒæ®µéšŽèªè¨¼ã‚’無効化ã—ã¾ã—ãŸ" disable_custom_emoji: "%{name} ã•ã‚“ãŒã‚«ã‚¹ã‚¿ãƒ çµµæ–‡å— %{target} を無効化ã—ã¾ã—ãŸ" @@ -256,13 +285,16 @@ ja: reopen_report: "%{name} ã•ã‚“ãŒé€šå ± %{target} ã‚’å†ã³é–‹ãã¾ã—ãŸ" reset_password_user: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ãƒ‘スワードをリセットã—ã¾ã—ãŸ" resolve_report: "%{name} ã•ã‚“ãŒé€šå ± %{target} を解決済ã¿ã«ã—ã¾ã—ãŸ" + sensitive_account: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’閲覧注æ„ã«ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸ" silence_account: "%{name} ã•ん㌠%{target} ã•んをサイレンスã«ã—ã¾ã—ãŸ" suspend_account: "%{name} ã•ん㌠%{target} ã•ã‚“ã‚’åœæ¢ã—ã¾ã—ãŸ" unassigned_report: "%{name} ã•ã‚“ãŒé€šå ± %{target} ã®æ‹…当を外ã—ã¾ã—ãŸ" + unsensitive_account: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã®é–²è¦§æ³¨æ„を解除ã—ã¾ã—ãŸ" unsilence_account: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ã‚µã‚¤ãƒ¬ãƒ³ã‚¹ã‚’解除ã—ã¾ã—ãŸ" unsuspend_account: "%{name} ã•ん㌠%{target} ã•ã‚“ã®åœæ¢ã‚’解除ã—ã¾ã—ãŸ" update_announcement: "%{name} ã•ã‚“ãŒãŠçŸ¥ã‚‰ã› %{target} ã‚’æ›´æ–°ã—ã¾ã—ãŸ" update_custom_emoji: "%{name} ã•ã‚“ãŒã‚«ã‚¹ã‚¿ãƒ çµµæ–‡å— %{target} ã‚’æ›´æ–°ã—ã¾ã—ãŸ" + update_domain_block: "%{name} ㌠%{target} ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ãƒ–ãƒãƒƒã‚¯ã‚’æ›´æ–°ã—ã¾ã—ãŸ" update_status: "%{name} ã•ん㌠%{target} ã•ã‚“ã®ãƒˆã‚¥ãƒ¼ãƒˆã‚’æ›´æ–°ã—ã¾ã—ãŸ" deleted_status: "(削除済)" empty: ãƒã‚°ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠@@ -366,6 +398,8 @@ ja: silence: サイレンス suspend: åœæ¢ title: æ–°è¦ãƒ‰ãƒ¡ã‚¤ãƒ³ãƒ–ãƒãƒƒã‚¯ + obfuscate: ドメインåã‚’ä¼ã›å—ã«ã™ã‚‹ + obfuscate_hint: ドメインブãƒãƒƒã‚¯ã®ãƒªã‚¹ãƒˆã‚’公開ã—ã¦ã„ã‚‹å ´åˆã€ãƒ‰ãƒ¡ã‚¤ãƒ³åã®ä¸€éƒ¨ã‚’ä¼ã›å—ã«ã—ã¾ã™ private_comment: コメント (éžå…¬é–‹) private_comment_hint: ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯åŒã˜ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿ãƒ¼ã‚‚閲覧ã§ãã¾ã™ã€‚ public_comment: コメント (公開) @@ -404,6 +438,7 @@ ja: instances: by_domain: ドメイン delivery_available: é…é€å¯èƒ½ + empty: ドメインãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ known_accounts: other: 既知ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆæ•° %{count} moderation: @@ -426,6 +461,21 @@ ja: expired: 期é™åˆ‡ã‚Œ title: フィルター title: 招待 + ip_blocks: + add_new: ãƒ«ãƒ¼ãƒ«ã‚’ä½œæˆ + created_msg: IPãƒ«ãƒ¼ãƒ«ã‚’è¿½åŠ ã—ã¾ã—㟠+ delete: 削除 + expires_in: + '1209600': 2週間 + '15778476': 6ヶ月 + '2629746': 1ヶ月 + '31556952': 1å¹´ + '86400': 1æ—¥ + '94670856': 3å¹´ + new: + title: æ–°è¦IPルール + no_ip_block_selected: ä½•ã‚‚é¸æŠžã•れã¦ã„ãªã„ãŸã‚IPルールを変更ã—ã¾ã›ã‚“ã§ã—㟠+ title: IPルール pending_accounts: title: 承èªå¾…ã¡ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ (%{count}) relationships: @@ -463,6 +513,8 @@ ja: comment: none: ãªã— created_at: é€šå ±æ—¥æ™‚ + forwarded: è»¢é€æ¸ˆã¿ + forwarded_to: "%{domain} ã«è»¢é€ã•れã¾ã—ãŸ" mark_as_resolved: 解決済ã¿ã¨ã—ã¦ãƒžãƒ¼ã‚¯ mark_as_unresolved: 未解決ã¨ã—ã¦å†ã³é–‹ã notes: @@ -506,6 +558,7 @@ ja: domain_blocks_rationale: title: コメントを表示 enable_bootstrap_timeline_accounts: + desc_html: æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¨å®šã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’自動的ã«ãƒ•ã‚©ãƒãƒ¼ã—ã¦ã€ãƒ›ãƒ¼ãƒ フィードãŒç©ºã«ãªã‚‰ãªã„よã†ã«ã™ã‚‹ title: æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®è‡ªå‹•フォãƒãƒ¼ã‚’有効ã«ã™ã‚‹ hero: desc_html: フãƒãƒ³ãƒˆãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•れã¾ã™ã€‚サイズã¯600x100px以上推奨ã§ã™ã€‚未è¨å®šã®å ´åˆã€æ¨™æº–ã®ã‚µãƒ ãƒã‚¤ãƒ«ãŒä½¿ç”¨ã•れã¾ã™ @@ -532,6 +585,9 @@ ja: min_invite_role: disabled: 誰ã«ã‚‚許å¯ã—ãªã„ title: 招待ã®ä½œæˆã‚’è¨±å¯ + require_invite_text: + desc_html: ã‚¢ã‚«ã‚¦ãƒ³ãƒˆç™»éŒ²ãŒæ‰¿èªåˆ¶ã®å ´åˆã€ã€Œæ„æ°—è¾¼ã¿ã‚’ãŠèžã‹ã›ãã ã•ã„ã€ã®ãƒ†ã‚ã‚¹ãƒˆã‚’å¿…é ˆå…¥åŠ›ã«ã™ã‚‹ + title: æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ç™»éŒ²æ™‚ã®ç†ç”±ã‚’å¿…é ˆå…¥åŠ›ã«ã™ã‚‹ registrations_mode: modes: approved: 登録ã«ã¯æ‰¿èªãŒå¿…è¦ @@ -671,8 +727,11 @@ ja: prefix_sign_up: 今ã™ã Mastodon ã‚’å§‹ã‚よã†ï¼ suffix: アカウントãŒã‚れã°ã€ã©ã‚“㪠Mastodon 互æ›ã‚µãƒ¼ãƒãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚‚フォãƒãƒ¼ã—ãŸã‚Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’やりå–りã§ãるよã†ã«ãªã‚Šã¾ã™ï¼ didnt_get_confirmation: 確èªãƒ¡ãƒ¼ãƒ«ã‚’å—ä¿¡ã§ãã¾ã›ã‚“ã‹ï¼Ÿ + dont_have_your_security_key: ã‚»ã‚ュリティã‚ーをæŒã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ forgot_password: パスワードをãŠå¿˜ã‚Œã§ã™ã‹ï¼Ÿ invalid_reset_password_token: ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãƒªã‚»ãƒƒãƒˆãƒˆãƒ¼ã‚¯ãƒ³ãŒæ£ã—ããªã„ã‹æœŸé™åˆ‡ã‚Œã§ã™ã€‚ã‚‚ã†ä¸€åº¦ãƒªã‚¯ã‚¨ã‚¹ãƒˆã—ã¦ãã ã•ã„。 + link_to_otp: æºå¸¯é›»è©±ã‹ã‚‰äºŒæ®µéšŽèªè¨¼ã‚³ãƒ¼ãƒ‰ã‚’入力ã™ã‚‹ã‹ã€ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„ + link_to_webauth: ã‚»ã‚ュリティã‚ーを使用ã™ã‚‹ login: ãƒã‚°ã‚¤ãƒ³ logout: ãƒã‚°ã‚¢ã‚¦ãƒˆ migrate_account: 別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«å¼•ã£è¶Šã™ @@ -697,7 +756,9 @@ ja: functional: アカウントã¯å®Œå…¨ã«æ©Ÿèƒ½ã—ã¦ã„ã¾ã™ã€‚ pending: ã‚ãªãŸã®ç”³è«‹ã¯ç¾åœ¨ã‚µãƒ¼ãƒãƒ¼ç®¡ç†è€…ã«ã‚ˆã‚‹å¯©æŸ»å¾…ã¡ã§ã™ã€‚ã“れã«ã¯ã—ã°ã‚‰ãã‹ã‹ã‚Šã¾ã™ã€‚ç”³è«‹ãŒæ‰¿èªã•れるã¨ãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚ redirecting_to: アカウント㯠%{acct} ã«å¼•ã£è¶Šã—è¨å®šã•れã¦ã„ã‚‹ãŸã‚éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã«ãªã£ã¦ã„ã¾ã™ã€‚ + too_fast: フォームã®é€ä¿¡ãŒé€Ÿã™ãŽã¾ã™ã€‚ã‚‚ã†ä¸€åº¦ã‚„り直ã—ã¦ãã ã•ã„。 trouble_logging_in: ãƒã‚°ã‚¤ãƒ³ã§ãã¾ã›ã‚“ã‹ï¼Ÿ + use_security_key: ã‚»ã‚ュリティã‚ーを使用 authorize_follow: already_following: ã‚ãªãŸã¯æ—¢ã«ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’フォãƒãƒ¼ã—ã¦ã„ã¾ã™ already_requested: æ—¢ã«ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ãƒ•ã‚©ãƒãƒ¼ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡ã—ã¦ã„ã¾ã™ @@ -722,6 +783,7 @@ ja: date: formats: default: "%Yå¹´%m月%dæ—¥" + with_month_name: "%Yå¹´%m月%dæ—¥" datetime: distance_in_words: about_x_hours: "%{count}時間" @@ -786,6 +848,7 @@ ja: request: アーカイブをリクエスト size: å®¹é‡ blocks: ブãƒãƒƒã‚¯ + bookmarks: ブックマーク csv: CSV domain_blocks: éžè¡¨ç¤ºã«ã—ãŸãƒ‰ãƒ¡ã‚¤ãƒ³ lists: リスト @@ -852,6 +915,8 @@ ja: status: èªè¨¼çŠ¶æ…‹ view_proof: 証明を表示 imports: + errors: + over_rows_processing_limit: "%{count} 行以上" modes: merge: çµ±åˆ merge_long: ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ä¿æŒã—ãŸã¾ã¾æ–°ã—ã„ã‚‚ã®ã‚’è¿½åŠ ã—ã¾ã™ @@ -861,6 +926,7 @@ ja: success: ãƒ•ã‚¡ã‚¤ãƒ«ã¯æ£å¸¸ã«ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã•れã€ç¾åœ¨å‡¦ç†ä¸ã§ã™ã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ç¢ºèªã—ã¦ãã ã•ã„ types: blocking: ブãƒãƒƒã‚¯ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒªã‚¹ãƒˆ + bookmarks: ブックマーク domain_blocking: éžè¡¨ç¤ºã«ã—ãŸãƒ‰ãƒ¡ã‚¤ãƒ³ãƒªã‚¹ãƒˆ following: フォãƒãƒ¼ä¸ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒªã‚¹ãƒˆ muting: ミュートã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒªã‚¹ãƒˆ @@ -978,6 +1044,14 @@ ja: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: 続行ã™ã‚‹ã«ã¯èªè¨¼ã‚¢ãƒ—リã§è¡¨ç¤ºã•れãŸã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„ + description_html: "<strong>二è¦ç´ èªè¨¼</strong>を有効ã«ã™ã‚‹ã¨ã€ãƒã‚°ã‚¤ãƒ³æ™‚ã«èªè¨¼ã‚¢ãƒ—リã‹ã‚‰ã‚³ãƒ¼ãƒ‰ã‚’入力ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" + enable: 有効化 + instructions_html: "<strong>Google Authenticatorã‹ã€ã‚‚ã—ãã¯ã»ã‹ã®TOTPアプリã§ã“ã®QRコードをスã‚ャンã—ã¦ãã ã•ã„。</strong>ã“れ以é™ã€ãƒã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãã¯ãã®ã‚¢ãƒ—リã§ç”Ÿæˆã•れるコードãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚" + manual_instructions: 'QRコードãŒã‚¹ã‚ャンã§ããšã€æ‰‹å‹•ã§ã®ç™»éŒ²ã‚’希望ã®å ´åˆã¯ã“ã®ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã‚³ãƒ¼ãƒ‰ã‚’利用ã—ã¦ãã ã•ã„。:' + setup: セットアップ + wrong_code: コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚サーãƒãƒ¼ã¨ãƒ‡ãƒã‚¤ã‚¹ã®æ™‚計ã«ãšã‚ŒãŒã‚ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。 pagination: newer: æ–°ã—ã„トゥート next: 次 @@ -1006,6 +1080,7 @@ ja: relationships: activity: 活動 dormant: éžã‚¢ã‚¯ãƒ†ã‚£ãƒ– + follow_selected_followers: é¸æŠžã—ãŸãƒ•ã‚©ãƒãƒ¯ãƒ¼ã‚’フォãƒãƒ¼ followers: フォãƒãƒ¯ãƒ¼ following: フォãƒãƒ¼ä¸ invited: 招待済㿠@@ -1102,6 +1177,7 @@ ja: profile: プãƒãƒ•ィール relationships: フォãƒãƒ¼ãƒ»ãƒ•ã‚©ãƒãƒ¯ãƒ¼ two_factor_authentication: 二段階èªè¨¼ + webauthn_authentication: ã‚»ã‚ュリティã‚ー spam_check: spam_detected: ã“れã¯è‡ªå‹•çš„ã«ä½œæˆã•れãŸé€šå ±ã§ã™ã€‚ã‚¹ãƒ‘ãƒ ãŒæ¤œå‡ºã•れã¦ã„ã¾ã™ã€‚ statuses: @@ -1134,6 +1210,8 @@ ja: other: "%{count}票" vote: 投票 show_more: ã‚‚ã£ã¨è¦‹ã‚‹ + show_newer: æ–°ã—ã„ã‚‚ã®ã‹ã‚‰è¡¨ç¤º + show_older: å¤ã„ã‚‚ã®ã‹ã‚‰è¡¨ç¤º show_thread: スレッドを表示 sign_in_to_participate: ãƒã‚°ã‚¤ãƒ³ã—ã¦ä¼šè©±ã«å‚åŠ title: '%{name}: "%{quote}"' @@ -1242,21 +1320,20 @@ ja: default: "%Yå¹´%m月%dæ—¥ %H:%M" month: "%Yå¹´ %b" two_factor_authentication: - code_hint: 続行ã™ã‚‹ã«ã¯èªè¨¼ã‚¢ãƒ—リã§è¡¨ç¤ºã•れãŸã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„ - description_html: "<strong>二段階èªè¨¼</strong>を有効ã«ã™ã‚‹ã¨ãƒã‚°ã‚¤ãƒ³æ™‚ã€èªè¨¼ã‚¢ãƒ—リã‹ã‚‰ã‚³ãƒ¼ãƒ‰ã‚’入力ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" + add: è¿½åŠ disable: 無効化 - enable: 有効 + disabled_success: 二段階èªè¨¼ãŒç„¡åйã«ãªã‚Šã¾ã—㟠+ edit: 編集 enabled: 二段階èªè¨¼ã¯æœ‰åйã«ãªã£ã¦ã„ã¾ã™ enabled_success: 二段階èªè¨¼ãŒæœ‰åйã«ãªã‚Šã¾ã—㟠generate_recovery_codes: リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’ç”Ÿæˆ - instructions_html: "<strong>Google Authenticatorã‹ã€ã‚‚ã—ãã¯ã»ã‹ã®TOTPアプリã§ã“ã®QRコードをスã‚ャンã—ã¦ãã ã•ã„。</strong>ã“れ以é™ã€ãƒã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãã¯ãã®ã‚¢ãƒ—リã§ç”Ÿæˆã•れるコードãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚" lost_recovery_codes: リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’使用ã™ã‚‹ã¨æºå¸¯é›»è©±ã‚’紛失ã—ãŸå ´åˆã§ã‚‚アカウントã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’紛失ã—ãŸå ´åˆã‚‚ã“ã“ã§å†ç”Ÿæˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€å¤ã„リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã¯ç„¡åйã«ãªã‚Šã¾ã™ã€‚ - manual_instructions: 'QRコードãŒã‚¹ã‚ャンã§ããšã€æ‰‹å‹•ã§ã®ç™»éŒ²ã‚’希望ã®å ´åˆã¯ã“ã®ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã‚³ãƒ¼ãƒ‰ã‚’利用ã—ã¦ãã ã•ã„。:' + methods: æ–¹å¼ + otp: èªè¨¼ã‚¢ãƒ—リ recovery_codes: リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ recovery_codes_regenerated: リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ãŒå†ç”Ÿæˆã•れã¾ã—㟠recovery_instructions_html: æºå¸¯é›»è©±ã‚’紛失ã—ãŸå ´åˆã€ä»¥ä¸‹ã®å†…ã©ã‚Œã‹ã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’使用ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚<strong>リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã¯å¤§åˆ‡ã«ä¿å…¨ã—ã¦ãã ã•ã„。</strong>ãŸã¨ãˆã°å°åˆ·ã—ã¦ã»ã‹ã®é‡è¦ãªæ›¸é¡žã¨ä¸€ç·’ã«ä¿ç®¡ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ - setup: åˆæœŸè¨å®š - wrong_code: コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚サーãƒãƒ¼ä¸Šã®æ™‚é–“ã¨ãƒ‡ãƒã‚¤ã‚¹ä¸Šã®æ™‚é–“ãŒä¸€è‡´ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ + webauthn: ã‚»ã‚ュリティã‚ー user_mailer: backup_ready: explanation: Mastodonアカウントã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã‚’å—ã‘付ã‘ã¾ã—ãŸã€‚今ã™ãダウンãƒãƒ¼ãƒ‰ã§ãã¾ã™ï¼ @@ -1270,20 +1347,23 @@ ja: title: ãƒã‚°ã‚¤ãƒ³ã‚’検出ã—ã¾ã—㟠warning: explanation: - disable: アカウントãŒå‡çµã•れã¦ã„ã‚‹é–“ã€ãƒ‡ãƒ¼ã‚¿ã¯ãã®ã¾ã¾æ®‹ã‚Šã¾ã™ãŒã€å‡çµãŒè§£é™¤ã•れるã¾ã§ã¯ä½•ã®æ“作もã§ãã¾ã›ã‚“。 - silence: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯åˆ¶é™ã•れã¦ã„ã¾ã™ãŒã€ã‚ãªãŸã‚’フォãƒãƒ¼ã—ã¦ã„るユーザーã®ã¿ã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ä¸Šã®æŠ•稿を見るã“ã¨ãŒã§ãã¾ã™ã€‚ãã—ã¦ã‚ãªãŸã¯æ§˜ã€…ãªå…¬é–‹ãƒªã‚¹ãƒˆã‹ã‚‰é™¤å¤–ã•れるã‹ã‚‚ã—れã¾ã›ã‚“。ãŸã ã—ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ‰‹å‹•ã§ã‚ãªãŸã‚’フォãƒãƒ¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ - suspend: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯åœæ¢ã•れã¦ã„ã¾ã™ã€‚ã‚ãªãŸã®æŠ•稿ã¨ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã•れãŸãƒ¡ãƒ‡ã‚£ã‚¢ãƒ•ァイルã¯ã€ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¨ã‚ãªãŸã®ãƒ•ã‚©ãƒãƒ¯ãƒ¼ãŒå‚åŠ ã—ã¦ã„ãŸã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰å®Œå…¨ã«å‰Šé™¤ã•れã¾ã—ãŸã€‚ + disable: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ãƒã‚°ã‚¤ãƒ³ãŒç¦æ¢ã•れ使用ã§ããªããªã‚Šã¾ã—ãŸã€‚ã—ã‹ã—アカウントã®ãƒ‡ãƒ¼ã‚¿ã¯ãã®ã¾ã¾æ®‹ã£ã¦ã„ã¾ã™ã€‚ + sensitive: ã‚ãªãŸã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã—ãŸãƒ¡ãƒ‡ã‚£ã‚¢ãƒ•ァイルã¨ãƒªãƒ³ã‚¯å…ˆã®ãƒ¡ãƒ‡ã‚£ã‚¢ã¯ã€é–²è¦§æ³¨æ„ã¨ã—ã¦æ‰±ã‚れã¾ã™ã€‚ + silence: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯åˆ¶é™ã•れã¾ã—ãŸãŒãã®ã¾ã¾ä½¿ç”¨ã§ãã¾ã™ã€‚ãŸã ã—æ—¢ã«ãƒ•ã‚©ãƒãƒ¼ã—ã¦ã„る人ã¯ã‚ãªãŸã®ãƒˆã‚¥ãƒ¼ãƒˆã‚’見るã“ã¨ãŒã§ãã¾ã™ãŒã€æ§˜ã€…ãªå…¬é–‹ã‚¿ã‚¤ãƒ ラインã«ã¯è¡¨ç¤ºã•れãªã„å ´åˆãŒã‚りã¾ã™ã€‚ã¾ãŸä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ä»Šå¾Œã‚‚手動ã§ã‚ãªãŸã‚’フォãƒãƒ¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + suspend: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ä½¿ç”¨ã§ããªããªã‚Šãƒ—ãƒãƒ•ィールやãã®ä»–データã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã‚Šã¾ã—ãŸã€‚アカウントãŒå®Œå…¨ã«å‰Šé™¤ã•れるã¾ã§ã¯ãƒã‚°ã‚¤ãƒ³ã—ã¦ãƒ‡ãƒ¼ã‚¿ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’リクエストã§ãã¾ã™ã€‚è¨¼æ‹ éš æ»…ã‚’é˜²ããŸã‚一部ã®ãƒ‡ãƒ¼ã‚¿ã¯å‰Šé™¤ã•ã‚Œãšæ®‹ã‚Šã¾ã™ã€‚ get_in_touch: ã“ã®ãƒ¡ãƒ¼ãƒ«ã«è¿”ä¿¡ã™ã‚‹ã“ã¨ã§ %{instance} ã®ã‚¹ã‚¿ãƒƒãƒ•ã¨é€£çµ¡ã‚’å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ review_server_policies: サーãƒãƒ¼ã®ãƒãƒªã‚·ãƒ¼ã‚’ç¢ºèª statuses: 'ç‰¹ã«æ¬¡ã®ãƒˆã‚¥ãƒ¼ãƒˆ:' subject: disable: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ %{acct} ã¯å‡çµã•れã¾ã—㟠none: "%{acct} ã«å¯¾ã™ã‚‹è¦å‘Š" + sensitive: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ %{acct} ã®æŠ•ç¨¿ãƒ¡ãƒ‡ã‚£ã‚¢ã¯é–²è¦§æ³¨æ„ã¨ãƒžãƒ¼ã‚¯ã•れã¾ã—㟠silence: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ %{acct} ã¯ã‚µã‚¤ãƒ¬ãƒ³ã‚¹ã«ã•れã¾ã—㟠suspend: ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ %{acct} ã¯åœæ¢ã•れã¾ã—㟠title: disable: アカウントãŒå‡çµã•れã¾ã—㟠none: è¦å‘Š + sensitive: ã‚ãªãŸã®ãƒ¡ãƒ‡ã‚£ã‚¢ãŒé–²è¦§æ³¨æ„ã¨ãƒžãƒ¼ã‚¯ã•れã¾ã—㟠silence: アカウントãŒã‚µã‚¤ãƒ¬ãƒ³ã‚¹ã«ã•れã¾ã—㟠suspend: アカウントãŒåœæ¢ã•れã¾ã—㟠welcome: @@ -1304,9 +1384,11 @@ ja: tips: è±†çŸ¥è˜ title: よã†ã“ãã€%{name}ï¼ users: + blocked_email_provider: ã“ã®ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒãƒã‚¤ãƒ€ã¯è¨±å¯ã•れã¦ã„ã¾ã›ã‚“ follow_limit_reached: ã‚ãªãŸã¯ç¾åœ¨ %{limit} 人以上フォãƒãƒ¼ã§ãã¾ã›ã‚“ generic_access_help_html: アクセスã§ãã¾ã›ã‚“ã‹ï¼Ÿ %{email} ã«å•ã„åˆã‚ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ invalid_email: メールアドレスãŒç„¡åйã§ã™ + invalid_email_mx: メールアドレスãŒå˜åœ¨ã—ãªã„よã†ã§ã™ invalid_otp_token: 二段階èªè¨¼ã‚³ãƒ¼ãƒ‰ãŒé–“é•ã£ã¦ã„ã¾ã™ invalid_sign_in_token: 無効ãªã‚»ã‚ュリティコードã§ã™ otp_lost_help_html: ã©ã¡ã‚‰ã‚‚使用ã§ããªã„å ´åˆã€%{email} ã«é€£çµ¡ã‚’å–ã‚‹ã¨è§£æ±ºã§ãã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“ @@ -1316,3 +1398,20 @@ ja: verification: explanation_html: <strong>プãƒãƒ•ィール内ã®ãƒªãƒ³ã‚¯ã®æ‰€æœ‰è€…ã§ã‚ã‚‹ã“ã¨ã‚’èªè¨¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™</strong>。ãã®ãŸã‚ã«ã¯ãƒªãƒ³ã‚¯ã•れãŸã‚¦ã‚§ãƒ–サイトã«Mastodonプãƒãƒ•ィールã¸ã®ãƒªãƒ³ã‚¯ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚リンクã«ã¯<code>rel="me"</code>属性を<strong>å¿…ãš</strong>与ãˆãªã‘れã°ãªã‚Šã¾ã›ã‚“。リンクã®ãƒ†ã‚ストã«ã¤ã„ã¦ã¯é‡è¦ã§ã¯ã‚りã¾ã›ã‚“。以下ã¯ä¾‹ã§ã™ï¼š verification: èªè¨¼ + webauthn_credentials: + add: ã‚»ã‚ュリティã‚ãƒ¼ã‚’è¿½åŠ + create: + error: ã‚»ã‚ュリティã‚ーã®è¿½åŠ ä¸ã«å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。 + success: ã‚»ã‚ュリティã‚ãƒ¼ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚ + delete: 削除 + delete_confirmation: 本当ã«ã“ã®ã‚»ã‚ュリティã‚ーを削除ã—ã¾ã™ã‹ï¼Ÿ + description_html: "<strong>ã‚»ã‚ュリティã‚ーã«ã‚ˆã‚‹èªè¨¼</strong>を有効ã«ã™ã‚‹ã¨ã€ãƒã‚°ã‚¤ãƒ³æ™‚ã«ã‚»ã‚ュリティã‚ãƒ¼ã‚’è¦æ±‚ã™ã‚‹ã‚ˆã†ã«ã§ãã¾ã™ã€‚" + destroy: + error: ã‚»ã‚ュリティã‚ーã®å‰Šé™¤ä¸ã«å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。 + success: ã‚»ã‚ュリティã‚ーを削除ã—ã¾ã—ãŸã€‚ + invalid_credential: ã‚»ã‚ュリティã‚ーãŒé–“é•ã£ã¦ã„ã¾ã™ + nickname_hint: ã‚»ã‚ュリティã‚ーã®åå‰ã‚’入力ã—ã¦ãã ã•ã„ + not_enabled: ã¾ã ã‚»ã‚ュリティã‚ーを有効ã«ã—ã¦ã„ã¾ã›ã‚“ + not_supported: ã“ã®ãƒ–ラウザã¯ã‚»ã‚ュリティã‚ーã«å¯¾å¿œã—ã¦ã„ãªã„よã†ã§ã™ + otp_required: ã‚»ã‚ュリティã‚ーを使用ã™ã‚‹ã«ã¯ã€ã¾ãšäºŒæ®µéšŽèªè¨¼ã‚’有効ã«ã—ã¦ãã ã•ã„。 + registered_on: "%{date} ã«ç™»éŒ²" diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 3a3a338589534e6be09523afdefe58f51cc6947a..523d2bdd5048562e3763c6989ed3f31674f31295 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -752,21 +752,14 @@ ka: default: მáƒáƒ¡áƒ¢áƒáƒ“áƒáƒœáƒ˜ mastodon-light: მáƒáƒ¡áƒ¢áƒáƒ“áƒáƒœáƒ˜ (ღიáƒ) two_factor_authentication: - code_hint: დáƒáƒ¡áƒáƒ›áƒáƒ¬áƒ›áƒ”ბლáƒáƒ“ შეიყვáƒáƒœáƒ”თ თქვენი áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒ¢áƒáƒ áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ¡áƒ’áƒáƒœ გენერირებული კáƒáƒ“ი - description_html: თუ ჩáƒáƒ თáƒáƒ•თ <strong>მეáƒáƒ ე-ფáƒáƒ¥áƒ¢áƒáƒ ის áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒªáƒ˜áƒáƒ¡</strong>, შესვლისáƒáƒ¡ áƒáƒ£áƒªáƒ˜áƒšáƒ”ბელი იქნებრფლáƒáƒ‘დეთ ტელეფáƒáƒœáƒ¡, რáƒáƒ›áƒ”ლიც დáƒáƒáƒ’ენერირებს შესვლის ტáƒáƒ™áƒ”ნებს. disable: გáƒáƒ—იშვრ- enable: ჩáƒáƒ თვრenabled: მეáƒáƒ ე-ფáƒáƒ¥áƒ¢áƒáƒ ის áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒªáƒ˜áƒ ჩáƒáƒ თულირenabled_success: მეáƒáƒ ე-ფáƒáƒ¥áƒ¢áƒáƒ ის áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒªáƒ˜áƒ წáƒáƒ მáƒáƒ¢áƒ”ბით ჩáƒáƒ˜áƒ თრgenerate_recovery_codes: áƒáƒ¦áƒ“გენის კáƒáƒ“ების გენერáƒáƒªáƒ˜áƒ - instructions_html: "<strong>დáƒáƒáƒ¡áƒ™áƒáƒœáƒ˜áƒ ეთ ეს ქრკáƒáƒ“ი გუგლ áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒ¢áƒáƒ ში áƒáƒœ მსგáƒáƒ•ს ტáƒáƒ¢áƒž áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒáƒ¨áƒ˜ თქვენს ტელეფáƒáƒœáƒ–ე</strong>. áƒáƒ›áƒ˜áƒ”რიდáƒáƒœ, ეს áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ დáƒáƒáƒ’ენერირებს ტáƒáƒ™áƒ”ნებს მáƒáƒ¨áƒ˜áƒœ რáƒáƒ“ესáƒáƒª დáƒáƒ’áƒáƒ˜áƒ დებáƒáƒ— áƒáƒ•ტáƒáƒ იზáƒáƒªáƒ˜áƒ." lost_recovery_codes: áƒáƒ¦áƒ“გენის კáƒáƒ“ები უფლებáƒáƒ¡ გáƒáƒ«áƒšáƒ”ვთ მიიღáƒáƒ— ხელმეáƒáƒ ე წვდáƒáƒ›áƒ თქვენი áƒáƒœáƒ’áƒáƒ იშისáƒáƒ“მი თუ დáƒáƒ™áƒáƒ გáƒáƒ•თ ტელეფáƒáƒœáƒ¡. თუ დáƒáƒ™áƒáƒ გეთ áƒáƒ¦áƒ“გენის კáƒáƒ“ები, მáƒáƒ— რეგენერáƒáƒªáƒ˜áƒ შეგიძლიáƒáƒ— áƒáƒ¥. ძველი áƒáƒ¦áƒ“გენის კáƒáƒ“ები áƒáƒ¦áƒáƒ იქნებრვáƒáƒšáƒ˜áƒ“ური. - manual_instructions: 'თუ ვერáƒáƒ¡áƒ™áƒáƒœáƒ˜áƒ ებთ ქრკáƒáƒ“ს დრსáƒáƒáƒ˜áƒ áƒáƒ”ბთ მის მექáƒáƒœáƒ˜áƒ™áƒ£áƒ რეჟიმში შეყვáƒáƒœáƒáƒ¡, áƒáƒ¥ áƒáƒ ის ჩვეულებრივი ტექსტური სáƒáƒ˜áƒ“უმლáƒ:' recovery_codes: გáƒáƒ£áƒ¬áƒ˜áƒ”თ áƒáƒ¦áƒ“გენის კáƒáƒ“ებს რეზერვáƒáƒªáƒ˜áƒ recovery_codes_regenerated: áƒáƒ¦áƒ’ენის კáƒáƒ“ების რეგენერáƒáƒªáƒ˜áƒ წáƒáƒ მáƒáƒ¢áƒ”ბით შესრულდრrecovery_instructions_html: თუ რáƒáƒ“ესმე დáƒáƒ™áƒáƒ გáƒáƒ•თ წვდáƒáƒ›áƒáƒ¡ თქვენს ტელეფáƒáƒœáƒ—áƒáƒœ, შეგიძლიáƒáƒ— ქვემáƒáƒ— მáƒáƒªáƒ”მული áƒáƒ¦áƒ“გენის კáƒáƒ“ები გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნáƒáƒ—, რáƒáƒ—რმáƒáƒ˜áƒžáƒáƒ•áƒáƒ— ხელმეáƒáƒ ე წვდáƒáƒ›áƒ თქვენი áƒáƒœáƒ’áƒáƒ იშისáƒáƒ“მი. <strong>იქáƒáƒœáƒ˜áƒ”თ áƒáƒ¦áƒ“გენის კáƒáƒ“ები დáƒáƒªáƒ£áƒšáƒáƒ“</strong>. მáƒáƒ’áƒáƒšáƒ˜áƒ—ისთვის, შეგიძლიáƒáƒ— áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— დრშეინáƒáƒ®áƒáƒ— სხვრსáƒáƒ‘უთებთáƒáƒœ ერთáƒáƒ“. - setup: დáƒáƒ§áƒ”ნებრ- wrong_code: შეყვáƒáƒœáƒ˜áƒšáƒ˜ კáƒáƒ“ი áƒáƒ იყრსწáƒáƒ ი! სწáƒáƒ ირსერვერის დრმáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის დრáƒ? user_mailer: backup_ready: explanation: თქვენ მáƒáƒ˜áƒ—ხáƒáƒ•ეთ თქვენი მáƒáƒ¡áƒ¢áƒáƒ“áƒáƒœáƒ˜áƒ¡ áƒáƒœáƒ’áƒáƒ იშის სრული რეზერვáƒáƒªáƒ˜áƒ. ის áƒáƒ®áƒšáƒ უკვე მზáƒáƒ“áƒáƒ გáƒáƒ“მáƒáƒ¡áƒáƒ¬áƒ”რáƒáƒ“! diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 1d34355b3d54c86515f439b95f73461158873e6b..af83d5fc6dc2a4b80b1d1650bc27de822b091d6d 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -35,6 +35,7 @@ kab: domain: Aqeddac reason: TaÉ£zent silenced: 'TisuffÉ£in ara d-yekken seg yiqeddacen-agi ad ttwaffrent deg tsuddmin tizuyaz d yidiwenniten, daÉ£en ur ttilin ara telÉ£a É£ef usedmer n yimseqdacen-nsen, skud ur ten-teá¸fiá¹›eḠara:' + silenced_title: Imeẓla yeggugmen unavailable_content_html: Maá¹£á¹udun s umata yeá¸men-ak ad teẓreḠagbur, ad tesdemreḠakked yimseqdacen-nniá¸en seg yal aqeddac deg fedivers. Ha-tent-an É£ur-k tsuraf i yellan deg uqeddac-agi. user_count_after: one: amseqdac @@ -42,6 +43,7 @@ kab: user_count_before: Amagger n what_is_mastodon: D acu-t Maá¹£á¹udun? accounts: + choices_html: 'Afranen n %{name}:' follow: Ḍfeá¹› followers: one: Umeá¸faá¹› @@ -66,9 +68,12 @@ kab: admin: Anedbal bot: Aá¹›ubut group: Agraw + moderator: Atrar unavailable: Ur nufi ara amaÉ£nu-a unfollow: Ur á¹á¹afaá¹› ara admin: + account_actions: + action: Eg tigawt account_moderation_notes: create: Eǧǧ tazmilt delete: Kkes @@ -88,6 +93,7 @@ kab: confirm: Sentem confirmed: Yettwasentem confirming: Asentem + delete: Kkes isefka deleted: Yettwakkes demote: Sider s weswir disable: Gdel @@ -104,6 +110,8 @@ kab: follows: Yeá¹afaá¹› header: Ixef inbox_url: URL n yinekcam + invite_request_text: Timental n tmerna + invited_by: Inced-it-id ip: Tansa IP joined: Ikcemed deg location: @@ -123,6 +131,7 @@ kab: most_recent_ip: Tansa IP taneggarut no_account_selected: Ula yiwen n umiá¸an ur yettwabeddel acku ula yiwen ur yettwafren no_limits_imposed: War tilisa + not_subscribed: Ur imulteÉ£ ara pending: Ittraǧu acegger perform_full_suspension: Ḥbes di leεá¸il promote: Ali s uswir @@ -132,19 +141,26 @@ kab: reject: Aggi reject_all: Aggi-ten akk remove_avatar: Kkes tugna n umaÉ£nu + remove_header: Kkes tacacit resend_confirmation: already_confirmed: Amseqdac-agi yettwasentem yakan send: Azen tikelt-nniá¸en imayl n usentem success: Imayl n usentem yettwazen mebla ugur! reset: Wennez reset_password: Beddel awal uffir + resubscribe: Ales ajerred role: Tisirag roles: admin: Anedbal + moderator: AseÉ£yad staff: TarbaÉ›t user: Amseqdac search: Nadi search_same_ip: Imseqdacen-nniá¸en s tansa IP am tinn-ik + shared_inbox_url: Bá¸u URL n tbewwaá¸t + show: + created_reports: Eg ineqqisen + targeted_reports: Yettwazen uneqqis sÉ£ur wiyaḠsilence: Sgugem silenced: Yettwasgugem statuses: TisuffÉ£in @@ -160,34 +176,54 @@ kab: whitelisted: Deg tebdert tamellalt action_logs: action_types: + change_email_user: Beddel imayl i useqdac + confirm_user: Sentem aseqdac + create_custom_emoji: Rnu imujit udmawan + create_ip_block: Rnu alugen n IP + destroy_ip_block: Kkes alugen n IP disable_2fa_user: Gdel 2FA + enable_user: Rmed aseqdac remove_avatar_user: Kkes avaá¹ar reset_password_user: Ales awennez n wawal n uffir silence_account: Sgugem amiá¸an + update_domain_block: Leqqem iḥder n taÉ£ult actions: + assigned_to_self_report: "%{name} imudd aneqqis %{target} i yiman-nsen" change_email_user: "%{name} ibeddel imayl n umseqdac %{target}" confirm_user: "%{name} isentem tansa imayl n umseqdac %{target}" create_account_warning: "%{name} yuzen alÉ£u i %{target}" + create_announcement: "%{name} yerna taselÉ£ut tamaynut %{target}" create_custom_emoji: "%{name} yessuli-d imujiten imaynuten %{target}" create_domain_allow: "%{name} yerna taÉ£ult %{target} É£er tebdart tamellalt" create_domain_block: "%{name} yesseḥbes taÉ£ult %{target}" create_email_domain_block: "%{name} yerna taÉ£ult n imayl %{target} É£er tebdart taberkant" + create_ip_block: "%{name} rnu alugen i IP %{target}" + demote_user: "%{name} iá¹£ubb-d deg usellun aseqdac %{target}" + destroy_announcement: "%{name} yekkes taselÉ£ut %{target}" destroy_custom_emoji: "%{name} ihudd imuji %{target}" destroy_domain_allow: "%{name} yekkes taÉ£ult %{target} seg tebdart tamellalt" destroy_domain_block: "%{name} yekkes aseḥbes n taÉ£ult %{target}" destroy_email_domain_block: "%{name} yerna taÉ£ult n imayl %{target} É£er tebdart tamellalt" + destroy_ip_block: "%{name} kkes alugen i IP %{target}" destroy_status: "%{name} yekkes tasuffeÉ£t n %{target}" disable_custom_emoji: "%{name} yessens imuji %{target}" disable_user: "%{name} yessens tuqqna i umseqdac %{target}" enable_custom_emoji: "%{name} yermed imuji %{target}" enable_user: "%{name} yermed tuqqna i umseqdac %{target}" memorialize_account: "%{name} yerra amiá¸an n %{target} d asebter n usmekti" + promote_user: "%{name} yerna deg usellun n useqdac %{target}" + remove_avatar_user: "%{name} yekkes avaá¹ar n %{target}" + reset_password_user: "%{name} iwennez awal uffir n useqdac %{target}" + resolve_report: "%{name} yefra aneqqis %{target}" silence_account: "%{name} yesgugem amiá¸an n %{target}" unsilence_account: "%{name} yekkes asgugem n umiá¸an n %{target}" + update_announcement: "%{name} ileqqem taselÉ£ut %{target}" update_custom_emoji: "%{name} yelqem imuji %{target}" + update_domain_block: "%{name} ileqqem iḥder n taÉ£ult i %{target}" update_status: "%{name} yelqem tasuffeÉ£t n %{target}" deleted_status: "(tasuffeÉ£t tettwakkes)" empty: Ulac iÉ£misen i yellan. + filter_by_user: Sizdeg s useqdac title: AÉ£mis n usenqed announcements: edit: @@ -227,6 +263,7 @@ kab: upload: Sali dashboard: config: Tawila + feature_deletions: Imiá¸an yettwaksen feature_invites: IseÉ£wan n iÉ›aá¹›uá¸en feature_profile_directory: Akaram n imaÉ£nuten feature_registrations: Ajerred @@ -246,6 +283,7 @@ kab: destroyed_msg: Taγult-a tettwakkes seg umuγ amellal undo: Kkes seg tebdart tamellalt domain_blocks: + add_new: Rni iḥder amaynut n taÉ£ult domain: Taγult new: severity: @@ -271,11 +309,13 @@ kab: instances: by_domain: Taγult delivery_available: Yella usiweḠ+ empty: Ulac taÉ£ultin yettwafen. known_accounts: one: "%{count} n umiá¸an i yettwasnen" other: "%{count} n yimiá¸anen i yettwassnen" moderation: all: Akk + limited: Yettwasgugem private_comment: Awennit uslig public_comment: Awennit azayez title: Tamatut @@ -289,8 +329,25 @@ kab: expired: Ifat title: Asizdeg title: IÉ›aruá¸en + ip_blocks: + add_new: Rnu alugen + created_msg: Yettwarna ulugen amaynut n IP akken iwata + delete: Kkes + expires_in: + '1209600': 2 yimalasen + '15778476': 6 wayyuren + '2629746': 1 wayyur + '31556952': 1 useggas + '86400': 1 wass + '94670856': 3 yiseggasen + new: + title: Rnu alugen n IP amaynut + no_ip_block_selected: Ula yiwen n ulugen n IP ur yettwabeddel acku ula yiwen ur yettwafren + title: Ilugan n IP pending_accounts: title: Imiá¸anen yettrajun (%{count}) + relationships: + title: AssaÉ£en n %{acct} relays: add_new: Rnu anmegli amaynut delete: Kkes @@ -310,6 +367,7 @@ kab: reports: one: "%{count} uneqqis" other: "%{count} n ineqqisen" + action_taken_by: Tigawt yettwaá¹á¹fen sÉ£ur are_you_sure: Tetḥaq-eá¸? comment: none: Ula yiwen @@ -367,12 +425,14 @@ kab: name: Ahacá¹ag reviewed: Yettwacegger title: Ihacá¹agen + unique_uses_today: "%{count} i d-yeffen ass-a" title: Tadbelt warning_presets: add_new: Rnu amaynut delete: Kkes admin_mailer: new_report: + body: "%{reporter} yettwazen É£ef %{target}" subject: Aneqqis amaynut i %{instance} (#%{id}) appearance: discovery: Asnirem @@ -385,6 +445,8 @@ kab: view: 'Ẓaá¹›:' view_profile: Ssken-d amaÉ£nu view_status: Ssken-d tasuffiÉ£t + applications: + token_regenerated: Ajuá¹u n unekcum yettusirew i tikkelt-nniá¸en akken iwata auth: apply_for_account: Suter asnebgi change_password: Awal uffir @@ -392,6 +454,7 @@ kab: checkbox_agreement_without_rules_html: Qebleγ <a href="%{terms_path}" target="_blank">tiwtilin n useqdec</a> delete_account: Kkes amiá¸an description: + prefix_invited_by_user: "@%{name} inced-ik·ikem ad ternuḠɣer uqeddac-a n Mastodon!" prefix_sign_up: Zeddi di Maá¹£á¹udun assa! forgot_password: Tettud awal-ik uffir? login: Qqen @@ -402,6 +465,7 @@ kab: cas: CAS saml: SAML register: Jerred + registration_closed: "%{instance} ur yeqbil ara imttekkiyen imaynuten" reset_password: Wennez awal uffir security: Taγellist set_new_password: Egr-d awal uffir amaynut @@ -411,6 +475,7 @@ kab: account_status: Addad n umiá¸an functional: Amiá¸an-inek·m yettwaheyya. trouble_logging_in: Γur-k uguren n tuqqna? + use_security_key: Seqdec tasarut n teÉ£list authorize_follow: already_following: Teá¹afareḠya kan amiá¸an-a follow: Ḍfeá¹› @@ -426,6 +491,7 @@ kab: date: formats: default: "%d %b %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}isr" @@ -442,6 +508,9 @@ kab: x_seconds: "%{count}tas" deletes: proceed: Kkes amiá¸an + warning: + username_available: Isem-ik·im n useqdac ad yuÉ£al yella i tikkelt-nniá¸en + username_unavailable: Isem-ik·im n useqdac ad yeqqim ulac-it directories: directory: Akaram n imaγnuten explore_mastodon: Snirem %{title} @@ -517,6 +586,10 @@ kab: '604800': 1 umalas '86400': 1 wass expires_in_prompt: Werǧin + invited_by: 'TettwaÉ›raá¸eḠs É£ur:' + max_uses: + one: 1 uuseqdec + other: "%{count} yiseqdac" max_uses_prompt: Ulac talast table: expires_at: Ad ifat di @@ -529,36 +602,51 @@ kab: digest: action: Wali akk tilγa mention: 'Yuder-ik-id %{name} deg:' + subject: + one: "1 wulÉ£u seg tirza-inek·inm taneqqarut ar tura \U0001F418" + other: "%{count} ilÉ£a imaynuten seg tirza-nek·inem taneggarut ar tura \U0001F418" + favourite: + subject: "%{name} yesmenyaf addad-ik·im" follow: body: "%{name} yeá¹afaá¹›-ik-id tura!" subject: "%{name} yeá¹afaá¹›-ik-id tura" title: Ameá¸faá¹› amaynut follow_request: + body: "%{name} yessuter-d ad ak·akem-yeá¸fer" title: Asuter amaynut n teá¸feá¹›t mention: action: Err body: 'Yuder-ik·ikem-id %{name} deg:' subject: Yuder-ik·ikem-id %{name} + reblog: + subject: "%{name} yesselha addad-ik·im" notifications: other_settings: Iγewwaá¹›en nniá¸en n tilγa number: human: decimal_units: + format: "%n%u" units: + billion: AṬ million: A + thousand: K trillion: Am + otp_authentication: + enable: Rmed + setup: Sbadu pagination: newer: Amaynut next: Wayed older: Aqbuá¹› prev: Win iÉ›eddan - truncate: d + truncate: "…" preferences: other: WiyaḠrelationships: activity: Armud n umiá¸an followers: Imeá¸faá¹›en following: Yeá¹afaá¹› + invited: Yettwancad last_active: Armud aneggaru most_recent: Melmi kan moved: Igujj @@ -571,6 +659,8 @@ kab: remote_interaction: favourite: proceed: Kemmel asmenyef + reblog: + proceed: Sentem beá¹á¹u reply: proceed: Kemmel tiririt sessions: @@ -605,7 +695,7 @@ kab: firefox_os: Firefox OS ios: iOS linux: Linux - mac: Mac + mac: macOS windows: Windows windows_mobile: Windows Mobile windows_phone: Tiliγri Windows Phone @@ -623,12 +713,17 @@ kab: export: Taktert n yisefka import: Kter import_and_export: Taktert d usifeḠ+ migrate: Tunigin n umiá¸an notifications: Tilγa preferences: Imenyafen profile: Ameγnu relationships: Imeá¸faá¹›en akked wid i teá¹á¹afaá¹›eḠ+ webauthn_authentication: Tisura n teÉ£list statuses: attached: + audio: + one: "%{count} n imesli" + other: "%{count} n imesliyen" image: one: "%{count} tugna" other: "%{count} tugniwin" @@ -641,6 +736,9 @@ kab: total_people: one: "%{count} n wemdan" other: "%{count} n yemdanen" + total_votes: + one: "%{count} n wedÉ£ar" + other: "%{count} n yedÉ£aren" vote: DÉ£eá¹› show_more: Ssken-d ugar show_thread: Ssken-d lxiḠ@@ -666,12 +764,19 @@ kab: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: + add: Rnu disable: Gdel - enable: Rmed + disabled_success: Asesteb s snat n tarrayin yensa akken iwata + edit: Ẓreg + otp: Asnas n usesteb + webauthn: Tisura n teÉ£list user_mailer: warning: title: + disable: Amiá¸an i igersen none: Γur-wat + silence: Amiá¸an yesÉ›a talast + suspend: Amiá¸an yettwaḥebsen welcome: full_handle: Tansa umiá¸an-ik takemmalit review_preferences_action: Beddel imenyafen @@ -682,3 +787,6 @@ kab: signed_in_as: 'TeqqneḠamzun d:' verification: verification: Asenqed + webauthn_credentials: + add: Rnu tasarut n teÉ£list tamaynut + delete: Kkes diff --git a/config/locales/kk.yml b/config/locales/kk.yml index bb7a57e87846166edded5a369bfa51993be2f776..5f0da18883966abe7cffaf94ef5555ae41d48a0d 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -519,6 +519,9 @@ kk: trends: desc_html: Бұрын қараÑтырылған Ñ…Ñштегтерді қазіргі уақытта трендте көпшілікке көрÑету title: Тренд хештегтер + site_uploads: + delete: Жүктелген файлды өшір + destroyed_msg: Жүктелген файл Ñәтті өшірілді! statuses: back_to_account: Ðккаунт бетіне оралы batch: @@ -1166,21 +1169,14 @@ kk: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: РаÑтау үшін түпнұÑқалықты раÑтау бағдарламаÑÑ‹ арқылы жаÑалған кодты енгізіңіз - description_html: "<strong>екі факторлы түпнұÑқалықты раÑтауды</strong> қоÑÑаңыз, кіру үшін Ñізге телефонға кіруіңізді талап етеді, Ñізге арнайы токен беріледі." disable: Ðжырату - enable: ҚоÑу enabled: Екі-факторлы Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ò›Ð¾Ñылған enabled_success: Екі-факторлы Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñәтті қоÑылды generate_recovery_codes: Қалпына келтіру кодтарын жаÑаңыз - instructions_html: "<strong>Мына QR кодты Google Authenticator арқылы Ñкандаңыз немеÑе Ò±Ò›ÑÐ°Ñ TOTP бағдарламалары арқылы</strong>. Одан кейін желіге кіру үшін токендер берілетін болады." lost_recovery_codes: Қалпына келтіру кодтары телефонды жоғалтÑаңыз, тіркелгіңізге қайта кіруге мүмкіндік береді. Қалпына келтіру кодтарын жоғалтÑаңыз, оларды оÑында қалпына келтіре алаÑыз. ЕÑкі қалпына келтіру кодтары жарамÑыз болады. - manual_instructions: 'Егер Ñіз QR-кодты Ñканерлей алмаÑаңыз және оны қолмен енгізуіңіз қажет болÑа, мұнда қарапайым нұÑқаулық:' recovery_codes: Қалпына келтіру кодтарын резервтік көшіру recovery_codes_regenerated: Қалпына келтіру кодтары қалпына келтірілді recovery_instructions_html: Егер Ñіз телефонға кіруді жоғалтÑаңыз, тіркелгіңізге кіру үшін төмендегі қалпына келтіру кодтарының бірін пайдалануға болады. <strong>Қалпына келтіру кодтарын қауіпÑіз Ò±Ñтаңыз </strong>. МыÑалы, оларды баÑып шығарып, оларды баÑқа маңызды құжаттармен Ñақтауға болады. - setup: Орнату - wrong_code: Енгізілген код жарамÑыз! Сервер уақыты мен құрылғының уақыты Ð´Ò±Ñ€Ñ‹Ñ Ð¿Ð°? user_mailer: backup_ready: explanation: Сіз Mastodon аккаунтыңыздың толық мұрағатын Ñұрадыңыз. Қазір жүктеуге дайын! diff --git a/config/locales/kn.yml b/config/locales/kn.yml index 25bee609a2d6fe3611350d41741cbd114fab7442..d44eb868f3955f075ea9cad7dd335042a9b5b0fc 100644 --- a/config/locales/kn.yml +++ b/config/locales/kn.yml @@ -10,11 +10,3 @@ kn: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 1742e5d0870353b1f432ba060e193347973737fe..042660432ee51adfbfd4d173754cfc62f4631a4c 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -57,6 +57,7 @@ ko: followers: other: 팔로워 following: 팔로잉 + instance_actor_flash: ì´ ê³„ì •ì€ ì„œë²„ ìžì‹ ì„ ë‚˜íƒ€ë‚´ê¸° 위한 ê°€ìƒì˜ ê³„ì •ì´ë©° ê°œì¸ ì‚¬ìš©ìžê°€ 아닙니다. ì´ ê³„ì •ì€ ì—°í•©ì„ ìœ„í•´ 사용ë˜ë©° ì •ì§€ë˜ì§€ 않아야 합니다. joined: "%{date}ì— ê°€ìž…í•¨" last_active: 최근 í™œë™ link_verified_on: "%{date}ì— ì´ ë§í¬ì˜ ì†Œìœ ê°€ 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤" @@ -94,6 +95,7 @@ ko: add_email_domain_block: ì´ ì´ë©”ì¼ ë„ë©”ì¸ì„ 차단하기 approve: ìŠ¹ì¸ approve_all: ëª¨ë‘ ìŠ¹ì¸ + approved_msg: 성공ì 으로 %{username}ì˜ ê°€ìž… ì‹ ì²ì„œë¥¼ 승ì¸í–ˆìŠµë‹ˆë‹¤ are_you_sure: ì •ë§ë¡œ ì‹¤í–‰í•˜ì‹œê² ìŠµë‹ˆê¹Œ? avatar: 아바타 by_domain: ë„ë©”ì¸ @@ -107,8 +109,10 @@ ko: confirm: í™•ì¸ confirmed: 확ì¸ë¨ confirming: í™•ì¸ ì¤‘ + delete: ë°ì´í„° ì‚ì œ deleted: ì‚ì œë¨ demote: 강등 + destroyed_msg: "%{username}ì˜ ë°ì´í„°ëŠ” ê³§ ì‚ì œë˜ë„ë¡ íì— ë“¤ì–´ê°”ìŠµë‹ˆë‹¤" disable: 비활성화 disable_two_factor_authentication: 2단계 ì¸ì¦ì„ 비활성화 disabled: ë¹„í™œì„±í™”ëœ @@ -119,10 +123,12 @@ ko: email_status: ì´ë©”ì¼ ìƒíƒœ enable: 활성화 enabled: 활성 + enabled_msg: "%{username}ì˜ ê³„ì •ì„ ì„±ê³µì 으로 얼리기 í•´ì œí•˜ì˜€ìŠµë‹ˆë‹¤" followers: 팔로워 수 follows: 팔로잉 수 header: í—¤ë” inbox_url: ìˆ˜ì‹ í•¨ URL + invite_request_text: 가입 í•˜ë ¤ëŠ” ì´ìœ invited_by: ì´ˆëŒ€ìž ip: IP joined: 가입 @@ -134,6 +140,8 @@ ko: login_status: ë¡œê·¸ì¸ ìƒíƒœ media_attachments: ì²¨ë¶€ëœ ë¯¸ë””ì–´ memorialize: 메모리엄으로 ì „í™˜ + memorialized: 기ë…비화 ë¨ + memorialized_msg: 성공ì 으로 %{username}를 기ë…비 ê³„ì •ìœ¼ë¡œ ì „í™˜í•˜ì˜€ìŠµë‹ˆë‹¤ moderation: active: í™œë™ all: ì „ì²´ @@ -154,13 +162,17 @@ ko: public: ì „ì²´ 공개 push_subscription_expires: PuSH êµ¬ë… ê¸°ê°„ 만료 redownload: 프로필 ì—…ë°ì´íЏ + redownloaded_msg: 성공ì 으로 %{username}ì˜ í”„ë¡œí•„ì„ ì›ë³¸ìœ¼ë¡œë¶€í„° ì—…ë°ì´íЏ 하였습니다 reject: ê±°ë¶€ reject_all: ëª¨ë‘ ê±°ë¶€ + rejected_msg: 성공ì 으로 %{username}ì˜ ê°€ìž… ì‹ ì²ì„œë¥¼ ë°˜ë ¤í•˜ì˜€ìŠµë‹ˆë‹¤ remove_avatar: 아바타 지우기 remove_header: í—¤ë” ì‚ì œ + removed_avatar_msg: 성공ì 으로 %{username}ì˜ ì•„ë°”íƒ€ ì´ë¯¸ì§€ë¥¼ ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤ + removed_header_msg: 성공ì 으로 %{username}ì˜ í—¤ë” ì´ë¯¸ì§€ë¥¼ ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤ resend_confirmation: already_confirmed: ì´ ì‚¬ìš©ìžëŠ” ì´ë¯¸ 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤ - send: 다시 í™•ì¸ ì´ë©”ì¼ + send: í™•ì¸ ë©”ì¼ ë‹¤ì‹œ 보내기 success: í™•ì¸ ì´ë©”ì¼ì´ ì „ì†¡ë˜ì—ˆìŠµë‹ˆë‹¤! reset: 초기화 reset_password: 암호 초기화 @@ -174,6 +186,8 @@ ko: search: 검색 search_same_email_domain: ê°™ì€ ì´ë©”ì¼ ë„ë©”ì¸ì„ 가진 다른 사용ìžë“¤ search_same_ip: ê°™ì€ IPì˜ ë‹¤ë¥¸ 사용ìžë“¤ + sensitive: 민ê°í•¨ + sensitized: 민ê°í•¨ìœ¼ë¡œ ì„¤ì •ë¨ shared_inbox_url: ê³µìœ ëœ inbox URL show: created_reports: ì´ ê³„ì •ì—서 ì œì¶œëœ ì‹ ê³ @@ -183,13 +197,19 @@ ko: statuses: 툿 수 subscribe: 구ë…하기 suspended: ì •ì§€ ë¨ + suspension_irreversible: ì´ ê³„ì •ì˜ ë°ì´í„°ëŠ” ë³µêµ¬í• ìˆ˜ ì—†ë„ë¡ ì‚ì œ ë©ë‹ˆë‹¤. ê³„ì •ì„ ì •ì§€ í•´ì œí•¨ìœ¼ë¡œì„œ ê³„ì •ì„ ë‹¤ì‹œ 사용 가능하게 í• ìˆ˜ 있지만 ì´ì „ì— ì‚ì œí•œ ì–´ë–¤ ë°ì´í„°ë„ 복구ë˜ì§€ 않습니다. + suspension_reversible_hint_html: ê³„ì •ì´ ì •ì§€ë˜ì—ˆìŠµë‹ˆë‹¤, ê·¸ë¦¬ê³ %{date}ì— ë°ì´í„°ê°€ ì™„ì „ížˆ ì‚ì œë 것입니다. ê·¸ 때까지는 ì–´ë–¤ 안 ì¢‹ì€ íš¨ê³¼ ì—†ì´ ê³„ì •ì´ ë³µêµ¬ ë 수 있습니다. 만약 지금 당장 ê³„ì •ì˜ ëª¨ë“ ë°ì´í„°ë¥¼ ì‚ì œí•˜ê³ ì‹¶ë‹¤ë©´, 아래ì—서 í–‰í• ìˆ˜ 있습니다. time_in_queue: "%{time}ë™ì•ˆ 기다림" title: ê³„ì • unconfirmed_email: ë¯¸í™•ì¸ ëœ ì´ë©”ì¼ ì£¼ì†Œ + undo_sensitized: 민ê°í•¨ìœ¼ë¡œ ì„¤ì • 취소 undo_silenced: 침묵 í•´ì œ undo_suspension: ì •ì§€ í•´ì œ + unsilenced_msg: 성공ì 으로 %{username} ê³„ì •ì„ ì œí•œ í•´ì œí–ˆìŠµë‹ˆë‹¤ unsubscribe: êµ¬ë… í•´ì œ + unsuspended_msg: 성공ì 으로 %{username} ê³„ì •ì„ ì •ì§€ í•´ì œí–ˆìŠµë‹ˆë‹¤ username: ì•„ì´ë”” + view_domain: ë„ë©”ì¸ì˜ 요약 보기 warn: ê²½ê³ web: 웹 whitelisted: 허용 ëª©ë¡ @@ -204,12 +224,14 @@ ko: create_domain_allow: ë„ë©”ì¸ í—ˆìš© ìƒì„± create_domain_block: ë„ë©”ì¸ ì°¨ë‹¨ 추가 create_email_domain_block: ì´ë©”ì¼ ë„ë©”ì¸ ì°¨ë‹¨ ìƒì„± + create_ip_block: IP 규칙 만들기 demote_user: ì‚¬ìš©ìž ê°•ë“± destroy_announcement: ê³µì§€ì‚¬í• ì‚ì œ destroy_custom_emoji: 커스텀 ì—모지 ì‚ì œ destroy_domain_allow: ë„ë©”ì¸ í—ˆìš© ì‚ì œ destroy_domain_block: ë„ë©”ì¸ ì°¨ë‹¨ ì‚ì œ destroy_email_domain_block: ì´ë©”ì¼ ë„ë©”ì¸ ì°¨ë‹¨ ì‚ì œ + destroy_ip_block: IP 규칙 ì‚ì œ destroy_status: 게시물 ì‚ì œ disable_2fa_user: 2단계 ì¸ì¦ 비활성화 disable_custom_emoji: 커스텀 ì—모지 비활성화 @@ -222,13 +244,16 @@ ko: reopen_report: ì‹ ê³ ë‹¤ì‹œ 열기 reset_password_user: 암호 ìž¬ì„¤ì • resolve_report: ì‹ ê³ ì²˜ë¦¬ + sensitive_account: ë‹¹ì‹ ì˜ ê³„ì •ì˜ ë¯¸ë””ì–´ë¥¼ 민ê°í•¨ìœ¼ë¡œ 표시 silence_account: ê³„ì • 침묵 suspend_account: ê³„ì • ì •ì§€ unassigned_report: ì‹ ê³ ë§¡ê¸° 취소 + unsensitive_account: ë‹¹ì‹ ì˜ ê³„ì •ì˜ ë¯¸ë””ì–´ë¥¼ 민ê°í•¨ìœ¼ë¡œ 표시하지 ì•ŠìŒ unsilence_account: ê³„ì • 침묵 취소 unsuspend_account: ê³„ì • ì •ì§€ 취소 update_announcement: ê³µì§€ì‚¬í• ì—…ë°ì´íЏ update_custom_emoji: 커스텀 ì—모지 ì—…ë°ì´íЏ + update_domain_block: ë„ë©”ì¸ ì°¨ë‹¨ ê°±ì‹ update_status: 게시물 게시 actions: assigned_to_self_report: "%{name}ì´ ë¦¬í¬íЏ %{target}ì„ ìžì‹ ì—게 í• ë‹¹í–ˆìŠµë‹ˆë‹¤" @@ -237,15 +262,17 @@ ko: create_account_warning: "%{name}ê°€ %{target}ì—게 ê²½ê³ ë³´ëƒ„" create_announcement: "%{name} ë‹˜ì´ ìƒˆ 공지 %{target}ì„ ë§Œë“¤ì—ˆìŠµë‹ˆë‹¤" create_custom_emoji: "%{name}ì´ ìƒˆë¡œìš´ ì—모지 %{target}를 추가했습니다" - create_domain_allow: "%{name} ë‹˜ì´ %{target} ë„ë©”ì¸ì„ í™”ì´íŠ¸ë¦¬ìŠ¤íŠ¸ì— ë„£ì—ˆìŠµë‹ˆë‹¤" + create_domain_allow: "%{name} ë‹˜ì´ %{target} ë„ë©”ì¸ì„ í—ˆìš©ë¦¬ìŠ¤íŠ¸ì— ë„£ì—ˆìŠµë‹ˆë‹¤" create_domain_block: "%{name}ì´ ë„ë©”ì¸ %{target}를 차단했습니다" create_email_domain_block: "%{name}ì´ ì´ë©”ì¼ ë„ë©”ì¸ %{target}를 차단했습니다" + create_ip_block: "%{name} ë‹˜ì´ IP 규칙 %{target}ì„ ë§Œë“¤ì—ˆìŠµë‹ˆë‹¤" demote_user: "%{name}ì´ %{target}ì„ ê°•ë“±í–ˆìŠµë‹ˆë‹¤" destroy_announcement: "%{name} ë‹˜ì´ ê³µì§€ %{target}ì„ ì‚ì œí–ˆìŠµë‹ˆë‹¤" destroy_custom_emoji: "%{name}ì´ %{target} ì—모지를 ì‚ì œí•¨" - destroy_domain_allow: "%{name} ë‹˜ì´ %{target} ë„ë©”ì¸ì„ í™”ì´íŠ¸ë¦¬ìŠ¤íŠ¸ì—서 ì œê±°í•˜ì˜€ìŠµë‹ˆë‹¤" + destroy_domain_allow: "%{name} ë‹˜ì´ %{target} ë„ë©”ì¸ì„ 허용리스트ì—서 ì œê±°í•˜ì˜€ìŠµë‹ˆë‹¤" destroy_domain_block: "%{name}ì´ ë„ë©”ì¸ %{target}ì˜ ì°¨ë‹¨ì„ í•´ì œí–ˆìŠµë‹ˆë‹¤" - destroy_email_domain_block: "%{name}ì´ ì´ë©”ì¼ ë„ë©”ì¸ %{target}ì„ í™”ì´íŠ¸ë¦¬ìŠ¤íŠ¸ì— ë„£ì—ˆìŠµë‹ˆë‹¤" + destroy_email_domain_block: "%{name}ì´ ì´ë©”ì¼ ë„ë©”ì¸ %{target}ì„ í—ˆìš©ë¦¬ìŠ¤íŠ¸ì— ë„£ì—ˆìŠµë‹ˆë‹¤" + destroy_ip_block: "%{name} ë‹˜ì´ IP 규칙 %{target}ì„ ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤" destroy_status: "%{name}ì´ %{target}ì˜ íˆ¿ì„ ì‚ì œí–ˆìŠµë‹ˆë‹¤" disable_2fa_user: "%{name}ì´ %{target}ì˜ 2FA를 비활성화 했습니다" disable_custom_emoji: "%{name}ì´ ì—모지 %{target}를 비활성화 했습니다" @@ -258,13 +285,16 @@ ko: reopen_report: "%{name}ì´ ë¦¬í¬íЏ %{target}ì„ ë‹¤ì‹œ 열었습니다" reset_password_user: "%{name}ì´ %{target}ì˜ ì•”í˜¸ë¥¼ 초기화했습니다" resolve_report: "%{name}ì´ %{target} ì‹ ê³ ë¥¼ 처리ë¨ìœ¼ë¡œ 변경하였습니다" + sensitive_account: "%{name} ë‹˜ì´ %{target}ì˜ ë¯¸ë””ì–´ë¥¼ 민ê°í•¨ìœ¼ë¡œ 표시했습니다" silence_account: "%{name}ì´ %{target}ì˜ ê³„ì •ì„ ì¹¨ë¬µì‹œì¼°ìŠµë‹ˆë‹¤" suspend_account: "%{name}ì´ %{target}ì˜ ê³„ì •ì„ ì •ì§€ì‹œì¼°ìŠµë‹ˆë‹¤" unassigned_report: "%{name}ì´ ë¦¬í¬íЏ %{target}ì„ í• ë‹¹ í•´ì œí–ˆìŠµë‹ˆë‹¤" + unsensitive_account: "%{name} ë‹˜ì´ %{target}ì˜ ë¯¸ë””ì–´ë¥¼ 민ê°í•˜ì§€ 않ìŒìœ¼ë¡œ 표시했습니다" unsilence_account: "%{name}ì´ %{target}ì— ëŒ€í•œ ì¹¨ë¬µì„ í•´ì œí–ˆìŠµë‹ˆë‹¤" unsuspend_account: "%{name}ì´ %{target}ì— ëŒ€í•œ ì •ì§€ë¥¼ í•´ì œí–ˆìŠµë‹ˆë‹¤" update_announcement: "%{name} ë‹˜ì´ ê³µì§€ %{target}ì„ ê°±ì‹ í–ˆìŠµë‹ˆë‹¤" update_custom_emoji: "%{name}ì´ ì—모지 %{target}를 ì—…ë°ì´íЏ 했습니다" + update_domain_block: "%{name} ë‹˜ì´ %{target}ì— ëŒ€í•œ ë„ë©”ì¸ ì°¨ë‹¨ì„ ê°±ì‹ í–ˆìŠµë‹ˆë‹¤" update_status: "%{name}ì´ %{target}ì˜ ìƒíƒœë¥¼ ì—…ë°ì´íЏ 했습니다" deleted_status: "(ì‚ì œë¨)" empty: 로그를 ì°¾ì„ ìˆ˜ 없습니다 @@ -346,9 +376,9 @@ ko: week_interactions: ì´ë²ˆ ì£¼ì˜ ìƒí˜¸ìž‘ìš© week_users_active: ì´ë²ˆ ì£¼ì˜ í™œì„± ì‚¬ìš©ìž week_users_new: ì´ë²ˆ ì£¼ì˜ ì‹ ê·œ ìœ ì € - whitelist_mode: í™”ì´íŠ¸ë¦¬ìŠ¤íŠ¸ 모드 + whitelist_mode: ì œí•œëœ íŽ˜ë”ë ˆì´ì…˜ 모드 domain_allows: - add_new: 허용 ëœ ë„ë©”ì¸ + add_new: ë„ë©”ì¸ í—ˆìš© created_msg: ë„ë©”ì¸ì´ 성공ì 으로 허용 목ë¡ì— 추가ë˜ì—ˆìŠµë‹ˆë‹¤ destroyed_msg: ë„ë©”ì¸ì´ 허용 목ë¡ì—서 ì œê±°ë˜ì—ˆìŠµë‹ˆë‹¤ undo: 허용 목ë¡ì—서 ì œì™¸ @@ -370,6 +400,8 @@ ko: silence: 침묵 suspend: ì •ì§€ title: 새로운 ë„ë©”ì¸ ì°¨ë‹¨ + obfuscate: ë„ë©”ì¸ ì´ë¦„ 난ë…í™” + obfuscate_hint: ë„ë©”ì¸ ì œí•œ 목ë¡ì„ 공개하는 경우 ë„ë©”ì¸ ì´ë¦„ì˜ ì¼ë¶€ë¥¼ 난ë…í™” 합니다 private_comment: 비공개 ì£¼ì„ private_comment_hint: ì´ ë„ë©”ì¸ ì œí•œì— ëŒ€í•œ 주ì„ì€ ì¤‘ìž¬ìžë¥¼ 위해 ë‚´ë¶€ì 으로 사용 ë©ë‹ˆë‹¤. public_comment: 공개 ì£¼ì„ @@ -408,6 +440,7 @@ ko: instances: by_domain: ë„ë©”ì¸ delivery_available: ì „ì†¡ 가능 + empty: ë„ë©”ì¸ì´ í•˜ë‚˜ë„ ì—†ìŠµë‹ˆë‹¤. known_accounts: other: ì•Œë ¤ì§„ ê³„ì • %{count}ê°œ moderation: @@ -430,6 +463,21 @@ ko: expired: ë§Œë£Œë¨ title: í•„í„° title: 초대 + ip_blocks: + add_new: 규칙 만들기 + created_msg: 성공ì 으로 새 IP ê·œì¹™ì„ ë§Œë“¤ì—ˆìŠµë‹ˆë‹¤ + delete: ì‚ì œ + expires_in: + '1209600': 2 주 + '15778476': 6 달 + '2629746': 1 달 + '31556952': 1 ë…„ + '86400': 1 ì¼ + '94670856': 3 ë…„ + new: + title: 새 IP 규칙 만들기 + no_ip_block_selected: 아무 ê²ƒë„ ì„ íƒ ë˜ì§€ 않아 ì–´ë–¤ IP ê·œì¹™ë„ ë³€ê²½ ë˜ì§€ 않았습니다 + title: IP 규칙들 pending_accounts: title: ëŒ€ê¸°ì¤‘ì¸ ê³„ì • (%{count}) relationships: @@ -447,7 +495,7 @@ ko: pending: ë¦´ë ˆì´ì˜ ìŠ¹ì¸ ëŒ€ê¸°ì¤‘ save_and_enable: ì €ìž¥í•˜ê³ í™œì„±í™” setup: ë¦´ë ˆì´ ì—°ê²° ì„¤ì • - signatures_not_enabled: 시í어모드나 í™”ì´íŠ¸ë¦¬ìŠ¤íŠ¸ëª¨ë“œë¥¼ ì‚¬ìš©í•˜ê³ ìžˆë‹¤ë©´ ë¦´ë ˆì´ëŠ” ì œëŒ€ë¡œ ë™ìž‘하지 ì•Šì„ ê²ƒìž…ë‹ˆë‹¤ + signatures_not_enabled: 시í어모드나 ì œí•œëœ íŽ˜ë”ë ˆì´ì…˜ 모드를 ì‚¬ìš©í•˜ê³ ìžˆë‹¤ë©´ ë¦´ë ˆì´ëŠ” ì œëŒ€ë¡œ ë™ìž‘하지 ì•Šì„ ê²ƒìž…ë‹ˆë‹¤ status: ìƒíƒœ title: ë¦´ë ˆì´ report_notes: @@ -467,6 +515,8 @@ ko: comment: none: ì—†ìŒ created_at: 리í¬íЏ ì‹œê° + forwarded: ì „ë‹¬ë¨ + forwarded_to: "%{domain}ì—게 ì „ë‹¬ë¨" mark_as_resolved: í•´ê²° 완료 처리 mark_as_unresolved: 미해결로 표시 notes: @@ -510,6 +560,7 @@ ko: domain_blocks_rationale: title: ì‚¬ìœ ë³´ì—¬ì£¼ê¸° enable_bootstrap_timeline_accounts: + desc_html: 새 사용ìžë“¤ì´ ìžë™ìœ¼ë¡œ ì„¤ì • ëœ ê³„ì •ë“¤ì„ íŒ”ë¡œìš° 하ë„ë¡ í•´ì„œ ê·¸ë“¤ì˜ í™ˆ 피드가 빈 ìƒíƒœë¡œ 시작하지 않ë„ë¡ í•©ë‹ˆë‹¤ title: 새 ìœ ì €ê°€ íŒ”ë¡œìš°í• ê³„ì •ì„ ë³´ì—¬ì£¼ê¸° hero: desc_html: í”„ë¡ íŠ¸íŽ˜ì´ì§€ì— 표시 ë©ë‹ˆë‹¤. 최소 600x100í”½ì…€ì„ ê¶Œìž¥í•©ë‹ˆë‹¤. 만약 ì„¤ì •ë˜ì§€ 않았다면, ì„œë²„ì˜ ì¸ë„¤ì¼ì´ 사용 ë©ë‹ˆë‹¤ @@ -536,6 +587,9 @@ ko: min_invite_role: disabled: ì•„ë¬´ë„ ëª» 하게 title: 초대ë§í¬ë¥¼ 만들 수 있는 권한 + require_invite_text: + desc_html: ê°€ìž…ì´ ìˆ˜ë™ ìŠ¹ì¸ì„ 필요로 í• ë•Œ, "왜 ê°€ìž…í•˜ë ¤ê³ í•˜ë‚˜ìš”?" í•ëª©ì„ ì„ íƒì‚¬í•으로 ë‘는 것보다는 필수로 ë‘는 ê²ƒì´ ë‚«ìŠµë‹ˆë‹¤ + title: 새 사용ìžê°€ 초대 ìš”ì² ê¸€ì„ ìž‘ì„±í•´ì•¼ 하ë„ë¡ registrations_mode: modes: approved: ê°€ìž…í•˜ë ¤ë©´ 승ì¸ì´ 필요함 @@ -675,8 +729,11 @@ ko: prefix_sign_up: ë§ˆìŠ¤í† ëˆì— 가입하세요! suffix: ê³„ì • 하나로 ì‚¬ëžŒë“¤ì„ íŒ”ë¡œìš° í•˜ê³ , ê²Œì‹œë¬¼ì„ ìž‘ì„±í•˜ë©° ë§ˆìŠ¤í† ëˆì„ í¬í•¨í•œ 다른 ì–´ë–¤ ì„œë²„ì˜ ìœ ì €ì™€ë„ ë©”ì‹œì§€ë¥¼ ì£¼ê³ ë°›ì„ ìˆ˜ 있습니다! didnt_get_confirmation: í™•ì¸ ë©”ì¼ì„ 받지 못하셨습니까? + dont_have_your_security_key: 보안 키가 없습니까? forgot_password: 비밀번호를 잊어버리셨습니까? invalid_reset_password_token: 암호 리셋 í† í°ì´ 올바르지 못하거나 ê¸°ê°„ì´ ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤. 다시 ìš”ì²í•´ì£¼ì„¸ìš”. + link_to_otp: 휴대í°ì˜ 2ì°¨ 코드 í˜¹ì€ ë³µêµ¬ 키를 ìž…ë ¥í•´ 주세요 + link_to_webauth: 보안 키 장치 사용 login: ë¡œê·¸ì¸ logout: 로그아웃 migrate_account: ê³„ì • 옮기기 @@ -701,7 +758,9 @@ ko: functional: ê³„ì •ì´ ì™„ë²½ížˆ ìž‘ë™í•©ë‹ˆë‹¤. pending: ë‹¹ì‹ ì˜ ê°€ìž… ì‹ ì²ì€ ìŠ¤íƒœí”„ì˜ ê²€ì‚¬ë¥¼ 위해 대기중입니다. ì´ê²ƒì€ ì‹œê°„ì´ ë‹¤ì†Œ 소요ë©ë‹ˆë‹¤. 가입 ì‹ ì²ì´ ìŠ¹ì¸ ë 경우 ì´ë©”ì¼ì„ 받게 ë©ë‹ˆë‹¤. redirecting_to: ê³„ì •ì´ %{acct}로 리다ì´ë ‰íЏ 중ì´ê¸° ë•Œë¬¸ì— ë¹„í™œì„± ìƒíƒœìž…니다. + too_fast: 너무 ë¹ ë¥´ê²Œ ì–‘ì‹ì´ ì œì¶œë˜ì—ˆìŠµë‹ˆë‹¤, 다시 시ë„하세요. trouble_logging_in: ë¡œê·¸ì¸ í•˜ëŠ”ë° ë¬¸ì œê°€ 있나요? + use_security_key: 보안 키 사용 authorize_follow: already_following: ì´ë¯¸ ì´ ê³„ì •ì„ íŒ”ë¡œìš° í•˜ê³ ìžˆìŠµë‹ˆë‹¤ already_requested: ì´ë¯¸ ì´ ê³„ì •ì—게 팔로우 ìš”ì²ì„ 보냈습니다 @@ -726,6 +785,7 @@ ko: date: formats: default: "%Y-%b-%d" + with_month_name: "%Y-%B-%d" datetime: distance_in_words: about_x_hours: "%{count}시간" @@ -790,6 +850,7 @@ ko: request: ì•„ì¹´ì´ë¸Œ ìš”ì²í•˜ê¸° size: í¬ê¸° blocks: 차단 + bookmarks: 보관함 csv: CSV domain_blocks: ë„ë©”ì¸ ì°¨ë‹¨ lists: 리스트 @@ -856,6 +917,8 @@ ko: status: ì¸ì¦ ìƒíƒœ view_proof: ì¦ëª… 보기 imports: + errors: + over_rows_processing_limit: "%{count}ê°œ ì´ìƒì˜ ì—´ì„ í¬í•¨í•©ë‹ˆë‹¤" modes: merge: 병합 merge_long: 기존 ê²ƒì„ ê·¸ëŒ€ë¡œ ë‘” 채 새로 추가 @@ -865,6 +928,7 @@ ko: success: 파ì¼ì´ ì •ìƒì 으로 업로드 ë˜ì—ˆìœ¼ë©°, 현재 처리 중입니다 types: blocking: 차단한 ê³„ì • ëª©ë¡ + bookmarks: 보관함 domain_blocking: ë„ë©”ì¸ ì°¨ë‹¨ ëª©ë¡ following: 팔로우 ì¤‘ì¸ ê³„ì • ëª©ë¡ muting: 뮤트 ì¤‘ì¸ ê³„ì • ëª©ë¡ @@ -982,6 +1046,14 @@ ko: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: 확ì¸ì„ 위해 ì¸ì¦ ì• í”Œë¦¬ì¼€ì´ì…˜ì— ìƒì„±ëœ 코드를 ìž…ë ¥í•´ 주ì‹ì‹œì˜¤ + description_html: ì¸ì¦ê¸° 앱으로 <strong>2단계 ì¸ì¦</strong>ì„ í™œì„±í™” 하면 ë¡œê·¸ì¸ ì‹œ ìž…ë ¥ í• í† í°ì„ ìƒì„±í•´ 주는 ì „í™”ê¸°ê°€ 필요합니다. + enable: 활성화 + instructions_html: "<strong>Google Authenticator, ë˜ëŠ” 타 TOTP ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 ì´ QR 코드를 스캔해 주ì‹ì‹œì˜¤.</strong> ì´í›„ ë¡œê·¸ì¸ ì‹œì—는 ì´ ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 ìƒì„±ë˜ëŠ” 코드가 필요합니다." + manual_instructions: 'QR 코드를 ìŠ¤ìº”í• ìˆ˜ 없어 수ë™ìœ¼ë¡œ 등ë¡ì„ ì›í•˜ì‹œëŠ” 경우 ì´ ë¹„ë°€ 코드를 사용해 주ì‹ì‹œì˜¤:' + setup: ì„¤ì • + wrong_code: 코드가 올바르지 않습니다! 서버와 íœ´ëŒ€ì „í™” ê°„ì˜ ì‹œê°ì´ ì¼ì¹˜í•˜ë‚˜ìš”? pagination: newer: 새로운 툿 next: ë‹¤ìŒ @@ -1010,6 +1082,7 @@ ko: relationships: activity: ê³„ì • í™œë™ dormant: 휴면 + follow_selected_followers: ì„ íƒí•œ íŒ”ë¡œì›Œë“¤ì„ íŒ”ë¡œìš° followers: 팔로워 following: 팔로잉 invited: ì´ˆëŒ€ë¨ @@ -1048,40 +1121,40 @@ ko: activity: 마지막 í™œë™ browser: 브ë¼ìš°ì € browsers: - alipay: ì•Œë¦¬íŽ˜ì´ - blackberry: ë¸”ëž™ë² ë¦¬ - chrome: í¬ë¡¬ - edge: 엣지 - electron: ì¼ë ‰íŠ¸ë¡ - firefox: 파ì´ì–´í스 + alipay: Alipay + blackberry: Blackberry + chrome: Chrome + edge: Microsoft Edge + electron: Electron + firefox: Firefox generic: 알 수 없는 브ë¼ìš°ì € - ie: IE - micro_messenger: 마ì´í¬ë¡œë©”ì‹ ì € - nokia: 노키아 S40 Ovi 브ë¼ìš°ì € - opera: ì˜¤íŽ˜ë¼ + ie: Internet Explorer + micro_messenger: MicroMessenger + nokia: Nokia S40 Ovi 브ë¼ìš°ì € + opera: Opera otter: Otter phantom_js: PhantomJS qq: QQ 브ë¼ìš°ì € - safari: 사파리 + safari: Safari uc_browser: UC브ë¼ìš°ì € - weibo: 웨ì´ë³´ + weibo: Weibo current_session: 현재 세션 description: "%{platform}ì˜ %{browser}" explanation: ë‚´ ë§ˆìŠ¤í† ëˆ ê³„ì •ì— í˜„ìž¬ ë¡œê·¸ì¸ ì¤‘ì¸ ì›¹ 브ë¼ìš°ì € 목ë¡ìž…니다. ip: IP platforms: - adobe_air: ì–´ë„비 ì—ì–´ - android: 안드로ì´ë“œ - blackberry: ë¸”ëž™ë² ë¦¬ - chrome_os: í¬ë¡¬OS - firefox_os: 파ì´ì–´í스OS + adobe_air: Adobe Air + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS ios: iOS - linux: 리눅스 - mac: ë§¥ + linux: Linux + mac: macOS other: 알 수 없는 í”Œëž«í¼ - windows: 윈ë„우즈 - windows_mobile: 윈ë„우즈 ëª¨ë°”ì¼ - windows_phone: 윈ë„우즈 í° + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone revoke: ì‚ì œ revoke_success: ì„¸ì…˜ì´ ì„±ê³µì 으로 ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤ title: 세션 @@ -1106,6 +1179,7 @@ ko: profile: 프로필 relationships: 팔로잉과 팔로워 two_factor_authentication: 2단계 ì¸ì¦ + webauthn_authentication: 보안 키 spam_check: spam_detected: ì´ê²ƒì€ ìžë™í™” ëœ ì‹ ê³ ìž…ë‹ˆë‹¤. ìŠ¤íŒ¸ì´ ê°ì§€ë˜ì—ˆìŠµë‹ˆë‹¤. statuses: @@ -1138,6 +1212,8 @@ ko: other: "%{count}명 투표함" vote: 투표 show_more: ë” ë³´ê¸° + show_newer: 새로운 것 표시 + show_older: ì˜¤ëž˜ëœ ê²ƒ 표시 show_thread: 글타래 보기 sign_in_to_participate: ë¡œê·¸ì¸ í•˜ì—¬ ì´ ëŒ€í™”ì— ì°¸ì—¬í•˜ê¸° title: '%{name}: "%{quote}"' @@ -1246,21 +1322,20 @@ ko: default: "%Yë…„ %mì›” %dì¼ %H:%M" month: "%Yë…„ %b" two_factor_authentication: - code_hint: 확ì¸í•˜ê¸° 위해서 ì¸ì¦ ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 í‘œì‹œëœ ì½”ë“œë¥¼ ìž…ë ¥í•´ 주ì‹ì‹œì˜¤ - description_html: "<strong>2단계 ì¸ì¦</strong>ì„ í™œì„±í™” 하면 ë¡œê·¸ì¸ ì‹œ ì „í™”ë¡œ ì¸ì¦ 코드를 ë°›ì„ í•„ìš”ê°€ 있습니다." + add: 추가 disable: 비활성화 - enable: 활성화 + disabled_success: 2단계 ì¸ì¦ì´ 비활성화 ë˜ì—ˆìŠµë‹ˆë‹¤. + edit: 편집 enabled: 2단계 ì¸ì¦ì´ 활성화 ë˜ì–´ 있습니다 enabled_success: 2단계 ì¸ì¦ì´ 활성화 ë˜ì—ˆìŠµë‹ˆë‹¤ generate_recovery_codes: 복구 코드 ìƒì„± - instructions_html: "<strong>Google Authenticator, ë˜ëŠ” 타 TOTP ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 ì´ QR 코드를 스캔해 주ì‹ì‹œì˜¤.</strong> ì´í›„ ë¡œê·¸ì¸ ì‹œì—는 ì´ ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 ìƒì„±ë˜ëŠ” 코드가 필요합니다." lost_recovery_codes: 복구 코드를 사용하면 íœ´ëŒ€ì „í™”ë¥¼ 분실한 경우ì—ë„ ê³„ì •ì— ì ‘ê·¼í• ìˆ˜ 있게 ë©ë‹ˆë‹¤. 복구 코드를 분실한 경우ì—ë„ ì—¬ê¸°ì„œ 다시 ìƒì„±í• 수 있지만, ì˜ˆì „ 복구 코드는 비활성화 ë©ë‹ˆë‹¤. - manual_instructions: 'QR 코드를 ìŠ¤ìº”í• ìˆ˜ 없어 수ë™ìœ¼ë¡œ 등ë¡ì„ ì›í•˜ì‹œëŠ” 경우 ì´ ë¹„ë°€ 코드를 사용해 주ì‹ì‹œì˜¤:' + methods: 2단계 ì¸ì¦ + otp: ì¸ì¦ 앱 recovery_codes: 복구 코드 recovery_codes_regenerated: 복구 코드가 다시 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤ recovery_instructions_html: íœ´ëŒ€ì „í™”ë¥¼ 분실한 경우, 아래 복구 코드 중 하나를 사용해 ê³„ì •ì— ì ‘ê·¼í• ìˆ˜ 있습니다. <strong>복구 코드는 ì•ˆì „í•˜ê²Œ 보관해 주ì‹ì‹œì˜¤.</strong> ì´ ì½”ë“œë¥¼ ì¸ì‡„í•´ 중요한 서류와 함께 보관하는 ê²ƒë„ ì¢‹ìŠµë‹ˆë‹¤. - setup: 초기 ì„¤ì • - wrong_code: 코드가 올바르지 않습니다. 서버와 íœ´ëŒ€ì „í™” ê°„ì˜ ì‹œê°ì´ ì¼ì¹˜í•˜ë‚˜ìš”? + webauthn: 보안 키 user_mailer: backup_ready: explanation: ë‹¹ì‹ ì´ ìš”ì²í•œ ê³„ì •ì˜ í’€ ë°±ì—…ì´ ì´ì œ 다운로드 가능합니다! @@ -1275,6 +1350,7 @@ ko: warning: explanation: disable: ë‹¹ì‹ ì˜ ê³„ì •ì´ ë™ê²° ëœ ë™ì•ˆ ë‹¹ì‹ ì˜ ê³„ì •ì€ ìœ ì§€ ë©ë‹ˆë‹¤. 하지만 ìž ê¸ˆì´ í’€ë¦´ 때까지 ë‹¹ì‹ ì€ ì•„ë¬´ ê²ƒë„ í• ìˆ˜ 없습니다. + sensitive: ë‹¹ì‹ ì˜ ì—…ë¡œë“œ 한 미디어 파ì¼ë“¤ê³¼ ë§í¬ëœ ë¯¸ë””ì–´ë“¤ì€ ë¯¼ê°í•¨ìœ¼ë¡œ 취급ë©ë‹ˆë‹¤. silence: ë‹¹ì‹ ì˜ ê³„ì •ì´ ì œí•œ ëœ ë™ì•ˆì—” ë‹¹ì‹ ì˜ íŒ”ë¡œì›Œ ì´ì™¸ì—” íˆ¿ì„ ë°›ì•„ ë³¼ 수 ì—†ê³ ê³µê°œ 리스팅ì—서 ì œì™¸ ë©ë‹ˆë‹¤. 하지만 다른 ì‚¬ëžŒë“¤ì€ ì—¬ì „ížˆ ë‹¹ì‹ ì„ íŒ”ë¡œìš° 가능합니다. suspend: ë‹¹ì‹ ì˜ ê³„ì •ì€ ì •ì§€ ë˜ì—ˆìœ¼ë©°, ëª¨ë“ íˆ¿ê³¼ 업로드 한 미디어가 서버ì—서 ì‚ì œ ë˜ì–´ ë˜ëŒë¦´ 수 없습니다. get_in_touch: ì´ ë©”ì¼ì— 대해 답장해서 %{instance}ì˜ ìŠ¤íƒœí”„ì™€ ì—°ë½ í• ìˆ˜ 있습니다. @@ -1283,11 +1359,13 @@ ko: subject: disable: ë‹¹ì‹ ì˜ ê³„ì • %{acct}ê°€ ë™ê²° ë˜ì—ˆìŠµë‹ˆë‹¤ none: "%{acct}ì—ê²Œì˜ ê²½ê³ " + sensitive: ë‹¹ì‹ ì˜ ê³„ì • %{acct}ì—서 í¬ìŠ¤íŒ… 하는 미디어는 민ê°í•¨ìœ¼ë¡œ ì„¤ì •ë˜ì—ˆìŠµë‹ˆë‹¤ silence: ë‹¹ì‹ ì˜ ê³„ì • %{acct}ê°€ ì œí•œ ë˜ì—ˆìŠµë‹ˆë‹¤ suspend: ë‹¹ì‹ ì˜ ê³„ì • %{acct}ê°€ ì •ì§€ ë˜ì—ˆìŠµë‹ˆë‹¤ title: disable: ê³„ì • ë™ê²° ë¨ none: ê²½ê³ + sensitive: ë‹¹ì‹ ì˜ ë¯¸ë””ì–´ëŠ” 민ê°í•¨ìœ¼ë¡œ 표시ë˜ì—ˆìŠµë‹ˆë‹¤ silence: ê³„ì • ì œí•œ ë¨ suspend: ê³„ì • ì •ì§€ ë¨ welcome: @@ -1308,9 +1386,11 @@ ko: tips: íŒ title: 환ì˜í•©ë‹ˆë‹¤ %{name} 님! users: + blocked_email_provider: í—ˆìš©ëœ ì´ë©”ì¼ ì œê³µìžê°€ 아닙니다 follow_limit_reached: ë‹¹ì‹ ì€ %{limit}ëª…ì˜ ì‚¬ëžŒì„ ë„˜ì–´ì„œ 팔로우 í• ìˆ˜ 없습니다 generic_access_help_html: ê³„ì • 로그ì¸ì— ë¬¸ì œê°€ 있나요? %{email} 로 ë„ì›€ì„ ìš”ì²í• 수 있습니다 invalid_email: ë©”ì¼ ì£¼ì†Œê°€ 올바르지 않습니다 + invalid_email_mx: ì´ë©”ì¼ ì£¼ì†Œê°€ 존재하지 않는 것 같습니다 invalid_otp_token: 2단계 ì¸ì¦ 코드가 올바르지 않습니다 invalid_sign_in_token: ìž˜ëª»ëœ ë³´ì•ˆ 코드 otp_lost_help_html: 만약 양쪽 모ë‘를 ìžƒì–´ë²„ë ¸ë‹¤ë©´ %{email}ì„ í†µí•´ ë³µêµ¬í• ìˆ˜ 있습니다 @@ -1320,3 +1400,20 @@ ko: verification: explanation_html: 'ë‹¹ì‹ ì€ <strong>프로필 메타ë°ì´í„°ì˜ ë§í¬ ì†Œìœ ìžìž„ì„ ê²€ì¦í• 수 있습니다</strong>. ì´ê²ƒì„ 하기 위해서는, ë§í¬ ëœ ì›¹ì‚¬ì´íЏì—서 ë‹¹ì‹ ì˜ ë§ˆìŠ¤í† ëˆ í”„ë¡œí•„ì„ ì—으로 ë§í¬í•´ì•¼ 합니다. ì—ë§í¬ëŠ” <strong>반드시</strong> <code>rel="me"</code> ì†ì„±ì„ ê°€ì§€ê³ ìžˆì–´ì•¼ 합니다. ë§í¬ì˜ í…스트는 ìƒê´€ì´ 없습니다. 여기 예시가 있습니다:' verification: ê²€ì¦ + webauthn_credentials: + add: 보안 키 추가 + create: + error: 보안 키를 ì¶”ê°€í•˜ëŠ”ë° ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 시ë„í•´ë³´ì‹ì‹œì˜¤. + success: 보안 키가 성공ì 으로 추가ë˜ì—ˆìŠµë‹ˆë‹¤. + delete: ì‚ì œ + delete_confirmation: ì •ë§ë¡œ ì´ ë³´ì•ˆ 키를 ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? + description_html: "<strong>보안 키 ì¸ì¦</strong>ì„ í™œì„±í™” 하면, ë¡œê·¸ì¸ ì‹œ 보안 키 중 하나가 필요합니다." + destroy: + error: 보안 키를 ì‚ì œí•˜ëŠ”ë° ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 시ë„í•´ë³´ì‹ì‹œì˜¤. + success: 보안 키가 성공ì 으로 ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤. + invalid_credential: ìž˜ëª»ëœ ë³´ì•ˆ 키 + nickname_hint: 새 보안 í‚¤ì˜ ë³„ëª…ì„ ìž…ë ¥í•´ 주세요 + not_enabled: ì•„ì§ WebAuthnì„ í™œì„±í™” 하지 않았습니다. + not_supported: ì´ ë¸Œë¼ìš°ì €ëŠ” 보안 키를 ì§€ì›í•˜ì§€ 않습니다 + otp_required: 보안 키를 사용하기 위해서는 2단계 ì¸ì¦ì„ ë¨¼ì € 활성화 í•´ 주세요 + registered_on: "%{date} ì— ë“±ë¡ë¨" diff --git a/config/locales/ku.yml b/config/locales/ku.yml index 2fbf0ffd710189ce2905acb59a57eba453b1b9f9..0d76e1b97d923ca6d9975b321989c6470ececbd0 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -1 +1,1415 @@ ---- {} +--- +ku: + about: + about_hashtag_html: ئەمانە توتی گشتین بە هەشتەگی گشتی <strong>#%{hashtag}}</strong>. گەر ئێوە Ù„Û• هەر ڕاژەیەک هەژمارەتان بێت دەتوانیت لێرە بەم نووسراوانە هاوئاهەنگ بن. + about_mastodon_html: 'تۆڕی کۆمەڵایەتی داهاتوو: هیچ ڕیکلامێک ØŒ هیچ چاودێرییەکی کۆمپانیا ØŒ دیزاینی ئەخلاقی Ùˆ لامەرکەزی! خاوەنی داتاکانت نابێ Ù„Û• ماستۆدۆن!' + about_this: دەربارە + active_count_after: چالاک + active_footnote: بەکارهێنەرانی چالاکی مانگانە (MAU) + administered_by: 'بەڕێوەبراو لەلایەن:' + api: API + apps: ئەپەکانی مۆبایل + apps_platforms: بەکارهێنانی ماستۆدۆن Ù„Û• iOSØŒ ئەندرۆید Ùˆ سەکۆکانی تر + browse_directory: گەڕان Ù„Û• ڕێبەرێکی Ù¾Ø±Û†ÙØ§ÛŒÙ„ Ùˆ پاڵاوتن بەپێی بەرژەوەندیەکان + browse_local_posts: گەڕانی ڕاستەوخۆ Ù„Û• نووسراوە گشتیەکان Ù„Û•Ù… ڕاژەوە + browse_public_posts: گەڕان Ù„Û• جۆگەیەکی زیندووی نووسراوە گشتیەکان لەسەر ماستۆدۆن + contact: بەردەنگ + contact_missing: سازنەکراوە + contact_unavailable: بوونی نییە + discover_users: پەیداکردنی بەکارهێنەران + documentation: بەڵگەکان + federation_hint_html: بە هەژمارەیەک لەسەر %{instance} دەتوانیت شوێن خەڵک بکەویت لەسەر هەرڕاژەیەکی ماستۆدۆن. + get_apps: ئەپێکی تەلەÙÛ†Ù† تاقی بکەرەوە + hosted_on: مەستودۆن میوانداری کراوە Ù„Û• %{domain} + instance_actor_flash: | + ئەم هەژمارەیە ئەکتەرێکی خەیاڵی بەکارهاتووە بۆ نوێنەرایەتی کردنی خودی ڕاژەکە Ùˆ Ù†Û•Ú© هیچ بەکارهێنەرێکی تاک. + بۆ مەبەستی Ùیدراسیۆن بەکاردێت Ùˆ نابێت بلۆک بکرێت مەگەر دەتەوێت هەموو نمونەکە بلۆک بکەیت، Ú©Û• Ù„Û• ØØ§ÚµÛ•تەش دا پێویستە بلۆکی دۆمەین بەکاربهێنیت. + learn_more: زیاتر Ùێربه + privacy_policy: ڕامیاری تایبەتێتی + see_whats_happening: بزانە Ú†ÛŒ ڕوودەدات + server_stats: 'زانیاری ڕاژەکار:' + source_code: کۆدی سەرچاوە + status_count_after: + one: دۆخ + other: دۆخەکان + status_count_before: Ù„Û• لایەن یەکەوە + tagline: دوای هاوڕێکان بکەوە Ùˆ ئەوانەی نوێ بدۆزیەوە + terms: مەرجەکانی خزمەتگوزاری + unavailable_content: ڕاژەی چاودێریکراو + unavailable_content_description: + domain: ڕاژەکار + reason: هۆکار + rejecting_media: 'پەڕگەکانی میدیا Ù„Û•Ù… ڕاژانەوە پرۆسە ناکرێت یان هەڵناگیرێن، Ùˆ هیچ وێنۆچکەیەک پیشان نادرێت، پێویستی بە کرتە کردنی دەستی هەیە بۆ ÙØ§ÛŒÙ„Û• سەرەکیەکە:' + rejecting_media_title: پاڵێوەری میدیا + silenced: 'بابەتەکانی ئەم ڕاژانە Ù„Û• Ù‡ÛŽÚµÛŒ کاتی گشتی Ùˆ Ú¯ÙØªÙˆÚ¯Û†Ú©Ø§Ù†Ø¯Ø§ دەشاردرێنەوە، Ùˆ هیچ ئاگانامێک دروست ناکرێت Ù„Û• چالاکی بەکارهێنەرانیان، مەگەر تۆ بەدوایان دەچیت:' + silenced_title: ڕاژە ناچالاکەکان + suspended: 'هیچ داتایەک Ù„Û•Ù… ڕاژانەوە پرۆسە ناکرێت، خەزن دەکرێت یان دەگۆڕدرێتەوە، وا دەکات هیچ کارلێک یان پەیوەندییەک Ù„Û•Ú¯Û•Úµ بەکارهێنەران Ù„Û•Ù… ڕاژانە Ù…Û•ØØ§Úµ بێت:' + suspended_title: ڕاژە ڕاگیراوەکان + unavailable_content_html: ماستۆدۆن بە گشتی ڕێگەت پێدەدات بۆ پیشاندانی ناوەڕۆک Ù„Û• Ùˆ کارلێ کردن Ù„Û•Ú¯Û•Úµ بەکارهێنەران Ù„Û• هەر ڕاژەیەکی تر بە گشتی. ئەمانە ئەو بەدەرکردنانەن Ú©Û• کراون لەسەر ئەم ڕاژە تایبەتە. + user_count_after: + one: بەکارهێنەر + other: بەکارهێنەران + user_count_before: "`خاوەن" + what_is_mastodon: ماستۆدۆن چییە? + accounts: + choices_html: 'هەڵبژاردنەکانی %{name}:' + endorsements_hint: دەتوانیت ئەو کەسانە پەسەند بکەیت Ú©Û• پەیڕەویان دەکەیت Ù„Û• ڕووکاری وێب، Ùˆ ئەوان لێرە دەردەکەون. + featured_tags_hint: دەتوانیت هاشتاگی تایبەت Ù¾ÛŽØ´Ú©Û•Ø´ بکەیت Ú©Û• لێرە پیشان دەدرێت. + follow: شوێن Ú©Û•ÙˆÛ• + followers: + one: شوێنکەوتوو + other: شوێن‌کەوتووان + following: شوێن‌کەوتووی + joined: بەشداری %{date} + last_active: دوا چالاکی + link_verified_on: خاوەنداریەتی ئەم لینکە Ù„Û• %{date} Ú†ÛŽÚ© کراوە + media: میدیا + moved_html: "%{name} گواستراوەتەوە بۆ %{new_profile_link}:" + network_hidden: ئەم زانیاریە بەردەست نیە + never_active: هەرگیز + nothing_here: لێرە هیچ نییە! + people_followed_by: ئەو کەسانەی Ú©Û• %{name} بەدوایدا دەکەون + people_who_follow: ئەو کەسانەی Ú©Û• بەدوای %{name} دا دەکەون + pin_errors: + following: تۆ دەبێت هەر ئێستا بە دوای ئەو کەسەدا بیت Ú©Û• دەتەوێت پەسەندی بکەیت + posts: + one: توت + other: تووتەکان + posts_tab_heading: تووتەکان + posts_with_replies: تووتەکان Ùˆ وڵامەکان + reserved_username: ناوی بەکارهێنەر پارێزراوە + roles: + admin: بەڕێوەبەر + bot: بۆت + group: گرووپ + moderator: مۆد + unavailable: Ù¾Ø±Û†ÙØ§ÛŒÙ„ بەردەست نیە + unfollow: بەدوادانەچو + admin: + account_actions: + action: ئەنجامدانی کردار + title: ئەنجامدانی کاری بەڕێوەبردن Ù„Û• %{acct} + account_moderation_notes: + create: جێهێشتنی تێبینی + created_msg: تێبینی بەڕێوەبەر بە سەرکەوتوویی دروست کرا! + delete: سڕینەوە + destroyed_msg: تێبینی بەڕێوەبەر بە سەرکەوتوویی لەناوچوو! + accounts: + add_email_domain_block: بلۆککردنی هەموو دۆمەینەکە + approve: پەسەند کردن + approve_all: پەسەندکردنی هەموو + approved_msg: بەرنامەی تۆمارکردنی %{username} بۆ چوونەناوی پەسەند کرا + are_you_sure: دڵنیای? + avatar: ÙˆÛŽÙ†Û†Ú†Ú©Û• + by_domain: دۆمەین + change_email: + changed_msg: ئیمەیڵی ئەژمێر بە سەرکەوتوویی گۆڕا! + current_email: ئیمەیلی ئێستا + label: گۆڕینی ئیمێڵ + new_email: ئیمەیڵی نوێ + submit: گۆڕینی ئیمێڵ + title: گۆڕینی ئیمەیڵ بۆ %{username} + confirm: پشتڕاستی بکەوە + confirmed: پشتڕاست کرا + confirming: پشتڕاستکردنەوە + delete: سڕینەوەی داتا + deleted: سڕینەوە + demote: پلە نزمکرایەوە + destroyed_msg: دراوەکانی %{username} Ù„Û• ڕیزی سڕینەوەن + disable: بەستن + disable_two_factor_authentication: لەکارخستنی 2FA + disabled: بەستوو + display_name: ناوی پیشاندان + domain: دۆمەین + edit: دەستکاری + email: پۆستی ئەلکترۆنی + email_status: دۆخی ئیمەیڵ + enable: چالاک کردن + enabled: چالاککراوە + enabled_msg: هەژمارە %{username} بە سەرکەوتوویی سنووردار کرا + followers: شوێنکەوتوان + follows: شوێنکەوتوان + header: سەرپەڕە + inbox_url: نیشانی هاتنەژوور + invited_by: هاتۆتە ژورەوە Ù„Û• لایەن + ip: ئای‌پی + joined: ئەندام بوو Ù„Û• + location: + all: هەموو + local: ناوخۆیی + remote: دوور + title: شوێن + login_status: دۆخی چوونەژوورەوە + media_attachments: هاوپێچی میدیا + memorialize: گۆڕان بە یادەوەری + memorialized: بیرکەوتنەوە + memorialized_msg: بە سەرکەوتوویی %{username} بۆ هەژمارێکی بیرەوەری گۆڕا + moderation: + active: چالاک + all: هەموو + pending: چاوەڕوان + silenced: بێدەنگ + suspended: ڕاگرتن + title: بەڕێوەبردن + moderation_notes: بەڕێوەبردنی تێبینیەکان + most_recent_activity: نوێترین چالاکی + most_recent_ip: نوێترین ئای Ù¾ÛŒ + no_account_selected: هیچ هەژمارەیەک نەگۆڕاوە ÙˆÛ•Ú© ئەوەی هیچ یەکێک دیاری نەکراوە + no_limits_imposed: هیچ سنوورێک نەسەپێنرا + not_subscribed: بەشدار نەبوو + pending: پێداچوونەوەی چاوەڕوان + perform_full_suspension: ڕاگرتن + promote: بەرزکردنەوە + protocol: پرۆتۆکۆل + public: گشتی + push_subscription_expires: بەشداری PuSH بەسەر دەچێت + redownload: نوێکردنەوەی Ù¾Ø±Û†ÙØ§ÛŒÙ„ + redownloaded_msg: Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ %{username} Ù„Û• بنەڕەتەوە بە سەرکەوتوویی نوێکرایەوە + reject: ڕەتکردنەوە + reject_all: هەموو ڕەت بکەوە + rejected_msg: بەرنامەی تۆمارکردنی %{username} بە سەرکەوتوویی ڕەتکرایەوە + remove_avatar: لابردنی وێنۆجکە + remove_header: سەرپەڕ لابدە + removed_avatar_msg: ÙˆÛŽÙ†Û•ÛŒ ئەڤاتار %{username} بە سەرکەوتوویی لابرا + removed_header_msg: بە سەرکەوتوویی ÙˆÛŽÙ†Û•ÛŒ سەرپەڕەی %{username} لابرا + resend_confirmation: + already_confirmed: ئەم بەکارهێنەرە پێشتر پشتڕاستکراوەتەوە + send: دووبارە ناردنی ئیمەیڵی دووپاتکردنەوە + success: ئیمەیڵی پشتڕاستکردنەوە بە سەرکەوتوویی نێردرا! + reset: ڕێکخستنەوە + reset_password: گەڕانەوەی تێپەڕوشە + resubscribe: دووبارە ئابونەبوون + role: مۆڵەتەکان + roles: + admin: بەڕێوەبەر + moderator: بەڕێوەبەر + staff: ستا٠+ user: بەکارهێنەر + search: گەڕان + search_same_email_domain: بەکارهێنەرانی دیکە بە ئیمەیلی یەکسان + search_same_ip: بەکارهێنەرانی تر بەهەمان ئای Ù¾ÛŒ + sensitive: هەستیار + sensitized: ÙˆÛ•Ú© هەستیار نیشان کراوە + shared_inbox_url: بەستەری سندوقی هاوبەشکراو + show: + created_reports: گوزارشتی تۆمارکراوە + targeted_reports: گوزارشتکراوە لەلایەن کەسانی ترەوە + silence: سنوور + silenced: سنوورکرا + statuses: دۆخەکان + subscribe: ئابوونە + suspended: ڕاگرتن + suspension_irreversible: داتای ئەم هەژمارەیە بە شێوەیەکی نائاسایی سڕاوەتەوە. دەتوانیت هەژمارەکەت ڕابخەیت بۆ ئەوەی بەکاربێت بەڵام هیچ داتایەک ناگەڕگەڕێتەوە Ú©Û• پێشتر بوونی بوو. + suspension_reversible_hint_html: هەژمارە ڕاگیرا ØŒ Ùˆ داتاکە بەتەواوی Ù„Û• %{date} لادەبرێت. تا ئەو کاتە هەژمارەکە دەتوانرێت بە بێ هیچ کاریگەریەکی خراپ بژمێردرێتەوە. ئەگەر دەتەوێت هەموو داتاکانی هەژمارەکە بسڕەوە، دەتوانیت Ù„Û• خوارەوە ئەمە بکەیت. + time_in_queue: چاوەڕوانی Ù„Û• ڕیزدا %{time} + title: هەژمارەکان + unconfirmed_email: ئیمەیڵی پشتڕاستنەکراو + undo_sensitized: " هەستیار نەکردن" + undo_silenced: بێدەنگ ببە + undo_suspension: دووبارە ڕاگرتن + unsilenced_msg: هەژماری %{username} بە سەرکەوتوویی بێسنوور کرا + unsubscribe: بەتاڵکردنی ئابوونە + unsuspended_msg: هەژمارە %{username} بە سەرکەوتوویی ئابوونەی بەتاڵکرا + username: ناوی بەکارهێنەر + view_domain: پیشاندانی کورتەبۆ دۆمەین + warn: وریاکردنەوە + web: ماڵپەڕ + whitelisted: پێرستی ڕێپێدراو + action_logs: + action_types: + assigned_to_self_report: تەرخانکردنی گوزارشت + change_email_user: گۆڕینی ئیمەیڵ بۆ بەکارهێنەر + confirm_user: دڵنیابوون Ù„Û• بەکارهێنەر + create_account_warning: دروستکردنی ئاگاداری + create_announcement: دروستکردنی راگەیەندراو + create_custom_emoji: دروستکردنی ئێمۆمۆجی دڵخواز + create_domain_allow: دروستکردنی ڕێپێدان بە دۆمەین + create_domain_block: دروستکردنی بلۆکی دۆمەین + create_email_domain_block: دروستکردنی بلۆکی دۆمەینی ئیمەیڵ + create_ip_block: دروستکردنی یاسای IP + demote_user: دابەزاندنی ئاستی بەکارهێنەر + destroy_announcement: سڕینەوەی راگەیەندراو + destroy_custom_emoji: سڕینەوەی ئێمۆمۆجی تایبەتمەند + destroy_domain_allow: سڕینەوەی ڕێپێدان بە دۆمەین + destroy_domain_block: سڕینەوەی بلۆکی دۆمەین + destroy_email_domain_block: سڕینەوەی بلۆکی دۆمەینی ئیمەیڵ + destroy_ip_block: سڕینەوەی یاسای IP + destroy_status: دۆخ بسڕەوە + disable_2fa_user: لەکارخستنی 2FA + disable_custom_emoji: سڕینەوەی ئێمۆمۆجی تایبەتمەند + disable_user: بەکارهێنەر Ù„Û• کاربخە + enable_custom_emoji: ئیمۆمۆجی تایبەتمەند چالاک بکە + enable_user: چالاککردنی بەکارهێنەر + memorialize_account: هەژماری بیرکەوتنەوە + promote_user: بەرزکردنەوەی بەکارهێنەر + remove_avatar_user: لابردنی وێنۆجکە + reopen_report: دووبارە کردنەوەی گوزارشت + reset_password_user: گەڕانەوەی تێپەڕوشە + resolve_report: گوزارشت چارەسەربکە + sensitive_account: میدیاکە Ù„Û• هەژمارەکەت ÙˆÛ•Ú© هەستیار نیشانە بکە + silence_account: هەژماری بێدەنگی + suspend_account: ڕاگرتنی هەژمارە + unassigned_report: گوزارشتی دیارینەکراو + unsensitive_account: میدیاکە Ù„Û• هەژمارەکەت ÙˆÛ•Ú© هەستیار نیشانە Ù…Û•Ú©Û• + unsilence_account: هەژماری بێ دەنگ + unsuspend_account: هەژماری هەڵنەوەستێنراو + update_announcement: بەڕۆژکردنەوەی راگەیەندراو + update_custom_emoji: بەڕۆژکردنی ئێمۆمۆجی دڵخواز + update_status: بەڕۆژکردنی دۆخ + actions: + assigned_to_self_report: "%{name} پێداچوونەوە بە گوزارشتی %{target} Ù„Û• ئەستۆ گرتووە" + change_email_user: "%{name} ناونیشانی ئیمەیلی بەکارهینەری %{target} گۆڕا" + confirm_user: "%{name} ناونیشانی ئیمەیلی بەکارهینەری %{target} پەسەند کرد" + create_account_warning: "%{name} ئاگاداریێک بۆ %{target} نارد" + create_announcement: "%{name} ئاگاداری نوێی دروستکرد %{target}" + create_custom_emoji: "%{name} ئیمۆجی نوێی %{target} بارکرد" + create_domain_allow: "%{name} دۆمەینی %{target} ڕێپێدا" + create_domain_block: "%{name} دۆمەنی %{target} بلۆککرد" + create_email_domain_block: "%{name} دۆمەینی ئیمەیلی %{target} بلۆککرد" + create_ip_block: "%{name} یاسای دروستکراو بۆ ئای‌پی %{target}" + demote_user: "%{name} ئاستی بەکارهێنەری %{target} دابەزاند" + destroy_announcement: "%{name} ئاگاداری %{target} سڕیەوە" + destroy_custom_emoji: "%{name} ئیمۆجی %{target} Ù„Û• ناوبرد" + destroy_domain_allow: "%{name} دۆمەنی%{target} Ù„Û• پێرستی ڕێپێدراو لابرد" + destroy_domain_block: "%{name} بەرگیری Ù„Û• دۆمەینی %{target} لابرد" + destroy_email_domain_block: "%{name} دۆمەینی ئیمەیلی %{target} خستە پێرستی ڕێپێدراو" + destroy_ip_block: "%{name} یاسای سڕینەوە بۆ ئای‌پی %{target}" + destroy_status: "%{name} نووسراوەی %{target} سڕیەوە" + disable_2fa_user: "%{name} دوو مەرجی ÙØ§Ú©ØªÛ•ر بۆ بەکارهێنەر %{target} Ù„Û• کارخست" + disable_custom_emoji: "%{name} ئیمۆجی %{target} ناچالاک کرد" + disable_user: "%{name} چوونەژوورەوەی بەکارهێنەری %{target} لەکارخست" + enable_custom_emoji: "%{name} ئیمۆجی %{target} چالاک کرد" + enable_user: "%{name} چوونەژوورەوەی بەکارهێنەری %{target} چالککرد" + memorialize_account: "%{name} هەژمارەی بەکارهێنەری %{target} گۆڕا بە Ù¾Û•Ú•Û•ÛŒ یادەوەری" + promote_user: "%{name} ئاستی بەکارهێنەری %{target} بەرزکردەوە" + remove_avatar_user: "%{name} ÙˆÛŽÙ†Û†Ú†Ú©Û•ÛŒ بەکارهێنەری %{target} سڕیەوە" + reopen_report: "%{name} گوزارشتی %{target} دووبارە وەگڕخستەوە" + reset_password_user: "%{name} تێپەروشەی بەکارهێنەری %{target} گەڕانەوە" + resolve_report: "%{name} گوزارشتی %{target} دووبارە وەگڕخستەوە" + sensitive_account: "%{name} بە %{target}'s میدیا ÙˆÛ•Ú© هەستیار دیاری کراوە" + silence_account: "%{name} هەژماری %{target}'s بێدەنگ کرا" + suspend_account: "%{name} هەژماری %{target}'ÛŒ ڕاگیرا" + unassigned_report: "%{name} ڕاپۆرتی دیاری نەکراوی %{target}" + unsensitive_account: "%{name} بە %{target}'s میدیا ÙˆÛ•Ú© هەستیار دیاری نەکراوە" + unsilence_account: "%{name} هەژماری %{target}'s بێ دەنگ" + unsuspend_account: "%{name} هەژماری %{target}'s هەڵنەپەسێردراو" + update_announcement: "%{name} بەڕۆژکراوەی راگەیاندنی %{target}" + update_custom_emoji: "%{name} ئیمۆجی %{target} نوێکرایەوە" + update_status: "%{name} نووسراوەی %{target} بەڕۆژکرد" + deleted_status: "(نووسراوە سڕاوە)" + empty: هیچ لاگی کارنەدۆزرایەوە. + filter_by_action: Ùلتەر کردن بە کردار + filter_by_user: Ùلتەر کردن بە کردار + title: تۆماری وردبینی + announcements: + destroyed_msg: بانگەوازەکە بە سەرکەوتوویی سڕاوەتەوە! + edit: + title: بڵاوکردنەوەی راگەیەندراو + empty: هیچ راگەیەندراوێک نەدۆزرایەوە. + live: زیندوو + new: + create: دروستکردنی راگەیەندراو + title: ڕاگەیاندنی نوێ + published_msg: بانگەوازەکە بە سەرکەوتوویی بڵاو کرایەوە! + scheduled_for: خشتەکراوە بۆ %{time} + scheduled_msg: ڕاگەیاندنی خشتەی بۆ بڵاوکردنەوە! + title: ڕاگه یه نراوەکان + unpublished_msg: بانگەواز بە سەرکەوتوویی بڵاونەکرایەوە! + updated_msg: بانگەوازەکە بە سەرکەوتوویی نوێکرایەوە! + custom_emojis: + assign_category: دانانی Ù¾Û†Ù„ÛŽÙ† + by_domain: دۆمەین + copied_msg: کۆپیەکی ناوخۆیی ئیمۆجیبەکە بە سەرکەوتوویی دروست کرد + copy: Ú©Û†Ù¾ÛŒ + copy_failed_msg: نهیتوانی کۆپیهکی ناوخۆیی ئهو ئیمۆجییە دروست بکات + create_new_category: دروستکردنی هاوپۆلی نوێ + created_msg: ئیمۆجی بە سەرکەوتوویی دروستکرا! + delete: سڕینەوە + destroyed_msg: ئیمۆجی بە سەرکەوتوویی بەتاڵکرا! + disable: لەکارخستن + disabled: ناچالاککراوە + disabled_msg: بە سەرکەوتوویی ئەو ئیمۆجییە Ù„Û• کارخراوە + emoji: ئیمۆجی + enable: چالاککردن + enabled: چالاککراوە + enabled_msg: ئەو ئیمۆجییە بە سەرکەوتووانە چالاک کرا + image_hint: PNG تا ٥٠کیلۆبایت + list: پێرست + listed: پێرستکراوە + new: + title: ئیمۆجی نوێی دڵخواز زیاد بکە + not_permitted: تۆ ڕێگەپێدراو نین بۆ ئەنجامدانی ئەم کارە + overwrite: نووسینەوە + shortcode: کورتەکلیل + shortcode_hint: بەلایەنی Ú©Û•Ù…Û•ÙˆÛ• ٢نووسە، تەنها نووسەکانی ئەل٠و بێ Ùˆ ژێرهێڵەکان + title: ئیمۆجی دڵخواز + uncategorized: هاوپۆل نەکراوە + unlist: بێ پێرست + unlisted: پێرست نەبووە + update_failed_msg: نه یتوانی ئه Ùˆ ئیمۆجییه نوێ بکاتەوە + updated_msg: ئیمۆجی بە سەرکەوتوویی نوێکرایەوە! + upload: بارکردن + dashboard: + authorized_fetch_mode: دۆخی پارێزراو + backlog: کاری پشتەواز + config: شێوەپێدان + feature_deletions: سڕینەوەی هەژمارە + feature_invites: بانگێشتکردنی بەستەرەکان + feature_profile_directory: ڕێنیشاندەرێکی Ù¾Ø±Û†ÙØ§ÛŒÙ„ + feature_registrations: تۆمارکراوەکان + feature_relay: گواستنەوەی گشتی + feature_spam_check: دژە سپام + feature_timeline_preview: Ù¾ÛŽØ´ نیشاندانی نووسراوەکان + features: تایبەتمەندیەکان + hidden_service: پەیوەندی نێوان ڕاژە یان خزمەتگوزاری نێننی + open_reports: ڕاپۆرتەکان بکەوە + pending_tags: هاشتاگی چاوەڕوانی پێداچوونەوە دەکات + pending_users: بەکارهێنەران چاوەڕێی پێداچوونەوەن + recent_users: بەکارهێنەرانی ئەم دواییە + search: گەڕانی تەواوی-دەق + single_user_mode: دۆخی بەکارهێنەری تاک + software: نەرمەکالا + space: بەکارهێنانی بۆشایی + title: داشبۆرد + total_users: ژمارەی بەکارهێنەران + trends: تاگە بەرچاوکراوەکان + week_interactions: چالاکیەکانی ئەم Ù‡Û•ÙØªÛ•یە + week_users_active: چالاکی ئەم Ù‡Û•ÙØªÛ•یە + week_users_new: بەکارهێنەرانی ئەم Ù‡Û•ÙØªÛ•یە + whitelist_mode: Ø´ÛŽÙˆÛ•ÛŒ پێرستی ڕێپێدراو + domain_allows: + add_new: ڕێپێدان بە دۆمەین + created_msg: دۆمەین بە سەرکەوتوویی رێگەی پێدرا + destroyed_msg: دۆمەین Ù„Û• پێرستی رێگەی پێدرا لابرا + undo: لابردن Ù„Û• پێرستی ڕێپێدراو + domain_blocks: + add_new: زیادکردنی بلۆکی دۆمەینی نوێ + created_msg: بلۆککردنی دۆمەین Ù„Û• ØØ§ÚµÛŽ Ø¬ÛŽØ¨Û•Ø¬ÛŽÚ©Ø±Ø¯Ù†Û• + destroyed_msg: بلۆکی دۆمەین هەڵوەشاوەتەوە + domain: دۆمەین + edit: دەستکاری بلۆکی دۆمەینی نوێ + existing_domain_block_html: ئێوە پێشتر سنووری دژوارتنا Ù„Û• سەر%{name} جێبەجێکردووە، سەرەتا دەبێ <a href="%{unblock_url}">بلۆک Ù‡Û•ÚµÙˆÛ•Ø´ÛŽÙ†Û•ÙˆÛ•</a>. + new: + create: دروستکردنی بلۆک + hint: بلۆکی دۆمەین رێگری Ù„Û• دروستکردنی هەژمارەی چوونەژوورەوە Ù„Û• بنکەی زانیارێکان ناکات ØŒ بەڵکو بە شێوەیەکی دووبارە Ùˆ خۆکارانە رێوشێوازی پێشکەوتوو تایبەت لەسەر ئەو هەژمارانە جێبەجێ دەکات. + severity: + desc_html: "<strong> بێدەنگی</strong> وا دەکات Ú©Û• نووسراوەکانی هەژمارەکان نەبینراوە بێت بۆ هەر کەسێک Ú©Û• شوێنیان Ù†Û•Ú©Û•ÙˆÛŽ. <strong>ڕاگرتنی</strong> هەموو ناوەڕۆکی هەژمارەکە، میدیا، Ùˆ داتای Ù¾Ø±Û†ÙØ§ÛŒÙ„Û•Ú©Û•ÛŒ بەکارهێنان. <strong>هیچ </strong> ئەگەر دەتەوێت ÙØ§ÛŒÙ„ەکانی میدیا ڕەت بکەیتەوە." + noop: هیچ + silence: بێدەنگ + suspend: ڕاگرتن + title: بلۆکی دۆمەینی نوێ + private_comment: لێدوانی تایبەت + private_comment_hint: لێدوان دەربارەی سنوورداری ئەم دۆمەینە بۆ بەکارهێنانی ناوخۆیی لەلایەن مۆدەرەکان. + public_comment: سەرنجی گشتی + public_comment_hint: لێدوان دەربارەی سنوورداری ئەم دۆمەینە بۆ گشتی، ئەگەر بڵاوکردنەوەی لیستی سنوورداری دۆمەینەکە چالاک بکرێت. + reject_media: ڕەتکردنەوەی ÙØ§ÛŒÙ„ەکانی میدیا + reject_media_hint: Ù¾Û•Ú•Ú¯Û• میدیای پاشکەوتکراو بە Ø´ÛŽÙˆÛ•ÛŽÚ©ÛŒ ناوخۆیی لابدە Ùˆ دابەزین Ù„Û• داهاتوو ڕەتدەکاتەوە. ناپەیوەندیدار Û• بۆ ڕاگرتن + reject_reports: گوزارشتەکان ڕەت بکەوە + reject_reports_hint: پشتگوێ خستنی هەموو گوزارشتەکان Ú©Û• دێن Ù„Û•Ù… دۆمەینە. ناپەیوەندیدارە بۆ ڕاگرتن + rejecting_media: ڕەتکردنەوەی ÙØ§ÛŒÙ„ەکانی میدیا + rejecting_reports: ڕەتکردنەوەی گوزارشتەکان + severity: + silence: بێدەنگ + suspend: ڕاگرتن + show: + affected_accounts: + one: هەژمارەیەک Ú©Û• Ù„Û• بنکەی زانیارێکان کاریگەری لەسەرە + other: "%{count} هەژمارەیەک Ú©Û• Ù„Û• بنکەی زانیارێکان کاریگەری لەسەرە" + retroactive: + silence: نابێدەنگی ئەو ئەژمێرانەی Ú©Û• هەیە Ù„Û•Ù… دۆمەینەوە + suspend: هەڵنەپەسێدراوی هەژمارە کاریگەرەکانی ئەم دۆمەین + title: گەڕانەوەی بلۆککردنی دۆمەین %{domain} + undo: گەڕانەوە + undo: گەڕانەوەی بلۆکی دۆمەینی + view: دیتنی بلۆکی دۆمەینی + email_domain_blocks: + add_new: زیادکردنی نوێ + created_msg: بە سەرکەوتوویی دۆمەینی ئیمەیڵ بلۆک کرا + delete: سڕینەوە + destroyed_msg: بە سەرکەوتوویی دۆمەینی ئیمەیڵ Ù„Û• بلۆک لاچوو + domain: دۆمەین + empty: هیچ دۆمەینێک Ù„Û• ئێستادا بلۆک نەکراوە. + from_html: Ù„Û• %{domain} + new: + create: زیادکردنی دۆمەین + title: بلۆککردنی دۆمەینی ئیمەیڵی نوێ + title: دۆمەینە بلۆککراوەکانی ئیمەیڵ + instances: + by_domain: دۆمەین + delivery_available: گەیاندن بەردەستە + known_accounts: + one: "%{count} هەژمارەی ناسراو" + other: "%{count} هەژمارەکانی ناسراو" + moderation: + all: هەموو + limited: سنووردار + title: بەڕێوەبردن + private_comment: لێدوانی تایبەت + public_comment: سەرنجی گشتی + title: پەیوەندی نێوان ڕاژە + total_blocked_by_us: لەلایەن ئێمە بەربەست کراوە + total_followed_by_them: شوێنمان دەکەون + total_followed_by_us: شوێنیان کەوتین + total_reported: گوزارشت له باره یان + total_storage: هاوپێچی میدیا + invites: + deactivate_all: هەموو لەکارخستنی + filter: + all: هەموو + available: بەردەستە + expired: بەسەرچووە + title: پاڵاوتن + title: بانگهێشتەکان + ip_blocks: + add_new: دروستکردنی یاسا + created_msg: سەرکەوتووانە یاسای نوێی IP زیادکرا + delete: سڕینەوە + expires_in: + '1209600': Ù¢ Ù‡Û•ÙØªÛ• + '15778476': Ù¦ مانگ + '2629746': Ù¡ مانگ + '31556952': Ù¡ ساڵ + '86400': Ù¡ Ú•Û†Ú˜ + '94670856': Ù£ ساڵ + new: + title: دروستکردنی یاسای نوێی IP + no_ip_block_selected: هیچ ڕێسایەکی IP نەگۆڕدرا ÙˆÛ•Ú© ئەوەی هیچ کامیان دەستنیشان نەکران + title: یاساکانی IP + pending_accounts: + title: هەژمارە هەڵواسراوەکان (%{count}) + relationships: + title: پەیوەنیەکان %{acct} + relays: + add_new: زیادکردنی گواستنەوەی نوێ + delete: سڕینەوە + description_html: دانەیەکی <strong>Ú•ÛŽÚµÛ•ÛŒ Ù†ÛŽÙˆ ڕاژەییە(federation relay) Ú©Û• قەبارەیەکی ÙØ±Û•ÛŒ Ù„Û• تووتە گشتییەکان Ù„Û• Ù†ÛŽÙˆ ڕاژە هاوبەشەکان Ùˆ ئابوونەکان دەگوازێتەوە <strong>رێڵە یارمەتی بە ڕاژە بچکۆلەو مامناوە ندییەکان دەدا Ú©Û• بابەتی ÙØ±Û•تر پەیدا بکەن</strong> گەر Ú•ÛŽÚµÛ• نەبێت، ئەم بابەتە گشتییانە تەنها کاتێک پەیدا دەبن Ú©Û• بە کارهێنەرانی ناوخۆیی خۆیان شوێنکەوتووی بەکارهێنەران Ù„Û• سەر ڕاژەکانی دیکە بن. + disable: لەکارخستن + disabled: ناچالاککراوە + enable: چالاککراوە + enable_hint: کاتێک چالاک کرا، ڕاژەکارەکەت بەشداری دەکات Ù„Û• هەموو توتەکانی گشتی Ù„Û•Ù… گواستنەوەیە، Ùˆ دەست دەکات بە ناردنی توتی گشتی ئەم ڕاژەیە. + enabled: چالاککراوە + inbox_url: نیشانەی URL + pending: چاوەڕێی پەسەندکردنی Ú•ÛŽÙ„Û•ÛŒ + save_and_enable: پاشکەوتکردن Ùˆ چالاککردن + setup: دامەزراندنی Ú•ÛŽÚµÛ•ÛŒ پەیوەندی + signatures_not_enabled: ڕیلەکان بە دروستی کارناکات Ù„Û• کاتێکدا دۆخی پارێزراو یان دۆخی سنوورداری گشتی چالاک کراوە + status: دۆخ + title: ڕێڵەکان + report_notes: + created_msg: تێبینی ڕاپۆرت کردن بە سەرکەوتوویی دروست کرا! + destroyed_msg: تێبینی گوزارشت بە سەرکەوتوویی سڕاوەتەوە! + reports: + account: + notes: + one: "%{count} یاداشت" + other: "%{count} یاداشت" + reports: + one: "%{count} گوزارشت" + other: "%{count} گوزارشتەکان" + action_taken_by: کردەوە Ù„Û• لایەن + are_you_sure: دڵنیای? + assign_to_self: دیاریکردن بۆ من + assigned: بەڕێوەبەری بەرپرس + by_target_domain: دۆمەینی هەژمارەی گوزارشتدراو + comment: + none: هیچ + created_at: گوزارشتکرا + mark_as_resolved: نیشانەی بکە ÙˆÛ•Ú© چارەسەرکراو + mark_as_unresolved: نیشانەکردن ÙˆÛ•Ú© چارەسەرنەکراوە + notes: + create: زیادکردنی تێبینی + create_and_resolve: چارەسەر کردن Ù„Û•Ú¯Û•Úµ تێبینی + create_and_unresolve: دووبارە کردنەوەی بە تێبینی + delete: سڕینەوە + placeholder: باسی ئەو کردارانە بکە Ú©Û• ئەنجام دراون، یان هەر نوێکردنەوەیەکی پەیوەندیداری ت... + reopen: دووبارە کردنەوەی گوزارشت + report: 'گوزارشت #%{id}' + reported_account: گوزارشتی هەژمارە + reported_by: گوزارشت Ù„Û• لایەن + resolved: چارەسەرکرا + resolved_msg: گوزارشتکردن بە سەرکەوتوویی چارەسەر کرا! + status: دۆخ + title: گوزارشتکرا + unassign: دیارینەکراوە + unresolved: چارەسەر نەکراوە + updated_at: نوێکرایەوە + settings: + activity_api_enabled: + desc_html: ژماردنی دۆخی بڵاوکراوە ÛŒ ناوخۆیی Ùˆ بەکارهێنەرە چالاکەکان Ùˆ تۆماری نوێ Ù„Û• سەتڵی Ù‡Û•ÙØªØ§Ù†Û• + title: بڵاوکردنەوەی ئاماری Ú©Û† دەربارەی چالاکی بەکارهێنەر + bootstrap_timeline_accounts: + desc_html: چەند ناوی بەکارهێنەرێک جیابکە بە بۆر، تەنها هەژمارەی بلۆککراوەکان Ùˆ ناوخۆیی کاردەکەن. بنەڕەت کاتێک بەتاڵ بوو هەموو بەڕێوەبەرە خۆجێیەکانن. + title: بەدواداچوەکانی گریمانەیی بۆ بەکارهێنەرە نوێکان + contact_information: + email: ئیمەیلی بازرگانی + username: ناوی بەکارهێنەر + custom_css: + desc_html: دەستکاری کردنی Ø´ÛŽÙˆÛ•ÛŒ CSS بارکراو لەسەر هەموو لاپەڕەکان + title: CSSÛŒ تایبەتمەند + default_noindex: + desc_html: کاردەکاتە سەر هەموو بەکارهێنەرەکان Ú©Û• ئەم ڕێکخستنە خۆیان نەگۆڕاون + title: بەکارهێنەران Ù„Û• پێڕستکردنی بزوێنەری گەڕان بە گریمانەیی هەڵبژێن + domain_blocks: + all: بۆ هەموو کەسێک + disabled: بۆ هیچ کەسێک + title: بلۆکەکانی دۆمەین پیشان بدە + users: بۆ چوونە ژوورەوەی بەکارهێنەرانی ناوخۆ + domain_blocks_rationale: + title: پیشاندانی ڕێژەیی + enable_bootstrap_timeline_accounts: + title: چالاککردنی بەدواکەکانی گریمانەیی بۆ بەکارهێنەرە نوێکان + hero: + desc_html: نیشان درا Ù„Û• Ù¾Û•Ú•Û•ÛŒ سەرەتا. بەلایەنی Ú©Û•Ù…Û•ÙˆÛ• 600x100px پێشنیارکراوە. کاتێک Ú•ÛŽÚ© نەکەویت، دەگەڕێتەوە بۆ وێنۆجکەی ڕاژە + title: ÙˆÛŽÙ†Û•ÛŒ پاڵەوان + mascot: + desc_html: نیشان دراوە Ù„Û• چەند لاپەڕەیەک. بەلایەنی Ú©Û•Ù…Û•ÙˆÛ• 293× 205px پێشنیارکراوە. کاتێک دیاری ناکرێت، دەگەڕێتەوە بۆ بەختبەختێکی ئاسایی + title: ÙˆÛŽÙ†Û•ÛŒ ماسکۆت + peers_api_enabled: + desc_html: ناوی دۆمەینەکانێک Ú©Û• ئەم ڕاژە پەیوەندی پێوەگرتووە + title: بڵاوکردنەوەی لیستی راژەکانی دۆزراوە + preview_sensitive_media: + desc_html: بینینی لینک Ù„Û• وێب سایتەکانی تر وێنۆچکەیەک پیشان دەدات تەنانەت ئەگەر میدیاکە بە هەستیاری نیشان کرابێت + title: پیشاندانی میدیای هەستیار Ù„Û• پێشبینیەکانی OpenGraph + profile_directory: + desc_html: ڕێگەدان بە بەکارهێنەران بۆ دۆزینەوەیان + title: چالاککردنی ڕێنیشاندەرێکی Ù¾Ø±Û†ÙØ§ÛŒÙ„ + registrations: + closed_message: + desc_html: Ù„Û• Ù¾Û•Ú•Û•ÛŒ Ù¾ÛŽØ´Û•ÙˆÛ• پیشان دەدرێت کاتێک تۆمارەکان داخراون. دەتوانیت تاگەکانی HTML بەکاربێنیت + title: نامەی تۆمارکردن داخراو + deletion: + desc_html: Ú•ÛŽ بدە بە هەر کەسێک هەژمارەکەی بسڕیتەوە + title: سڕینەوەی هەژمارە بکەوە + min_invite_role: + disabled: هیچکەس + title: ڕێپێدانی بانگهێشتەکان لەلایەن + registrations_mode: + modes: + approved: پەسەندکردنی داواکراو بۆ ناوتۆمارکردن + none: کەس ناتوانێت خۆی تۆمار بکات + open: هەر کەسێک دەتوانێت خۆی تۆمار بکات + title: مەرجی تۆمارکردن + show_known_fediverse_at_about_page: + desc_html: کاتێک ناچالاک کرا، Ù‡ÛŽÚµÛŒ کاتی گشتی Ú©Û• بەستراوەتەوە بە لاپەڕەی ئێستا سنووردار دەبن، تەنها ناوەڕۆکی ناوخۆیی پیشاندەدرێن + title: نیشاندانی ڕاژەکانی دیکە Ù„Û• پێشنەمایەشی ئەم ڕاژە + show_staff_badge: + desc_html: پیشاندانی هێمایەک هاوکار Ù„Û• سەر Ù¾Û•Ú•Û•ÛŒ بەکارهێنەر + title: نیشاندانی هێمای هاوکار + site_description: + desc_html: کورتە باسیک دەربارەی APIØŒ دەربارەی ئەوە Ú† شتێک دەربارەی ئەم ڕاژەی ماستۆدۆن تایبەتە یان هەر شتێکی گرینگی دیکە. دەتوانن HTML بنووسن، بەتایبەت <code><a></code> ÙˆÛ• <code><em></code>. + title: دەربارەی ئەم ڕاژە + site_description_extended: + desc_html: شوێنیکی باشە بۆ نووسینی سیاسەتی ئیس، یاسا Ùˆ ڕێسا ØŒ ڕێنمایی Ùˆ هەر شتیک Ú©Û• تایبەت بەم ڕاژیە، تاگەکانی HTMLــلیش Ú•ÛŽÚ¯Û•ÛŒ پێدراوە + title: زانیاری تەواوکەری تایبەتمەندی + site_short_description: + desc_html: نیشان Ù„Û• شریتی لاتەنیشت Ùˆ مێتا تاگەکان. Ù„Û• پەرەگراÙÛŽÚ© دا وەسÙÛŒ بکە Ú©Û• ماستۆدۆن چیە Ùˆ Ú†ÛŒ وا Ù„Û• ڕاژە Ú©Û• دەکات تایبەت بێت. + title: دەربارەی ئەم ڕاژە + site_terms: + desc_html: دەتوانیت سیاسەتی تایبەتیێتی خۆت بنووسیت، مەرجەکانی خزمەتگوزاری یان یاسایی تر. دەتوانیت تاگەکانی HTML بەکاربێنیت + title: مەرجەکانی خزمەتگوزاری ئاسایی + site_title: ناوی ڕاژە + spam_check_enabled: + desc_html: ماستۆدۆن دەتوانێت هەژمارەکان خۆکارانە بێدەنگ یان گوزارشتیان بکا. زۆر جار بۆ ناسینی هەرزەپەیام Ùˆ پەیامی نەخوازیاری دووپاتدەبێتەوە،جار Ùˆ بار بە Ù‡Û•ÚµÛ• دەردەچێت. + title: دژە هەرزەنامە + thumbnail: + desc_html: بۆ پێشبینین بەکارهاتووە Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ OpenGraph ÙˆÛ• API. ڕووناکی بینین ١٢٠٠x٦٣٠پیکسێڵ پێشنیارکراوە + title: ÙˆÛŽÙ†Û•ÛŒ بچکۆلەی ڕاژە + timeline_preview: + desc_html: لینکەکە نیشان بدە بۆ Ù‡ÛŽÚµÛŒ کاتی گشتی لەسەر Ù¾Û•Ú•Û•ÛŒ نیشتنەوە Ùˆ Ú•ÛŽÚ¯Û• بە API بدە دەستگەیشتنی هەبێت بۆ Ù‡ÛŽÚµÛŒ کاتی گشتی بەبێ سەلماندنی ڕەسەنایەتی + title: ڕێگەبدە بە چوونە ژورەوەی نەسەلمێنراو بۆ Ù‡ÛŽÚµÛŒ کاتی گشتی + title: ڕێکخستنەکانی ماڵپەڕ + trendable_by_default: + desc_html: کاریگەری لەسەر هاشتاگی پێشوو Ú©Û• پێشتر Ú•ÛŽÚ¯Û• پێنەدراوە + title: Ú•ÛŽÚ¯Û• بدە بە هاشتاگی بەرچاوکراوە بەبێ پێداچوونەوەی پێشوو + trends: + desc_html: بە ئاشکرا هاشتاگی پێداچوونەوەی پێشوو پیشان بدە Ú©Û• ئێستا بەرچاوکراوەن + title: هاشتاگی بەرچاوکراوە + site_uploads: + delete: سڕینەوەی ÙØ§ÛŒÙ„ÛŒ بارکراو + destroyed_msg: بارکردنی ماڵپەڕ بە سەرکەوتوویی سڕدراوەتەوە! + statuses: + back_to_account: گەڕانەوە بۆ لاپەڕەی هەژمارە + batch: + delete: سڕینەوە + nsfw_off: نیشانەکردن ÙˆÛ•Ú© هەستیار نیە + nsfw_on: نیشانەکردن ÙˆÛ•Ú© هەستیار + deleted: سڕینەوە + failed_to_execute: جێبەجێ کردن سەرکەوتوو نەبوو + media: + title: میدیا + no_media: هیچ میدیایەک + no_status_selected: هیچ دۆخیک نەگۆڕاوە ÙˆÛ•Ú© ئەوەی هیچ بارێک دەستنیشان نەکراوە + title: دۆخی ئەژمێر + with_media: بە میدیا + tags: + accounts_today: بەکارهێنانی بێ هاوتای ئەمڕۆ + accounts_week: بەکارهێنەری یەکتا Ù„Û•Ù… Ù‡Û•ÙØªÛ•یە + breakdown: بەکارهێنانی ئەمڕۆ بە جوداکردنی سەرچاوە + context: دەق + directory: Ù„Û• پێرست + in_directory: "%{count} Ù„Û• پێرست" + last_active: دوا چالاکی + most_popular: بەناوبانگترین + most_recent: تازەترین + name: هەشتاگ + review: پێداچوونەوەی دۆخ + reviewed: پێداچوونەوە + title: هەشتاگ + trending_right_now: بەرچاوکردن Ù„Û• ئێستادا + unique_uses_today: T%{count} ئەمڕۆ بڵاوکراوە + unreviewed: پێداچوونەوە نەکراوە + updated_msg: ڕێکخستنی هاشتاگ بە سەرکەوتوویی نوێکرایەوە + title: بەڕێوەبەر + warning_presets: + add_new: زیادکردنی نوێ + delete: سڕینەوە + edit_preset: دەستکاریکردنی ئاگاداری پێشگریمان + title: بەڕێوەبردنی ئاگادارکردنەوە پێش‌سازدان + admin_mailer: + new_pending_account: + body: وردەکاریهەژمارە نوێیەکە Ù„Û• خوارەوەیە. دەتوانیت ئەم نەرمەکالا پەسەند بکەیت یان ڕەت بکەیتەوە. + subject: هەژمارەیەک نوێ بۆ پێداچوونەوە لەسەر %{instance} (%{username}) + new_report: + body: بەکارهێنەری %{reporter} گوزارشی Ù„Û• بەکارهینەری%{target} دا + body_remote: کەسێک Ù„Û• %{domain} گوزارشتی %{target} ناردووە + subject: گوزارشتێکی نوی Ù„Û• %{instance} (#%{id}) + new_trending_tag: + body: 'هاشتاگی #%{name} ئەمڕۆ ئاراستە دەکرێت، بەڵام پێشتر پێداچوونەوەی بۆ نەکراوە. بە ئاشکرا پیشان نادرێت مەگەر تۆ Ú•ÛŽÚ¯Û•ÛŒ Ù¾ÛŽ بدەیت، یان تەنها Ùۆرمەکەت ÙˆÛ•Ú© خۆی پاشەکەوت بکەیت Ú©Û• هەرگیز Ù„ÛŽÛŒ نەبیستیت.' + subject: تاگێکی نوێ Ù„Û• %{instance} نیازمەندی پێداچوونەوەیە (#%{name}) + aliases: + add_new: دروستکردنی ناوی ساختە + created_msg: نازناوێکی نوێیان سەرکەوتووانە دروستکرد. ئێستا دەتوانیت دەست بە گواستنەوە کەیت Ù„Û• هەژمێرە کۆنەکەت. + deleted_msg: سەرکەوتووانە نازناوەکان لابدە. گواستنەوە Ù„Û•Ùˆ هەژمارەوە بۆ ئەم کەسە چیتر نابێت. + empty: هیچ نازناوێکت نیە. + hint_html: ئەگەر دەتەوێت Ù„Û• هەژمارەیەکی ترەوە بگوێزریتەوە بۆ ئەم هەژمارە، لێرەدا دەتوانیت نازناوێک دروست بکەیت، Ù¾ÛŽØ´ ئەوەی ئەوە بەردەوام بیت Ù„Û• گواستنەوەی Ù„Û• هەژمارە Ú©Û†Ù†Û•Ú©Û• بۆ ئەم هەژمارە پێویستە. ئەم کردەوەیە خۆی Ù„Û• خۆیدا <strong>بێ زەرە Ùˆ ناگەڕێتەوە</strong><strong>گواستنەوەی Ù„Û• هەژمارەی Ú©Û†Ù†Û• بۆ هەژمارەی نوێ دەستی پێکردووە</strong>. + remove: سڕینەوەی پەیوەندی ناز ناو + appearance: + advanced_web_interface: روخساری پێشکەوتوو + advanced_web_interface_hint: 'ئەگەر دەتەوێت پانی شاشەکە بەکاربێنیت، دەتوانی بە یارمەتی ڕووکاری پێشکەوتوو چەندین ستوونی جیاواز ڕێکبخەیت بۆ بینینی زانیاری زیاتر Ù„Û• هەمان کات Ú©Û• دەتەوێت بیبینیت: نووسراوەکانی نووسەرانی دیکە، ئاگانامەکان، پێرستی نووسراوەکانی هەموو شوێنێک، ÙˆÛ• هەر ژمارەیەک Ù„Û• لیستەکان Ùˆ هاشتاگەکان.' + animations_and_accessibility: ئەنیمەیشن Ùˆ توانایی دەستپێگەیشتن + confirmation_dialogs: پەیامەکانی پەسەندکراو + discovery: دۆزینەوە + localization: + body: ماستۆدۆن لەلایەن خۆبەخشەوە وەردەگێڕێت. + guide_link: https://crowdin.com/project/mastodon + guide_link_text: هەموو کەسێک دەتوانێت بەشداری بکات. + sensitive_content: ناوەڕۆکی هەستیار + toot_layout: Ù„Û†ÛŒ توت + application_mailer: + notification_preferences: گۆڕینی پەسەندکراوەکانی ئیمەیڵ + salutation: "%{name}," + settings: 'گۆڕینی پەسەندکراوەکانی ئیمەیڵ: %{link}' + view: 'نیشاندان:' + view_profile: Ù¾Ø±Û†ÙØ§ÛŒÙ„ نیشان بدە + view_status: پیشاندانی دۆخ + applications: + created: بەرنامە بە سەرکەوتوویی دروست کرا + destroyed: بەرنامە بە سەرکەوتوویی سڕدراوەتەوە + invalid_url: بەستەری دابینکراو نادروستە + regenerate_token: دووبارە دروستکردنەوەی نیشانەی چوونە ژوورەوە + token_regenerated: کۆدی دەستپێگەیشتن بە سەرکەوتوویی دروستکرا + warning: زۆر ئاگاداربە Ù„Û•Ù… داتایە. هەرگیز Ù„Û•Ú¯Û•Úµ کەس دا هاوبەشی Ù…Û•Ú©Û•! + your_token: کۆدی دەستپێگەیشتنی ئێوە + auth: + apply_for_account: داواکردنی بانگهێشتێک + change_password: تێپەڕوشە + checkbox_agreement_html: من ڕازیم بە <a href ="%{rules_path}" target="_blank">یاساکانی ڕاژە</a> ÙˆÛ• <a href="%{terms_path}" target="_blank">مەرجەکانی خزمەتگوزاری</a> + checkbox_agreement_without_rules_html: من ڕازیم بە <a href="%{terms_path}" target="_blank">مەرجەکانی خزمەتگوزاری</a> + delete_account: سڕینەوەی هەژمارە + delete_account_html: گەر هەرەکتە هەژمارەکەت بسڕیتەوە، Ù„Û• <a href="%{path}">Ù„Û•Ù… قوناغانە</a> بڕۆیتە Ù¾ÛŽØ´Û•ÙˆÛ•. داوای پەسەند کردنتان لێدەگیرێت. + description: + prefix_invited_by_user: "@%{name} بانگت دەکات بۆ پەیوەندیکردن بەم ڕاژەی ماستۆدۆن!" + prefix_sign_up: ئەمڕۆ خۆت تۆمار بکە Ù„Û• ماستۆدۆن! + suffix: بە هەژمارەیەک، دەتوانیت شوێن هەژمارەکانی دیکە بکەویت، نوێکردنەوەکان بڵاوبکەوە Ùˆ نامە Ù„Û•Ú¯Û•Úµ بەکارهێنەران Ù„Û• هەر ڕاژەیەکی ماستۆدۆن Ùˆ زیاتر بگۆڕیتەوە! + didnt_get_confirmation: ڕێنماییەکانی دڵنیاکردنەوەت پێنەدرا? + dont_have_your_security_key: کلیلی ئاسایشت نیە? + forgot_password: تێپەڕوشەکەت لەبیر چووە? + invalid_reset_password_token: وشەی نهێنی دووبارە ڕێکبخەوە دروست نیە یان بەسەرچووە. تکایە داوایەکی نوێ بکە. + link_to_otp: کۆدی دوو ÙØ§Ú©ØªÛ•ر Ù„Û• تەلەÙۆنەکەت یان کۆدی چاککردنەوە تێبنووسە + link_to_webauth: بەکارهێنانی ئامێری کلیلی پاراستن + login: چوونەژوورەوە + logout: چوونەدەرەوە + migrate_account: گواستنەوە بۆ ئەژمێرێکی تر + migrate_account_html: ئەگەر دەتەوێت ئەم هەژمارە دووبارە ئاڕاستە بکەیت بۆ ئەژمێرێکی تر، دەتوانیت <href="%{path}"> کرتەیەک لێرە بکەی </a>. + or_log_in_with: یان چوونە ژوورەوە بە + providers: + cas: CAS + saml: SAML + register: خۆ تۆمارکردن + registration_closed: "%{instance} ئەندامانی نوێ قبووڵ ناکات" + resend_confirmation: دووبارە ناردنی ڕێنماییەکانی دووپاتکردنەوە + reset_password: گەڕانەوەی تێپەڕوشە + security: ئاسایش + set_new_password: سازدانی تێپەڕوشەی نوێ + setup: + email_below_hint_html: ئەگەر ناونیشانی ئیمەیڵی خوارەوە نادروستە، دەتوانیت لێرە بیگۆڕیت Ùˆ ئیمەیڵێکی پشتڕاستکردنەوەی نوێ وەربگۆڕیت. + email_settings_hint_html: ئیمەیڵی پشتڕاستکردنەوە Ú©Û• نێردرا بۆ %{email}. ئەگەر ناونیشانی ئیمەیڵ ڕاست نەبوو، دەتوانیت Ù„Û• ڕێکبەندەکانی هەژمارەکەت بیگۆڕیت. + title: دامەزراندن + status: + account_status: دۆخی هەژمارە + confirming: چاوەڕوانی دڵنیاکردنەوەی ئیمەیڵ بۆ تەواوکردن. + functional: هەژمارەکەت بەتەواوی کارا بووەتەوە. + pending: ئەپلیکەیشەنەکەت چاوەڕوانی پێداچوونەوەیە لەلایەن ستاÙەکەمانەوە. لەوانەیە ئەمە هەندێک کاتی بخایەنێت ئەگەر ئەۆپەکەت پەسەند کرا، ئیمەیڵت پێدەگات. + redirecting_to: هەژمارەکەت ناچالاکە لەبەرئەوەی ئێستا دووبارە ئاڕاستەدەکرێتەوە بۆ %{acct}. + trouble_logging_in: Ú©ÛŽØ´Û• ت هەیە بۆ چوونە ژوورەوە? + use_security_key: کلیلی ئاسایش بەکاربهێنە + authorize_follow: + already_following: ئێوە ئێستا شوێن کەوتووی ئەم هەژمارەیەی + already_requested: تۆ پێشتر داواکاری بەدواداچوت ناردوە بۆ ئەو هەژمارە + error: بەداخەوە هەڵەیەک هەبوو Ù„Û• کاتی گەڕان بەدوای ئەو هەژمارەیە + follow: شوێن Ú©Û•ÙˆÛ• + follow_request: 'تۆ داواکاری شوێنکەوتنت ناردووە بۆ:' + following: 'ئەنجام بوو! تۆ ئێستا بەدوای ئەم بەکارهێنەرە دەکەویت:' + post_follow: + close: یان، دەتوانیت ئەم پەنجەرەیە دابخەیت. + return: Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ بەکارهێنەر نیشان بدە + web: بڕۆ بۆ وێب + title: دوای %{acct} بکەوە + challenge: + confirm: بەردەوام بە + hint_html: "<strong>خاڵ:</strong> ئیمە Ù„Û• کاتژمێری داهاتوو تێپەروشەت لێداوا ناکەین." + invalid_password: تێپەروشە دروست نیە + prompt: دڵنیابوون Ù„Û• نهێنوشە بۆ بەردەوامبوون + crypto: + errors: + invalid_key: کلیلی باوڕپێکراو Ed25519 یان Curve25519 دروست نییە + invalid_signature: واژووی Ed25519 بڕوادار نییە + date: + formats: + default: "%b %d, %Y" + with_month_name: "%B %d, %Y" + datetime: + distance_in_words: + about_x_hours: "%{count}کات" + about_x_months: "%{count}mo" + about_x_years: "%{count}ساڵ" + almost_x_years: "%{count}ساڵ" + half_a_minute: ئێستا + less_than_x_minutes: "%{count}m" + less_than_x_seconds: ئێستا + over_x_years: "%{count}ساڵ" + x_days: "%{count}Ú•Û†Ú˜" + x_minutes: "%{count}m" + x_months: "%{count}mo" + x_seconds: "%{count}s" + deletes: + challenge_not_passed: ئەو زانیاریانەی تێنووست کردووە ڕاست نەبوو + confirm_password: تێپەڕوشەی ئێستات تێبنووسە بۆ سەلماندنی ناسنامەکەت + confirm_username: ناوی بەکارهێنەرت تێبنووسە بۆ دڵنیابوون Ù„Û• کردارەکە + proceed: سڕینەوەی هەژمارە + success_msg: هەژمارەکەت بە سەرکەوتوویی سڕرایەوە + warning: + before: 'Ù¾ÛŽØ´ بەردەوام بوون، تکایە ئەم تێبینیانە بە وردی بخوێننەوە:' + caches: وادیارە ئەو ناوەرۆکە Ú©Û• ڕاژەکانی دیکە پاشکەوتیان کردووە بمینێتەوە + data_removal: بابەتەکانت Ùˆ داتاکانی تر بە هەمیشەیی لادەبرێن + email_change_html: دەتوانی <a href="%{path}"> ناونیشانی ئیمەیڵەکەت بگۆڕیت</a> بەبێ سڕینەوەی هەژمارەکەت + email_contact_html: گەر ئیمەیل نەگەیشتووە بۆ داوای یارمەتی پەیامێک بنێرە بۆ <a href="mailto:%{email}">%{email}</a> پیغام دهید + email_reconfirmation_html: ئەگەر ئیمەیڵی پشتڕاستکردنەوەت پێنەگەشتووە، دەتوانیت <a href="%{path}"> دووبارە داوای لێبکە</a> + irreversible: ناتوانیت هەژمارەکەت بگەڕێنیتەوە یان کارا بکەیتەوە + more_details_html: بۆ زانیاری زیاتر، <a href="%{terms_path}"> پاراستنی نهێنیەکان</a> ببینە. + username_available: ناوی تێپەڕبوونت دووبارە بەردەست دەبێت + username_unavailable: ناوی تێپەڕبوونت بەردەست نییە + directories: + directory: ڕێنیشاندەرێکی Ù¾Ø±Û†ÙØ§ÛŒÙ„ + explanation: دۆزینەوەی بەکارهێنەران لەسەر بنەمای بەرژەوەندییەکانیان + explore_mastodon: گەڕان Ù„Û• %{title} + domain_validator: + invalid_domain: ناوی دۆمەین بڕوادار نییە + errors: + '400': داواکاریەکەی Ú©Û• پێشکەشت کردووە نادروستە یان نەیپێکا. + '403': تۆ مۆڵەتت نیە بۆ بینینی ئەم لاپەڕەیە. + '404': ئەو لاپەڕەیەی بەدوای دەگەڕێی لێرە نیە. + '406': ئەم پەڕەیە Ù„Û• Ùۆرماتی داواکراودا بەردەست نییە. + '410': ئەو لاپەڕەیەی بەدوای دا دەگەڕایت چیتر لێرە بوونی نیە. + '422': + content: سەلماندنەکەی ئاسایش سەرکەوتوو نەبوو. تۆ بلۆکی کۆکیز دەکەیت? + title: سەلماندنەکەی ئاسایش سەرکەوتوو نەبوو + '429': داواکاری زۆر + '500': + content: داوای لێبوردن دەکەین، بەڵام Ù„Û• کۆتاییەکەماندا. شتێک Ù‡Û•ÚµÛ• ڕویداوە. + title: ئەم لاپەڕەیە ڕاست نییە + '503': ناتوانرێت Ù¾Û•Ú•Û•Ú©Û• خزمەت بکرێت بەهۆی شکستی ڕاژەیەکی کاتی. + noscript_html: بۆ بەکارهێنانی بەرنامەی وێبی ماستۆدۆن، تکایە جاڤاسکریپت بەتوانا بکە. Ù„Û• جیاتی ئەوە، یەکێک Ù„Û• < href="%{apps_path}">ئەپێکی ماستۆدۆن</a>بەکارببە. + existing_username_validator: + not_found: بەکارهێنەرێک بەم هەژمارەی بەکارهێنەرە Ù„Û•Ù… ڕاژە پەیدا نەبوو + not_found_multiple: نەیتوانی %{usernames} بدۆزێتەوە + exports: + archive_takeout: + date: بەروار + download: داگرتنی ئەرشیÙەکەت + hint_html: دەتوانیت داوای ئەرشیÙÛŒ <strong> نووسراوە Ùˆ میدیای بارکراوەی خۆت </strong> بکەی. داتای هەناردەکراو Ù„Û• Ùۆرماتی ActivityPub دەبێت، دەخوێنرێتەوە لەلایەن هەر نەرمەکالایەکی گونجاو. دەتوانیت هەموو Ù§ Ú•Û†Ú˜ جارێک داوای ئەرشیÙێکەت بکەیت. + in_progress: خەریکی Ú©Û† کردنەوەی ئەرشیڤەکەت... + request: داوای ئەرشیÙەکەت بکە + size: قەبارە + blocks: تۆ بلۆک دەکەیت + bookmarks: نیشانکراوەکان + csv: CSV + domain_blocks: دۆمەین قەپاتکرا + lists: لیستەکان + mutes: هەژمارە بێدەنگ کراوە + storage: هەمارگەی میدیا + featured_tags: + add_new: زیادکردنی نوێ + errors: + limit: ئێوە ژمارەی بڕی ڕێگەپێدراوەی هاشتاگت هەیە + hint_html: "<strong> هاشتاگی تایبەت چییە؟</strong> بە شێوەیەکی دیار نیشان دەدرێت لەسەر Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ گشتی Ùˆ Ú•ÛŽÚ¯Û• بە خەڵک دەدات بۆ گەڕان Ù„Û• نووسراوە گشتیەکانت بە تایبەتی لەژێر ئەو هاشتاگە. ئامرازێکی زۆر باشن بۆ پاراستنی کاری داهێنەرانە یان Ù¾Ú•Û†Ú˜Û•ÛŒ درێژخایەنی ئێوە." + filters: + contexts: + account: Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکان + home: ماڵەوە + notifications: ئاگادارییەکان + public: پێرستی گشتی نووسراوەکان + thread: Ú¯ÙØªÙˆÚ¯Û†Ú©Ø§Ù† + edit: + title: دەستکاری Ùلتەر + errors: + invalid_context: هیچ دەقێکی نادروست نییە یان بێ بڕوایە + invalid_irreversible: Ùلتەرکردنی بێ گەڕانەوە تەنها کار دەکات Ù„Û•Ú¯Û•Úµ چوارچێوەی ماڵ یان ئاگانامەکان + index: + delete: سڕینەوە + empty: هیچ پالێوەرێکت نیە. + title: Ùلتەرەکان + new: + title: زیادکردنی Ùلتەری نوێ + footer: + developers: پەرەپێدەران + more: زیاتر… + resources: سەرچاوەکان + trending_now: هەوادارانی ئێستا + generic: + all: هەموو + changes_saved_msg: گۆڕانکاریەکان بە سەرکەوتوویی هەڵگیرا! + copy: ڕوونووس + delete: سڕینەوە + no_batch_actions_available: هیچ گرووپێکی کاری بەردەست نیە لەسەر ئەم لاپەڕەیە + order_by: ڕێکخستن بەپێی + save_changes: گۆڕانکاریەکان بپارێزە + validation_errors: + one: شتێک هێشتا تەواو ڕاست نیە تکایە چاو بە Ù‡Û•ÚµÛ•Ú©Û•ÛŒ خوارەوە بخشێنەوە + other: هێشتا تەواو ڕاست نیە تکایە چاو بە Ù‡Û•ÚµÛ•ÛŒ %{count} خوارەوە بخشێنەوە + html_validator: + invalid_markup: 'نیشانەی HTML نادروستی تێدایە: %{error}' + identity_proofs: + active: چالاک + authorize: بەڵێ، Ú•ÛŽÚ¯Û• بدە + authorize_connection_prompt: ئایا ئەم گرێدانە نهێنییە ڕیگە دەدەی? + errors: + failed: پەیوەندی کردنی نهێنیکردن سەرکەوتوو نەبوو. تکایە دووبارە Ù„Û• %{provider} Ù‡Û•ÙˆÚµ بدەوە. + keybase: + invalid_token: نیشانە کانی بنەکلیلی سەرەکی (Ù‡Û•Ø´) واژووی دیجیتاڵن Ùˆ لانی Ú©Û•Ù… ٦٦ نووسە Ù„Û• توانی ١٦ هەیە + verification_failed: ئەم بنە کلیلیە(Keybase) بە ءینوانی واژووی دیجیتاڵی بەکارهێنەری %{kb_username} پەسەند ناکا، تکایا دووبارە Ù„Û• بنە کلیلێکی دیکە Ù‡Û•ÙˆÚµ بدەوە. + wrong_user: ناتوانرێت پشت ڕاستکردنەوەیەک بۆ %{proving} Ù„Û• کاتێک بە عینوانی %{current} هاتنەتە ناوە. بە عینوانی %{proving} بچنە ناوەو دووبارە Ù‡Û•ÙˆÚµ بدەنەوە. + explanation_html: لێرە دەتوانیت بە نهێنی ناسنامەکانی تر ت گرێ بدەی Ù„Û• سەکۆکانی ترەوە، ÙˆÛ•Ú© کلیلی بنکە. ئەمە Ú•ÛŽÚ¯Û• دەدات بە کەسانی تر نامەی رەمزێنراوەکانت بۆ بنێرن لەسەر ئەو پلاتÙۆرمە ØŒ رێگەیان پێدەدات متمانە بکەن Ú©Û• ئەو ناوەڕۆکەی تۆ دەیاننێریت Ù„Û• تۆوە دێت. + i_am_html: من %{username} ــم لەسەر %{service} ــنم. + identity: ناسنامە + inactive: ناچالاکە + publicize_checkbox: 'ئەمە توت بکە:' + publicize_toot: 'پەسەند کرا! من %{username} لەسەر %{service} Ù‡Û•Ù…: %{url}' + remove: لابردنی بەڵگە Ù„Û• هەژمارەی + removed: بە سەرکەوتوویی بەڵگەنامەی سەلماندن لابرا Ù„Û• هەژمارەی بەکارهینەر + status: دۆخی سەلماندن + view_proof: پیشاندانی سەلماندن + imports: + modes: + merge: یەکخستن + merge_long: هێشتنەوەی تۆمارەکانی بەردەست Ùˆ زیادکردنی دانەنوێکان + overwrite: نووسینەوە + overwrite_long: دراوەکانی ئێستا بسڕەوە Ùˆ دراوی نوێ زیاد بکە + preface: دەتوانیت زانیاری هاوردە بکەیت Ú©Û• ناردوتە تە Ù„Û• ڕاژەیەکی ترەوە، ÙˆÛ•Ú© لیستی ئەو کەسانەی Ú©Û• تۆ بەدوای دادەکەویت یان بەربەستت دەکەن. + success: داتاکەت بە سەرکەوتوویی بارکرا Ùˆ ئێستا Ù„Û• کاتی خۆیدا پرۆسێس دەکرێت + types: + blocking: لیستی بلۆککردن + bookmarks: نیشانەکان + domain_blocking: لیستی بلۆککردنی دۆمەین + following: لیستی خوارەوە + muting: لیستی کپکردنەوە + upload: بارکردن + in_memoriam_html: لەیادبوون. + invites: + delete: لەکارخستن + expired: بەسەرچووە + expires_in: + '1800': ٣٠خولەک + '21600': Ù¦ کاتژمێر + '3600': Ù¡ کاتژمێر + '43200': ١٢ کاتژمێر + '604800': Ù¡ Ù‡Û•ÙØªÛ• + '86400': Ù¡ Ú•Û†Ú˜ + expires_in_prompt: هەرگیز + generate: دروستکردنی لینکی بانگهێشت + invited_by: 'بانگهێشتکرایت لەلایەن:' + max_uses: + one: Ù¡ بار + other: "%{count} بار" + max_uses_prompt: بێ سنوور + prompt: دروست کردن Ùˆ هاوبەش کردنی لینکەکان Ù„Û•Ú¯Û•Úµ ئەوانی تر بۆ پێدانی چوونە ژوورەوە بۆ ئەم ڕاژە + table: + expires_at: بەسەرچووە + uses: بەکارهاوردنەکان + title: بانگهێشتکردنی خەڵک + lists: + errors: + limit: تۆ گەیشتوویتە زۆرترین Ú•ÛŽÚ˜Û•ÛŒ لیستەکان + media_attachments: + validations: + images_and_video: ناتوانرێت Ù„Û•Ú¯Û•Úµ ئەو نووسراوانە Ú©Û• ÙˆÛŽÙ†Û•ÛŒ Ù„Û•Ú¯Û•ÚµÛ• ،ڤیدیۆ بار بکەی + not_ready: ناتوانێت ÙØ§ÛŒÙ„ەکان هاوپێچ بکات Ú©Û• پرۆسەکەیان تەواو نەکردووە. دووبارە Ù‡Û•ÙˆÚµ بدە! + too_many: ناتوانێت زیاتر Ù„Û• Ù¤ ÙØ§ÛŒÙ„ هاوپێچ بکات + migrations: + acct: گوێزرایەوە بۆ + cancel: پاشگەزبوونەوە Ù„Û• دووبارە ئاڕاستەکردنەوە + cancel_explanation: هەڵوەشاندنەوەی دووبارە ئاڕاستەکردنەوە هەژمارەی ئێستات چالاک دەکات، بەڵام ئەو شوێنکەوتوانی ناهێنە وه Ú©Û• گواستراوەتەوە بۆ ئەو هەژمارە. + cancelled_msg: سەرکەوتووانە دووبارە ئاڕاستەکردنەوەکەی بەتاڵ کردەوە. + errors: + already_moved: هەمان ئەژمێرە Ú©Û• تۆ پێشتر گواستووتە بۆ + missing_also_known_as: نازناوێکی ئەم هەژمارە نییە + move_to_self: ناتوانێت هەژمارەی ئێستا بێت + not_found: نادۆزرێتەوە + on_cooldown: تۆ دەبێت چاوەڕوان بیت + followers_count: شوێنکەوتوانی کاتی Ù„Û• ØØ§ÚµÛŒ گواستنەوە + incoming_migrations: گواستنەوە Ù„Û• هەژمارەی جیاواز + incoming_migrations_html: بۆ گواستنەوە Ù„Û• هەژمارەیەکی ترەوە بۆ ئەم هەژمارە، سەرەتا پێویستە <href="%{path}"> ئەژمێرێک دروست </a> بکەی. + moved_msg: هەژمارەکەت ئێستا دووبارە ئاڕاستە دەکرێتەوە بۆ %{acct} Ùˆ شوێنکەوتوانی تۆ گواستراوەتەوە بۆ ئەوێ. + not_redirecting: هەژمارەکەت Ù„Û• ئێستادا دووبارە ئاڕاستە ناکرێتەوە بۆ هیچ هەژمارەیەکی دیکە. + on_cooldown: تۆ بەم دواییە هەژمارەکەت Ú©Û†Ú† کردووە. ئەم کارە Ù„Û• رۆژەکانی %{count} دا جارێکی تر بەردەست دەبێت. + past_migrations: گەواستنەوەکانی ڕابردوو + proceed_with_move: شوێنکەوتوان بگوازەوە + redirected_msg: ئەژمێرەکەت ئێستا دووبارە ئاڕاستە دەکرێتەوە بۆ %{acct}. + redirecting_to: ئەژمێرەکەت دووبارە ئاڕاستە دەکرێتەوە بۆ %{acct}. + set_redirect: دووبارە ئاڕاستەکردن Ú•ÛŽÚ© بخە + warning: + backreference_required: پێویستە سەرەتا هەژمارە نوێیەکە بۆ گەڕانەوەی سەرچاوەی ئەم هەژمارە رێکوپێک بکرێت + before: 'Ù¾ÛŽØ´ بەردەوام بوون، تکایە ئەم تێبینیانە بە وردی بخوێننەوە:' + cooldown: دوای گواستنەوە ماوەیەکی چاوەڕوان دەبێ Ú©Û• Ù„Û• ماوەی ئەو دا نابێت جارێکی تر بگوازیتەوە + disabled_account: هەژمارەی ئێستات دوای ئەوە بە تەواوی بەکارناهیێت. هەرچۆنێک بێت، تۆ دەستگەیشتنت دەبێت بۆ ناردنەدەرەوەی داتا Ùˆ هەروەها دووبارە کاراکردنەوە. + followers: ئەم کردارە هەموو شوێنکەوتوانی هەژمارەی ئێستا دەگوازێتەوە بۆ هەژمارەی نوێ + only_redirect_html: ئێوە دەتانن هەژمارەکەی خۆتان <a href="%{path}">بیخەنە سەر هەژمارەیەکی دیکە</a>. + other_data: هیچ داتایەکی تر بە خۆکارانە ناگوێزرێتەوە + redirect: Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ هەژمارەی ئێستات بە ئاگادارییەکی ئاراستەکەراوە نوێ دەکرێتەوە Ùˆ دووردەکەویت Ù„Û• گەڕانەکان + moderation: + title: بەڕێوەبردن + move_handler: + carry_blocks_over_text: ئەم بەکارهێنەرە گواسترایەوە بۆ %{acct}ØŒ تۆ بلۆکت کردووە. + carry_mutes_over_text: ئەم بەکارهێنەرە گواسترایەوە بۆ %{acct}ØŒ تۆ بێدەنگت کردووە. + copy_account_note_text: 'ئەم بەکارهێنەرە Ù„Û• %{acct} Û•ÙˆÛ• گواستیەوە، تێبینیەکانی پێشووت دەربارەیان بوون:' + notification_mailer: + digest: + action: پیشاندانی هەموو ئاگانامەکان + body: ئەمە کورتەی ئەو نامانەی Ù„Û• دەستت دا Ù„Û• دوا سەردانیت Ù„Û• %{since} + mention: "%{name} ئاماژەی بە تۆ کرد Ù„Û•:" + new_followers_summary: + one: لەکاتێک Ú©Û• نەبوو ،شوێنکەوتوویێکی نوێت پەیداکرد،ئاÙەرم! + other: کاتیک Ú©Û• نەبووی %{count} شوێنکەوتوویێکی نوێت پەیدا کرد! Ú† باشە! + subject: + one: "ئاگاداریێکی نووی Ù„Û• دوایین سەردانی ئێوە\U0001F418" + other: "%{count} ئاگاداریێکی نوێ Ù„Û• دوایین سەردانی ئێوە\U0001F418" + title: Ù„Û• غیابی تۆدا... + favourite: + body: 'دۆخت پەسەندکراوە لەلایەن %{name}:' + subject: "%{name} دۆخی تۆی پەسەند کرد" + title: دڵخوازکردنی نوێ + follow: + body: "%{name} ئێستا شوێنکەوتوو ئێوەیە!" + subject: "%{name} ئێستا شوێنکەوتوو ئێوەیە" + title: شوێنکەوتوانی نوێ + follow_request: + action: بەڕێوەبردنی داوای شوێنکەوتن + body: "%{name} داوای کردووە Ú©Û• شوێنت بکەوێت" + subject: 'چاوەڕوانی شوێنکەوتووە: %{name}' + title: داواکاری شوینکەوتنی نوێ + mention: + action: وەڵام + body: "%{name} لێرە ناوی ئێووەی بردووە:" + subject: "%{name} لێرە ناوی ئێووەی بردووە" + title: ناوبراوەی نوێ + reblog: + body: "%{name} نووسیسراوەکەی ئێوەی توتاندەوە:" + subject: "%{name} نووسراوەکەتی دووبارە توتاند" + title: توتاندنەوەی نوێ + notifications: + email_events: رووداوەکان بۆ ئاگاداری ئیمەیلی + email_events_hint: 'ئەو ڕووداوانە دیاریبکە Ú©Û• دەتەوێت ئاگانامەکان وەربگری بۆ:' + other_settings: ڕێکبەندەکانی ئاگانامەکانی تر + number: + human: + decimal_units: + format: "%n%u" + units: + billion: B + million: M + quadrillion: Q + thousand: K + trillion: T + otp_authentication: + code_hint: کۆدێک داخڵ بکە Ú©Û• دروست کراوە لەلایەن ئەپی ڕەسەنایەتیەوە بۆ دڵنیابوون + description_html: ئەگەر تۆ <strong> هاتنەژوورەوەی دوو قۆناغی</strong> بە یارمەتی ئەپێکی پەسەندکردن چالاک بکەن، پێویستە بۆ چوونەژوورەوە ØŒ بە تەلەÙۆنەکەتان Ú©Û• کۆدیکتان بۆ دروستدەکات دەستپێگەیشتنتان هەبێت. + enable: چالاککردن + instructions_html: "<strong> QR بدۆزەوە بۆ ناو ڕەسەنایەتی گووگڵ یان کاربەرنامەی TOTP هاوشێوە لەسەر تەلەÙۆنەکەت </strong>. Ù„Û• ئێستاوە، ئەو کاربەرنامەیە نیشانە دروست دەکات Ú©Û• دەبێت داخڵیان بکەیت لەکاتی چوونە ژوورەوە." + manual_instructions: 'ئەگەر ناتوانیت کۆدی QR سکان بکەیت Ùˆ پێویستە بە دەستی تێبنووسە، ئەمە نهێنیی دەقی سادەیە:' + setup: ئامادەکردن + wrong_code: کۆدی داخڵکراو نادروستە! ئایا کاتی ڕاژە Ùˆ کاتی ئامێر راستن? + pagination: + newer: نوێتر + next: داهاتوو + older: کۆنتر + prev: پێشوو + truncate: "…" + polls: + errors: + already_voted: تۆ پێشتر دەنگت داوە لەسەر ئەم ڕاپرسییە + duplicate_options: خاوەنی ئایەمی دووبارە + duration_too_long: Ù„Û• داهاتوو زۆر دوورە + duration_too_short: Ù„Û• داهاتوو زۆر نزیکە + expired: ڕاپرسیەکە پێشتر کۆتایی هاتووە + invalid_choice: بژاردەی دەنگدانی هەڵبژێردراو بوونی نییە + over_character_limit: ناتوانێت هەر کامێکی درێژتر بێت Ù„Û• %{max} نووسە + too_few_options: پێویستە زیاتر Ù„Û• یەک بڕگەی هەبێت + too_many_options: ناتوانێت زیاتر Ù„Û• %{max} بەندی تێدا بێت + preferences: + other: Ù‡ÛŒ تر + posting_defaults: بڵاوکردنی بنەڕەتەکان + public_timelines: Ù‡ÛŽÚµÛŒ کاتی گشتی + reactions: + errors: + limit_reached: سنووری کاردانه وه ÛŒ جیاواز Ú¯Ù‡ یشت + unrecognized_emoji: ئیمۆجییەکی ناسراو نییە + relationships: + activity: چالاکی هەژمارە + dormant: ناچالاک + follow_selected_followers: شوێنکەوتوان دیاریکراو بکە + followers: شوێنکەوتوان + following: شوێن‌کەوتووی + invited: بانگهێشتەکان + last_active: دوایین چالاکی + most_recent: تازەترین + moved: گوێزرایەوە + mutual: دوولایەنە + primary: سەرەتایی + relationship: پەیوەندی + remove_selected_domains: لابردنی هەموو شوێنکەوتوانی دۆمەینە دیاریکراوەکان + remove_selected_followers: شوێنکەوتوانی دیاریکراو لابدە + remove_selected_follows: کۆتایی بە بەدوادانەچوی بەکارهێنەرە دیاریکراوەکان بدە + status: دۆخی هەژمارە + remote_follow: + acct: ناونیشانی هەژمارەی username@domainخۆت لێرە بنووسە + missing_resource: نەیتوانی URLÛŒ ئاراستەکردنەوەی پێویست بدۆزێتەوە بۆ ئەژمێرەکەت + no_account_html: هێشتا نەبووی بە ئەندام؟ <a href='%{sign_up_path}' target='_blank'>لێرە دەتوانی هەژمارەیەک دروست بکەی</a> + proceed: بەردەوام بە بۆ بەدواداچوون + prompt: 'تۆ بەدوای دا دەچیت:' + reason_html: "<strong> بۆچی ئەم هەنگاوە پێویستە؟ </strong> <code>%{instance}</code> لەوانەیە ئەو ڕاژەیە نەبێت Ú©Û• تۆ تۆمارت کردووە، بۆیە پێویستە سەرەتا دووبارە ئاڕاستەت بکەین بۆ ڕاژەکاری ماڵەوەت." + remote_interaction: + favourite: + proceed: بۆ دڵخوازکردنی ئەم توتە + prompt: 'دەتەوێت ئەم تووتە تپەسەند بکەیت؛:' + reblog: + proceed: بەردەوام بە بۆ دووبارە توتاندن + prompt: 'دەتەوێت ئەم تووتە دووبارە بکەیتەوە:' + reply: + proceed: بۆ وەڵامدانەوە + prompt: 'دەتەوێت ئەم تووتە وڵام بدەیتەوە:' + scheduled_statuses: + over_daily_limit: ئێوە Ù„Û• سنووری ڕیپێدراوی %{limit} توتی ئەو رۆژە،خۆرتر ڕۆیشتوویت + over_total_limit: تۆ سنووری خشتەکراوی %{limit} ت بەزاندووە + too_soon: پێویستە بەرواری خشتەکراو Ù„Û• داهاتوودا بێت + sessions: + activity: دوایین چالاکی + browser: وێبگەڕ + browsers: + alipay: Alipay + blackberry: بلاکبێری + chrome: کرۆم + edge: Ù…Ø§ÛŒÚ©Ø±Û†Ø³Û†ÙØª ئیچ + electron: ئەلکترۆن + firefox: ÙØ§ÛŒÛ•رÙۆکس + generic: وێبگەڕی نەناسراو + ie: ئینتێرنێت ئێکسپلۆرەر + micro_messenger: مایکرۆمێسنجەر + nokia: وێبگەڕی نۆکیا ئێس ٤٠ئۆڤی + opera: ئۆپێرا + otter: ئۆتەر + phantom_js: ÙØ§Ù†ØªÛ†Ù… جەی ئێس + qq: وێبگەڕی QQ + safari: Ø³Ø§ÙØ±ÛŒ + uc_browser: وێبگەڕی UC + weibo: Weibo + current_session: دانیشتنی ئێستا + description: "%{browser} لەسەر %{platform}" + explanation: ئەمانە وێبگەڕەکەن Ú©Û• ئێستا چووەتە ژوورەوە بۆ ئەژمێری ماستۆدۆنی خۆت. + ip: ئای‌پی + platforms: + adobe_air: Adobe Air + android: ئەندرۆید + blackberry: بلاکبێری + chrome_os: سیستەمی کارگێڕی کرۆم + firefox_os: سیستەمی کارگێڕی ÙØ§ÛŒÛ•رÙۆکس + ios: iOS + linux: لینۆکس + mac: ماک + other: سیستەمیکارگێڕی نەناسراو + windows: ویندۆز + windows_mobile: ویندۆزموبایل + windows_phone: ویندۆزÙÛ†Ù† + revoke: بەتاڵکردن + revoke_success: دانیشتن بەسەرکەوتوویی بەتاڵکرا + title: کۆبوونەوەکان + settings: + account: هەژمارە + account_settings: ڕێکخستنەکانی هەژمارە + aliases: نازناوەی هەژمارە + appearance: ڕووخسار + authorized_apps: ئەپەکانی ڕێگەپێدراو + back: گەڕانەوە بۆ ماستۆدۆن + delete: سڕینەوەی هەژمارە + development: گەشەپێدان + edit_profile: دەستکاری Ù¾Ø±Û†ÙØ§ÛŒÙ„ + export: ناردن زانیاری + featured_tags: هاشتاگی تایبەت + identity_proofs: سەلماندنی ناسنامە + import: هاوردن + import_and_export: هاوردەکردن Ùˆ ناردن + migrate: گواستنەوەی هەژمارە + notifications: ئاگادارییەکان + preferences: پەسەندەکان + profile: Ù¾Ø±Û†ÙØ§ÛŒÙ„ + relationships: شوێنکەوتوو Ùˆ شوێنکەوتوان + two_factor_authentication: کۆدی دووقۆناغی هاتنەژوور + webauthn_authentication: کلیلەکانی پاراستن + spam_check: + spam_detected: ئەمە هەژمارەیەکی خۆکارانەیەبۆ ناساندنی سپام. + statuses: + attached: + audio: + one: "%{count} دەنگ" + other: "%{count} دەنگ" + description: 'هاوپێچ: %{attached}' + image: + one: "%{count} ÙˆÛŽÙ†Û•" + other: "%{count} وێنەکان" + video: + one: "%{count} ڤیدیۆ" + other: "%{count} ڤیدیۆکان" + boosted_from_html: توکراوەتەوە لەلایەن %{acct_link} + content_warning: 'ئاگاداری ناوەڕۆک: %{warning}' + disallowed_hashtags: + one: 'هاشتاگی ڕێگەپێنەدراوەی تێدابوو: %{tags}' + other: 'هاشتاگەکانی ڕێگەپێنەدراوەی تێدابوو: %{tags}' + errors: + in_reply_not_found: ئەو دۆخەی Ú©Û• تۆ Ù‡Û•ÙˆÚµÛŒ وەڵامدانەوەی دەدەیت وادەرناکەوێت Ú©Û• هەبێت. + language_detection: بە شێوەیەکی خۆکارانە زمان بدۆزیەوە + open_in_web: کردنەوە Ù„Û• وێب + over_character_limit: سنووری نووسەی %{max} تێپەڕێنرا + pin_errors: + limit: تۆ پێشتر زۆرترین ژمارەی توتتی چەسپیوەت هەیە + ownership: نووسراوەکانی تر ناتوانرێ بسەلمێت + private: توتی ناگشتی ناتوانرێت بچەسپێ + reblog: بەهێزکردن ناتوانرێت بچەسپێ + poll: + total_people: + one: "%{count} کەس" + other: "%{count} خەڵک" + total_votes: + one: "%{count} دەنگ" + other: "%{count} دەنگەکان" + vote: دەنگ + show_more: زیاتر پیشان بدە + show_newer: نوێتر پیشان بدە + show_older: پیشاندانی کۆنتر + show_thread: نیشاندانی ڕشتە + sign_in_to_participate: بچۆ ژوورەوە بۆ بەشداریکردن Ù„Û• Ú¯ÙØªÙˆÚ¯Û†Ú©Û•دا + title: '%{name}: "%{quote}"' + visibilities: + private: شوێنکەوتوانی تەنها + private_long: تەنها بۆ شوێنکەوتوانی پیشان بدە + public: گشتی + public_long: هەموو کەس دەتوانێت ببینێت + unlisted: پێرست نەبووە + unlisted_long: هەموو کەس دەتوانێت بیبینێت، بەڵام Ù„Û• Ù‡ÛŽÚµÛŒ کاتی گشتی دا نەریزراوە + stream_entries: + pinned: توتی چەسپکراو + reblogged: بەهێزکردن + sensitive_content: ناوەڕۆکی هەستیار + tags: + does_not_match_previous_name: Ù„Û•Ú¯Û•Úµ ناوی پێشوو یەک ناگرێتەوە + terms: + body_html: | + <h2>سیاسەتی تایبەت</h2> + <h3 id="collect">Ú† زانیاریێک Ú©Û† دەکەینەوە؟</h3> + <ul> + <li><em>زانیاری ئەژمێری بنەڕەتی</em>: ئەگەر تۆ لەسەر ئەم ڕاژەی تۆماربکەیت، لەوانەیە داوات لێبکرێت ناوی بەکارهێنەر، ناونیشانی ئیمەیڵ Ùˆ نهێنوشە تێبنووسیت. هەروەها دەتوانیت زانیاری Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ زیاتر تێبنووسی ت ÙˆÛ•Ú© ناوی پیشاندان Ùˆ ژیاننامە، Ùˆ بارکردنی ÙˆÛŽÙ†Û•ÛŒ Ù¾Ø±Û†ÙØ§ÛŒÙ„ Ùˆ ÙˆÛŽÙ†Û•ÛŒ سەرپەڕە. ناوی بەکارهێنەر، ناوی پیشاندان، ژیاننامە، ÙˆÛŽÙ†Û•ÛŒ Ù¾Ø±Û†ÙØ§ÛŒÙ„ Ùˆ ÙˆÛŽÙ†Û•ÛŒ سەرپەڕە هەمیشە بە ئاشکرا لیست کراوە.</li> + <li><em> پۆستەکان، بەدواکەوتن Ùˆ زانیاری گشتی </em>: لیستی ئەو کەسانەی Ú©Û• پەیڕەوی دەکەیت بە ئاشکرا لیست کراوە، هەمان شت بۆ شوێنکەوتەکانت ڕاستە. کاتێک ئیمەیڵێکت Ù¾ÛŽØ´Ú©Û•Ø´ کرد، بەروار Ùˆ کات خەزن کراوە Ùˆ هەروەها ئەو بەرنامەیەی Ú©Û• نامەکەت Ù„Û•ÙˆÛ• Ù¾ÛŽØ´Ú©Û•Ø´ کردووە. نامەکان لەوانەیە هاوپێچی میدیای تێدابێت، ÙˆÛ•Ú© ÙˆÛŽÙ†Û• Ùˆ ڤیدیۆ. گشتی Ùˆ لیستە نەکراوەکان بابەتەکان بە ئاشکرا بەردەستن. کاتێک بابەتێک Ù¾ÛŽØ´Ú©Û•Ø´ دەکەیت لەسەر Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت، Ú©Û• هەروەها زانیاری بەردەستی گشتیە. بابەتەکانت دەگەیەنینە شوێنکەوتەکانت، Ù„Û• هەندێک ØØ§ÚµÛ•تدا مانای وایە دەگەیەنینە ڕاژەکاری جیاواز Ùˆ کۆپیەکان Ù„Û•ÙˆÛŽ هەڵگیراون. کاتێک بابەتەکان دەسڕیتەوە، ئەمە بە هەمان شێوەیە دەگەیەنیتە شوێنکەوتوانی خۆت. کاری سەرلێبڕین یان بە دڵنییاکردنی پۆستی تر هەمیشە گشتیە.</li> + <li><em> ڕاستەوخۆ Ùˆ تەنها شوێنکەوتوانی بابەتەکان</em>: هەموو بابەتەکان خەزن کراون Ùˆ Ù„Û• ڕاژەکارەکە دا پرۆسەکراون. پۆست تەنها شوێنکەوتوانی خۆت دەگەیەنینە شوێنکەوتوانی خۆت Ùˆ بەکارهێنەران Ú©Û• تێیدا باس دەکرێت، Ùˆ پۆستی ڕاستەوخۆش تەنها دەگەیەنینە ئەو بەکارهێنەرانەی Ú©Û• ئاماژەیان پێکراوە Ù„Û• هەندێک ØØ§ÚµÛ•تدا واتە دەگەیەنینە ڕاژەی جیاوازەکان Ùˆ کۆپیەکان Ù„Û•ÙˆÛŽ هەڵگیراون ئێمە Ù‡Û•ÙˆÚµÛŒ باوەڕێکی باش دەکەین بۆ سنووردارکردنی گەیشتن بەو پۆستانە تەنها بۆ کەسانی ڕێگەپێدراو، بەڵام لەوانەیە ڕاژەکارەکانی تر سەرکەوتوو نەبوون. بۆیە گرنگە پێداچوونەوە بە سێرڤەرەکان بکەیت Ú©Û• شوێنکەوتوانی تۆ Ù‡ÛŒ ئەوەن. لەوانەیە بژاردەیەک بگۆڕیت بۆ پەسەندکردن Ùˆ ڕەتکردنەوەی شوێنکەوتوانی نوێ بە دەستی Ù„Û• ڕێکبەندەکان. <em> تکایە Ù„Û• بیرت بێت Ú©Û• کارپێکەرەکانی سێرڤەرەکە Ùˆ هەر خزمەتکاری وەرگرێک لەوانەیە ئەم جۆرە نامانە </em>ØŒ Ùˆ وەرگرەکان لەوانەیە گرتەی شاشە یان Ú©Û†Ù¾ÛŒ بکەن یان بە پێچەوانەوە دووبارە بەشداری پێبکەن. <em> هیچ زانیاریەکی مەترسیدار لەسەر ماستۆدۆن بڵاو</em></li> + <li><em>ئای Ù¾ÛŒ Ùˆ مێتاداتای تر</em>: کاتێک دەچیتە ژوورەوە، ئێمە ئەو ئای Ù¾ÛŒ Û• تۆمار دەکەین Ú©Û• تۆ Ù„Û• ناوی Û•ÙˆÛ• داخڵ تدەکەیت، هەروەها ناوی بەرنامەی وێبگەڕەکەت. هەموو ئەو کۆکراوانەی Ù„Û• کۆبوونەوەکاندا Ù‡Û•Ù† بۆ پێداچوونەوە Ùˆ بەتاڵکردنەوەت Ù„Û• ڕێکبەندەکان. نوێترین ناونیشانی IP بەکارهێنراوە خەزن کراوە بۆ ١٢ مانگ. هەروەها لەوانەیە ئێمە مادە ڕاژەکارەکان بهێڵین Ú©Û• ئای Ù¾ÛŒ ئەدرێسی هەموو داواکارییەک بۆ ڕاژەکارەکانمان </li> + </ul> + < hr="spacer" /> + + <h3 id="use">ئێمە زانیاری ئێوەمان بۆ چییە؟</h3> + + <p> ئەو زانیاریانەی Ù„Û• ئێوە Ú©Û†ÛŒ دەکەین لەوانەیە بەم ڕێگایانە بەکار بهێنرێت:</p> + + <ul> + <li> بۆ دابینکردنی ئەرکە سەرەکیەکانی ماستۆدۆن. دەتوانیت تەنها کارلێک بکەیت Ù„Û•Ú¯Û•Úµ ناوەڕۆکی کەسانی تر Ùˆ ناوەڕۆکی خۆت پۆست بکەیت کاتێک دەچیتە ژوورەوە. بۆ نموونە، لەوانەیە شوێن کەسانی تر بکەویت بۆ بینینی پۆستە تێکەڵەکانیان Ù„Û• تایم لاینی ماڵەوەی تایبەتی خۆت.</li> + <li> بۆ چاودێری کردنی کۆمەڵگا، بۆ نموونە بەراوردکردنی ناونیشانی IPەکەت Ù„Û•Ú¯Û•Úµ کەسانی ناسراو بۆ دیاریکردنی خۆدزینەوە یان پێشێلکاریتر.</li> + <li> ئەو ئیمەیڵەی Ú©Û• تۆ دەستەبەرت کردووە لەوانەیە بەکاربێت بۆ ناردنی زانیاری، ئاگاداری دەربارەی کەسانی تر Ú©Û• کارلێک دەکەن Ù„Û•Ú¯Û•Úµ ناوەڕۆکەکەت یان ناردنی نامەکانت، Ùˆ وەڵامدانەوەی پرسیارکردنەکان، Ùˆ/یان داواکارییان یان پرسیارەکانی تر.</li> + </ul> + < hr="spacer" /> + + <h3 id="بپارێزە"> Ú†Û†Ù† زانیاریەکەت دەپارێزین؟</h3> + + <p> ئێمە چەندین پێوانەی ئەمنی جۆراوجۆر جێبەجێ دەکەین بۆ پاراستنی سەلامەتی زانیاری Û• تایبەتیەکانت کاتێک تۆ داخڵت کردووە یان پێشکەشکردن یان چوونە ژوورەوە بۆ زانیاری تایبەتی. Ù„Û• نێوان شتەکانی تردا، دانیشتنی وێبگەڕەکەت، هەروەها تراÙیکی نێوان کاربەرنامەکانت Ùˆ APIØŒ بە SSL پارێزراوە، Ùˆ نهێنوشەکەت بە بەکارهێنانی ئەلگاریتمی یەک-Ú•ÛŽÚ¯Û•ÛŒ بەهێز بە هاوسێکراوە. دەتوانیت سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر بەتوانا بکەیت بۆ زیاتر پاراستنی چوونە ژوورەوە بۆ ئەژمێرەکەت.</p> + + < hr="spacer" /> + < hr="spacer" /> + + <h3 id="داتا-هێشتنەوە"> بیمەنامەی هێشتنەوە داتامان چییە؟</h3> + + <p> ئێمە بە باشی Ù‡Û•ÙˆÚµ بۆ باوەڕەکان </p> + + <ul> + <li> سێرڤەری پاراستنی ناونووسەکان Ú©Û• ناونیشانی ئای Ù¾ÛŒ تێدایە بۆ هەموو داواکاریەکان بۆ ئەم سێرڤەرە، تا ئێستا ÙˆÛ•Ú© ئەو جۆرە لۆگانە پارێزراون، زیاتر Ù„Û• 90 Ú•Û†Ú˜.</li> + <li> ئای پیەکە بپارێزە Ú©Û• پەیوەندی بە بەکارهێنەرە تۆمارکراوەکان هەیە زیاتر Ù„Û• 12 مانگ.</li> + </ul> + <p> دەتوانیت داواکاری Ùˆ داگرتنی ئەرشیÙÛŒ ناوەڕۆکەکەت بکەیت، لەوانە بابەتەکانت، هاوپێچەکانی میدیا، ÙˆÛŽÙ†Û•ÛŒ Ù¾Ø±Û†ÙØ§ÛŒÙ„ØŒ Ùˆ ÙˆÛŽÙ†Û•ÛŒ سەرپەڕە.</p> + + <p> تۆ دەتوانیت بە شێوەیەکی نائاسایی ئەژمێرەکەت بسڕیتەوە Ù„Û• هەر کاتێکدا.</p> + + < hr="spacer"/> + + <h3 id="کۆکیز"> ئایا ئێمە کۆکیز بەکار بێنە؟</h3> + + <p> بەڵێ کۆکیزەکان ÙØ§ÛŒÙ„ÛŒ بچووکن Ú©Û• سایتێک یان دابینکەری خزمەتگوزاریەکەی دەیگوێزێتەوە بۆ هارد درایڤی کۆمپیوتەرەکەت Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ وێبگەڕەکەت (ئەگەر ڕێگەت Ù¾ÛŽ بدەیت). ئەم کۆکیزانە وێبسایتە بەتوانا دەکەن بۆ ناسینەوەی وێبگەڕەکەت و، ئەگەر ئەژمێرێکی تۆمارکراوت هەیە، بیبەستە بە ئەژمێری تۆمارکراو.</p> + + <p> کۆکیز بەکاربێنە بۆ تێگەیشتن Ùˆ هەڵگرتنی پەسەندیەکانی تۆ بۆ سەردانەکانی داهاتوو.</p> + + < hr="spacer" /> + + <h3 ="ئاشکرا</h3> > ئایا هیچ زانیارییەک بۆ ØØ²Ø¨Û•کانی دەرەوە ئاشکرا دەکەین؟ + + <p> ئێمە زانیاریە تایبەتەکانت Ù†Ø§ÙØ±Û†Ø´ÛŒÙ†ØŒ بازرگانی دەکەین، یان ناگوازرێتەوە بۆ ØØ²Ø¨Û•کانی دەرەوە. ئەمە لایەنی سێیەمی باوەڕپێکراو ÛŒ تێدا نییە Ú©Û• یارمەتیمان دەدات Ù„Û• کارپێکردنی سایتەکەمان، ئەنجامدانی کارەکانمان، یان خزمەتکردنی ئێوە، هەتا ئەو ØØ²Ø¨Ø§Ù†Û• ڕازی بن بە نهێنی هێشتنەوەی ئەم زانیاریانە. هەروەها لەوانەیە زانیاریەکەت بڵاوکەینەوه کاتێک پێمان وایە ئازادکردن گونجاوە بۆ پابەندبوون بە یاسا، سەپاندنی سیاسەتی ماڵپەڕەکەمان، یان پاراستنی ماÙەکانمان یان ماÙÛŒ تر، موڵک، یان سەلامەتی.</p> + + <p> لەوانەیە ناوەڕۆکی گشتیت دابەزێنرابێت لەلایەن خزمەتگوزاریەکانی ترەوە Ù„Û• تۆڕەکەدا. پۆستە گشتی Ùˆ تەنها شوێنکەوتوانی تۆ دەگەیەنینە ئەو سێرڤەرانەی Ú©Û• شوێنکەوتوانی تێیدا نواندووە، Ùˆ پەیامی ڕاستەوخۆ دەگەیەنینە خزمەتکارەکانی وەرگرەکان، Ù„Û• دووری ئەوەی Ú©Û• شوێنکەوتوانی یان وەرگرەکان Ù„Û• سێرڤەرێکی جیاواز Ù„Û•Ù….</p> + + <p> کاتێک تۆ مۆڵەت بە کاربەرنامەیەک بدەیت بۆ بەکارهێنانی ئەژمێرەکەت، بەگوێرەی مەودای مۆڵەتەکانت Ú©Û• پەسەندت کردووە، لەوانەیە بچێتە ناو زانیاری Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ گشتی، لیستی خوارەوەت، شوێنکەوتوانی تۆ، لیستەکانت، هەموو بابەتەکانت، Ùˆ دڵراوەکانی تۆ. کاربەرنامەکان هەرگیز ناتوانن دەستگەیشتنیان هەبێت بە ناونیشانی ئیمەیڵ یان نهێنوشە.</p> + < hr="spacer" /> + + <h3 id="منداڵان"> بەکارهێنانی سایت لەلایەن منداڵانەوە</h3> + + <p> ئەگەر ئەم سێرڤەرە Ù„Û• یەکێتی ئەورووپا یان ئی ئی ئی ئەی بێت: ماڵپەڕ، بەرهەم Ùˆ خزمەتگوزارییەکانی ئێمە هەموویان ئاراستەی ئەو کەسانە دەکرێت Ú©Û• بە لایەنی Ú©Û•Ù…Û•ÙˆÛ• 16 ساڵ Ù†. ئەگەر تەمەنت Ù„Û• خوار 16 ساڵەوە بێت، Ù„Û• سەر پێداویستی GDPR (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">General Data Protection Regulation</a>) ئەم سایتە بەکارمەهێنیت.</p> + + <p> ئەگەر ئەم سێرڤەرە Ù„Û• ئەمریکا بێت: ماڵپەڕ Ùˆ بەرهەم Ùˆ خزمەتگوزاریەکانمان هەمووی ئاراستەی ئەو کەسانە دەکرێت Ú©Û• بە لایەنی Ú©Û•Ù…Û•ÙˆÛ• 13 ساڵ Ù†. ئەگەر تۆ Ù„Û• خوار تەمەنی 13 ساڵیەوەبیت، Ù„Û• سەر داواکاریەکانی COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Children's Online Privacy Protection act</a>) ئەم سایتە بەکارمەهێنیت.</p> + + <p> یاسا دەتوانێت جیاواز بێت ئەگەر ئەم سێرڤەرە Ù„Û• دەسەڵاتی دادوەری تر بێت.</p> + + < hr="spacer" /> + + <h3 id="گۆڕانکاریەکان"> گۆڕانکاریەکان Ù„Û• سیاسەتی تایبەتمەندیمان</h3> + + <p> ئەگەر بڕیارمان دا سیاسەتی تایبەتمەندیمان بگۆڕین، ئەو گۆڕانکاریانە Ù„Û•Ù… پەڕەیە بڵاودەکەینەوە.</p> + + <p> ئەم دۆکیومێنتە CC-BY-SA Û•. دوایین جار نوێکرایەوە Ù„Û• 7ÛŒ ئازاری 2018.</p> + + <p> Ù„Û• بنەڕەتدا Ù„Û• < href="https://github.com/discourse/discourse">Discourse privacy policy</a>.</p> + title: "%{instance} مەرجەکانی خزمەتگوزاری Ùˆ سیاسەتی تایبەتیێتی" + themes: + contrast: ماستۆدۆن (کۆنتراستی بەرز) + default: ماستۆدۆن (Ú•Û•Ø´) + mastodon-light: ماستۆدۆن (کاڵ) + time: + formats: + default: "%b %d, %Y, %H:%M" + month: "%b %Y" + two_factor_authentication: + add: زیادکردن + disable: لەکارخستنی 2FA + disabled_success: سەلماندنی سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر بە سەرکەوتوویی لەکارخراوە + edit: دەستکاری + enabled: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر چالاک کراوە + enabled_success: سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر بە سەرکەوتوویی چالاک کرا + generate_recovery_codes: دروست کردنی کۆدی چاککردنەوە + lost_recovery_codes: کۆدی گەڕاندنەوە ڕێگەت Ù¾ÛŽ دەدات Ú©Û• دەستگەیشتنت بۆ هەژمارەکەت بەدەست بهێنێ ئەگەر تەلەÙۆنەکەت لەدەست بدەیت. ئەگەر کۆدەکانی چاکبوونەوەت لەدەست داوە، دەتوانیت لێرە دووبارە دروستیان Ú©Û•ÛŒ. کۆدی چاککردنەوەی کۆنت هەڵدەوەشێنێتەوە. + methods: دوو - میتۆدی ÙØ§Ú©ØªÛ•ر + otp: ئەپی ڕاستەوە + recovery_codes: پاڵپشتکردن Ù„Û• کۆدی هێنانەوەی + recovery_codes_regenerated: کۆدی گەڕاندنەوە بە سەرکەوتوویی دووبارە دروست بوویەوە + recovery_instructions_html: گەر تەلەÙۆنەکەت بزر کرد دەتوانی بە یەکێک Ù„Û• کۆدەکانی خوارەوە چاودێری هەژمارەکەت Ù„Û• دەست بگریت.<strong>ائەم کۆدانە Ù„Û• شوێنێکی پاراو هەڵبگرە</strong> بۆ نموونە چاپی بکەن یان Ù„Û•Ú¯Û•Úµ بەڵگەنامە گرینگەکانت دایبنێ. + webauthn: کلیلەکانی پاراستن + user_mailer: + backup_ready: + explanation: ئێوە وشانێکی پاڵپشتی تەواوت Ù„Û• هەژمارەکەی خۆت داوا کردووە، ئەم پاڵپشتییە ئێستا ئامادەی بارکردنە! + subject: ئارشیڤی ئێوە ئامادەی داگرتنە + title: وەرگرتنی ئارشیڤ + sign_in_token: + details: 'وردەکاریی هەوڵەکان:' + explanation: 'Ù‡Û•ÙˆÚµÛŽÚ© بۆ هاتنە Ù†ÛŽÙˆ هەژمارەکەتان Ù„Û• ناونیسانێکی ئای‌پی پەیداکرا. گەر خۆتانن. تێپەڕوشەی پاراستن بۆ Ù¾Û•Ú•Û•ÛŒ بەرنگاری دابین بکە:' + further_actions: 'گەر ئێوە نیین تکایە تێپەڕوشە بگۆڕە ÙˆÛ• لێرەوە پەسەند بوونی دوو قۆناغی Ù„Û• سەر هەژمارەکەتان چالاک بکەن:' + subject: تکایە دڵنیابە Ù„Û• هەوڵدان بۆ چوونە ژوورەوە + title: هەوڵدان بۆ چوونە ژوورەوە + warning: + explanation: + disable: تا کاتێک هەژمارەی ئێوە نەوێستاوە، دراوەکانی ئێوە دەستکاری ناکرێت.بەڵام تا کاتێک Ú©Û• هەژمارەکەتان ناکرێتەوە. ناتوانن هیچ ئیشێکی لەسەر بکەن. + sensitive: Ù¾Û•Ú•Ú¯Û• میدیایە بارکراوەکانت Ùˆ میدیا لینککراوەکانت ÙˆÛ•Ú© هەستیار مامەڵەیان Ù„Û•Ú¯Û•Úµ دەکرێت. + silence: تا کاتیک هەژمارەکەتان سنووردار بێت، تەنها ئەو کەسانە Ú©Û• پێشتر شوێنکەوتووی ئێوە بوون نووسراوەکانی ئێوە Ù„Û•Ù… ڕاژە دەبینن. شایەد ئێوە Ù„Û• زۆر پێرستی گشتی دیار نەکەون؛ بەڵام خەڵکانی دیکە دەتوانن بە دڵی خۆیان پەیگیری ئێوە بن. + suspend: هەژمارەکەتان هەڵواسراوە، ÙˆÛ• تەواو توت Ùˆ میدیاکان Ú©Û• لەسەر ئەم ڕاژە بارتان کردووە یان ئەو ڕاژانە Ú©Û• شوێنکەوتووتان Ù„Û• سەری بووە ئیتر ناگەڕێنەوە. + get_in_touch: بە وڵام دانەوەی ئەم ئیمەیلە دەتوانن Ù„Û• Ú¯Û•Úµ لیژنەی %{instance} Ù„Û• پەیوەندی بن. + review_server_policies: پێداچوونەوەی سیاسەتەکانی ڕاژە + statuses: 'بە دیاریکراوی، بۆ:' + subject: + disable: هەژمارەکەت %{acct} بەستراوە + none: ئاگاداری بۆ %{acct} + sensitive: هەژمارەکەت %{acct} میدیایەکی پۆست کردن بە هەستیار نیشان کراوە + silence: هەژمارەکەی %{acct} سنووردار کراوە + suspend: هەژمارەکەی %{acct} ڕاگیرا + title: + disable: هەژمارە بەستراوە + none: ئاگاداری + sensitive: میدیاکەت بە هەستیار نیشان کراوە + silence: هەژماری سنووردار + suspend: هەژمار ڕاگیرا + welcome: + edit_profile_action: Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ جێگیرکردن + edit_profile_step: 'ئێوە دەتوانن Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەتان بە دڵخوازی خۆتان بگۆڕن: دەتوانن ÙˆÛŽÙ†Û•ÛŒ Ù¾Ø±Û†ÙØ§ÛŒÙ„،وێنەی پاشبنەما،ناو Ùˆ... هتد دابین بکەن. ئەگەر هەرەکت بێت دەتوانی هەژمارەکەت تایبەت بکەیتەوە تا تەنها کەسانێک Ú©Û• ئێوە ڕێگەتان داوە دەتوانن شوێنکەوتوو هەژمارەکەتان بن.' + explanation: ئەمە چەند ئامۆژگارییەکن بۆ دەست پێکردنت + final_action: دەست بکە بە بڵاوکردنەوە + final_step: 'چیزی بنووسید! تەنانەت گەر ئێستا کەسێک شوێن کەوتووی ئێوە نەبوو، هەژمارەکانی دیکە Ùˆ سەردانکەرەکانی Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەتان نووسراوەکانی گشتی ئێوە دەبینن. بۆ نموونە Ù„Û• پێرستی نووسراوە خۆماڵییەکان Ùˆ Ù„Û• لکاوەی(هاشتاگ) ەکان، شایەد هەرەکتان بێت بە چەسپکراوەی # خۆتان بناسێنن.' + full_handle: ناوی بەکارهێنەری تەواوی ئێوە + full_handle_hint: ئەمە ئەو شتەیە Ú©Û• بە هاوڕێکانت دەلێی بۆ ئەوەی پەیام یان Ù„Û• ڕاژەیەکی دیکەی ترەوە بەدوات بکەون. + review_preferences_action: گۆڕینی پەسەندەکان + review_preferences_step: دڵنیابە Ù„Û• دانانی پەسەندکراوەکانت، ÙˆÛ•Ú© کام ئیمەیل Ú©Û• دەتەوێت وەریبگرێ، یان دەتەوێت Ú† ئاستێکی تایبەتیت بۆ بابەتەکانت Ù¾ÛŽØ´ گریمانە بێت. ئەگەر نەخۆشی جوڵەت(دڵ تێکەڵدان Ù„Û• ÙˆÛŽÙ†Û• جووڵەییەکان) نیە، دەتوانیت هەڵبژێریت بۆ بەتواناکردنی پەخشکردنی خۆکاری GIF. + subject: بەخێربیت بۆ ماستۆدۆن + tip_federated_timeline: پێرستی نووسراوەکانی هەمووشوێنێک وێنەیەکی گشتی Ù„Û• تۆڕی ماستۆدۆنە، بەڵام تەنها بریتییە Ù„Û• هاوسێکان Ú©Û• شوێنیان کەوتن؛بس تەواو نییە. + tip_following: بە شیوەی بنەڕەتی بەڕێوەبەران ڕاژەکەتان چاودێری دەکەن، بۆ پەداکردنی کەسانی سەرنجڕاکێشە چاودێری نووسراوە ناخۆیی Ùˆ نووسراوەکانی شوێنەکانی دیکە بکەن. + tip_local_timeline: پێرستی نووسراوە ناوخۆییەکان شێوەیەکی تەواو Ù„Û• بەکارهێنەران Ù„Û• سەر %{instance} پیسان دەدەن، ئەمانە جەیرانی ئێوەن! + tip_mobile_webapp: ئەگەر وێبگەڕی مۆبایلەکەت پێشنیاری زیادکردنی ماستۆدۆن بۆ شاشەی ڕوومێزیەکەتی کرد، دەتوانیت ئاگانامەکانی هاندان وەربگری. Ù„Û• زۆر Ú•ÙˆÛ•ÙˆÛ• ÙˆÛ•Ú© بەرنامەیەیەکی ئەسڵی ئیس دەکا! + tips: ئامۆژگاریەکان + title: بەخێربێیت، بەکارهێنەر %{name}! + users: + blocked_email_provider: ئەم دابینکەری ئیمەیڵە رێگەپێدراو نییە + follow_limit_reached: ناتوانیت زیاتر Ù„Û• %{limit} خەڵک پەیڕەو کەیت + generic_access_help_html: کێشەت هەیە Ù„Û• گەیشتن بە هەژمارەکەت؟ دەتوانیت Ù„Û•Ú¯Û•Úµ %{email} بۆ یارمەتیدان پەیوەندی بگرن + invalid_email: ناونیشانی ئیمەیڵەکە نادروستە + invalid_email_mx: Ù„Û•ÙˆÛ• ناچێت ناونیشانی ئیمەیڵ بوونی هەبێت + invalid_otp_token: کۆدی دوو-ÙØ§Ú©ØªÛ•ر نادروستە + invalid_sign_in_token: کۆدی پاراستن دروست نیە + otp_lost_help_html: گەر بەو دووڕێگا نەتوانی بچیتە ژوورەوە، لەوانەیە پەیوەندی بگری بە %{email} بۆ یارمەتی + seamless_external_login: تۆ Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ خزمەتگوزاری دەرەکیەوە داخڵ بووی، بۆیە ڕێکبەندەکانی نهێنوشە Ùˆ ئیمەیل بەردەست نین. + signed_in_as: 'چوونە ژوورەوە ÙˆÛ•Ú©:' + suspicious_sign_in_confirmation: وادیارە تۆ پێشتر Ù„Û•Ù… ئامێرە نەچویتە ژوورەوە، Ùˆ بۆ ماوەیەک نەچویتە ژوورەوە، بۆیە کۆدی پاراستن دەنێردرینە ناونیشانی ئیمەیڵەکەت بۆ دڵنیابوون Ù„Û•ÙˆÛ•ÛŒ Ú©Û• ئەوە تۆیت. + verification: + explanation_html: 'دەتوانیت <strong> خۆت بسەلمێنیت ÙˆÛ•Ú© خاوەنی لینکەکان Ù„Û• مێتاداتای Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت</strong>. بۆ ئەمە، ماڵپەڕە لینککراوەکە پێویستە لینکێکی تێدا بێت بۆ Ù¾Ø±Û†ÙØ§ÛŒÙ„ÛŒ ماستۆدۆنەکەت. بەستەری <strong> دەبێت </strong> هەبێت <code>="me"</code>. ناوەڕۆکی دەقی لینکەکە گرنگ نییە. ئەمە نموونەیەکە:' + verification: ساغ کردنەوە + webauthn_credentials: + add: زیادکردنی کلیلی ئاسایشی نوێ + create: + error: کێشەیەک هەبوو Ù„Û• زیادکردنی کلیلی پاراستنەکەت. تکایە دووبارە Ù‡Û•ÙˆÚµ دەوەشنەوە. + success: کلیلی ئاسایشت بە سەرکەوتوویی زیادکرا. + delete: سڕینەوە + delete_confirmation: ئایا دڵنیایت Ù„Û•ÙˆÛ•ÛŒ دەتەوێت ئەم کلیلی پاراستنە بسڕیتەوە? + description_html: ئەگەر تۆ <strong> کلیلی سەلماندنت</strong> چالاک دەکەی، بۆ چوونە ژوورەوە پێویستت Ù¾ÛŽ دەبێ، یەکێک Ù„Û• کلیلە کانی ئاسایشت بەکاربێنیت. + destroy: + error: کێشەیەک هەبوو Ù„Û• سڕینەوەی کلیلی پاراستنەکەت. تکایە دووبارە Ù‡Û•ÙˆÚµ بدەرەوە. + success: کلیلی ئاسایشت بە سەرکەوتوویی سڕایەوە. + invalid_credential: کۆدی پاراستن دروست نیە + nickname_hint: نازناوی کلیلی ئاسایشی نوێت تێبنووسە + not_enabled: تۆ هێشتا WebAuthnت چالاک نەکردووە + not_supported: ئەم وێبگەڕە پشتگیری کلیلەکانی پاراستن ناکات + otp_required: بۆ بەکارهێنانی کلیلەکانی پاراستن تکایە سەرەتا سەلماندنی دوو-ÙØ§Ú©ØªÛ•ر چالاک بکە. + registered_on: تۆمارکراو Ù„Û• %{date} diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 5a4542ea8c380e0e200cedcdc5c429fb2d9c3dae..0e4bb65bc803dd3e5e62ca4457d56e978b6772d0 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -776,21 +776,14 @@ lt: default: Mastodon (Tamsus) mastodon-light: Mastodon (Å viesus) two_factor_authentication: - code_hint: Ä®veskite autentikacijos aplikacijos sugeneruotÄ… kodÄ… kad galÄ—tumete tÄ™sti - description_html: Jeigu įjungiate <strong>dviejų veiksnių autentikacijÄ…</strong>, prisijungiant jums reikÄ—s turÄ—ti su savimi savo telefonÄ…, kuris jums generuos prisijungimo žetonus. disable: IÅ¡jungti - enable: Ä®jungti enabled: Dviejų veiksnių autentikacija įjungta enabled_success: Dviejų veiksnių autentikacija sÄ—kmingai įjungta generate_recovery_codes: Sugeneruoti atkÅ«rimo kodus - instructions_html: "<strong>Nuskenuokite šį QR kodÄ… į Google Autentikatorių arba panaÅ¡iÄ… TOTP aplikacijÄ… jÅ«sų telefone</strong>. Nuo Å¡iol, Å¡i aplikacija jums generuos žetonus, kurių reikÄ—s norint prisijungti." lost_recovery_codes: AtkÅ«rimo kodai jums leidžia atgauti prisijungimÄ… prie JÅ«sų paskyros, jeigu prarandate telefonÄ…. Jeigu praradote atkÅ«rimo kodus, juos galite sugeneruoti Äia. JÅ«sų senieji atkÅ«rimo kodai nebeveiks. - manual_instructions: 'Jeigu jÅ«s negalite nuskenuoti QR kodo ir turite jį įvesti savarankiÅ¡kai, Å¡tai Äia yra tekstas Å¡iam kodui:' recovery_codes: Atsarginio atkÅ«rimo kodai recovery_codes_regenerated: AtkÅ«rimo kodai sÄ—kmingai sugeneruoti recovery_instructions_html: Jeigu prarandate prieiga prie telefono, jÅ«s galite naudoti atkÅ«rimo kodus esanÄius žemiau, kad atgautumÄ—te priega prie savo paskyros.<strong>Laikykite atkÅ«rimo kodus saugiai</strong> Pavyzdžiui, galite norÄ—ti juos iÅ¡spausdinti, ir laikyti kartu su kitais svarbiais dokumentais. - setup: Nustatyti - wrong_code: Koda netinkamas! Ar serverio laikas ir prietaiso laikas vienodi? user_mailer: backup_ready: explanation: JÅ«s prašėte pilnos Mastodon paskyros atsarginÄ—s kopijos. Ji paruoÅ¡ta parsisiuntimui! diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 5c493be56a71b7eae5c7261157db4cee5d4bf5f6..510458c5e12398c44fb2132032c50ac1318dcf03 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -10,11 +10,3 @@ lv: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/mk.yml b/config/locales/mk.yml index c2cafa5a708d0d4c267b2a5386456ad1dd6847dd..b538272dee40067bee1eb62431540fb50bb67aeb 100644 --- a/config/locales/mk.yml +++ b/config/locales/mk.yml @@ -10,11 +10,3 @@ mk: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/ml.yml b/config/locales/ml.yml index f2731cf04befa95cad715218f93ef770ff479350..2f24ee3ececfef28ec54ee8bd6908c153f41af1c 100644 --- a/config/locales/ml.yml +++ b/config/locales/ml.yml @@ -1,32 +1,52 @@ --- ml: about: + about_this: à´•àµà´±à´¿à´šàµà´šàµ + api: API + apps: മൊബൈൽ ആപàµà´ªàµà´•ൾ + contact: ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´• contact_missing: സജàµà´œà´®à´¾à´•àµà´•ിയിടàµà´Ÿà´¿à´²àµà´² contact_unavailable: à´²à´àµà´¯à´®à´²àµà´² discover_users: ഉപയോഗàµâ€Œà´¤à´¾à´•àµà´•ളെ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´• + get_apps: മൊബൈൽ ആപàµà´ªàµ പരീകàµà´·à´¿à´•àµà´•àµà´• learn_more: കൂടàµà´¤àµ½ പഠികàµà´•àµà´• privacy_policy: à´¸àµà´µà´•ാരàµà´¯à´¤à´¾ നയം see_whats_happening: à´Žà´¨àµà´¤àµŠà´•àµà´•െ സംà´à´µà´¿à´•àµà´•àµà´¨àµà´¨àµ à´Žà´¨àµà´¨àµ കാണàµà´• + source_code: സോഴàµà´¸àµ കോഡൠstatus_count_before: ആരാൽ à´Žà´´àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ tagline: à´¸àµà´¹àµƒà´¤àµà´¤àµà´•àµà´•ളെ പിനàµà´¤àµà´Ÿà´°àµà´•à´¯àµà´‚ à´ªàµà´¤à´¿à´¯à´µà´°àµ† à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•à´¯àµà´‚ ചെയàµà´¯àµà´• terms: സേവന à´µàµà´¯à´µà´¸àµà´¥à´•ൾ unavailable_content: à´²à´àµà´¯à´®à´²àµà´²à´¾à´¤àµà´¤ ഉളàµà´³à´Ÿà´•àµà´•à´‚ unavailable_content_description: + domain: സെർവർ reason: കാരണം what_is_mastodon: à´Žà´¨àµà´¤à´¾à´£àµ മാസàµà´±àµà´±à´¡àµ‹àµº? accounts: follow: പിനàµà´¤àµà´Ÿà´°àµà´• - following: നിങàµà´™àµ¾ പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µàµ¼ + following: പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ joined: "%{date} ൽ ചേർനàµà´¨àµ" last_active: അവസാനം സജീവമായിരàµà´¨àµà´¨à´¤àµ link_verified_on: സനàµà´§à´¿à´¯àµà´Ÿàµ† ഉടമസàµà´¥à´¾à´µà´¸àµâ€Œà´•ാശം %{date} ൽ പരിശോധികàµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ media: മാധàµà´¯à´®à´™àµà´™àµ¾ moved_html: "%{name}, %{new_profile_link} ലേകàµà´•ൠനീങàµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ:" + network_hidden: à´ˆ വിവരം à´²à´àµà´¯à´®à´²àµà´² + nothing_here: ഇവിടെ à´’à´¨àµà´¨àµà´®à´¿à´²àµà´²! + posts_tab_heading: ടൂടàµà´Ÿàµà´•ൾ + posts_with_replies: ടൂടàµà´Ÿàµà´•à´³àµà´‚ മറàµà´ªà´Ÿà´¿à´•à´³àµà´‚ + roles: + admin: à´…à´¡àµâ€Œà´®à´¿à´¨àµâ€ + bot: ബോടàµà´Ÿàµ + group: à´—àµà´°àµ‚à´ªàµà´ªàµ + unavailable: à´ªàµà´°àµŠà´«àµˆàµ½ à´²à´àµà´¯à´®à´²àµà´² admin: account_moderation_notes: delete: മായàµà´•àµà´•àµà´• accounts: + add_email_domain_block: à´‡-മെയിൽ ഡൊമെയàµàµ» തടയàµà´• approve: അംഗീകരികàµà´•àµà´• + approve_all: à´Žà´²àµà´²à´¾à´‚ അംഗീകരികàµà´•àµà´• + are_you_sure: നിങàµà´™àµ¾à´•àµà´•ൠഉറപàµà´ªà´¾à´£àµ‹? + avatar: അവതാർ by_domain: മേഖല change_email: changed_msg: à´…à´‚à´—à´¤àµà´¤à´¿à´¨àµà´±àµ† ഇലകàµà´Ÿàµà´°àµ‹à´£à´¿à´•ൠകതàµà´¤à´¿à´¨àµà´±àµ† മേൽവിലാസം വിജയകരമായി മാറàµà´±à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ! @@ -37,6 +57,8 @@ ml: title: "%{username} à´¨àµà´±àµ† ഇലകàµà´Ÿàµà´°àµ‹à´£à´¿à´•ൠകതàµà´¤àµ മേൽവിലാസം മാറàµà´±àµà´•" confirm: നിജപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´• confirmed: നിജപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿ + confirming: à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ + delete: ഡാറàµà´± ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• deleted: മായിചàµà´šàµ demote: തരം താഴàµà´¤àµà´¤àµà´• disable: à´ªàµà´°à´µà´°àµâ€à´¤àµà´¤à´¨ രഹിതമാകàµà´•àµà´• @@ -44,6 +66,56 @@ ml: disabled: à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨ രഹിതമാകàµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ display_name: കാണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨ നാമം domain: മേഖല + edit: തിരàµà´¤àµà´¤àµà´• + email: ഇമെയിൽ + header: തലകàµà´•െടàµà´Ÿàµ + location: + all: à´Žà´²àµà´²à´¾à´‚ + moderation: + active: സജീവമാണൠ+ all: à´Žà´²àµà´²à´¾à´‚ + resend_confirmation: + send: à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ വീണàµà´Ÿàµà´‚ അയയàµà´•àµà´•àµà´• + success: à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ വിജയകരമായി അയചàµà´šàµ! + reset: à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´• + reset_password: പാസàµâ€Œà´µàµ‡à´¡àµ à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´• + role: à´…à´¨àµà´®à´¤à´¿à´•ൾ + roles: + user: ഉപയോകàµà´¤à´¾à´µàµ + search: തിരയàµà´• + title: à´…à´•àµà´•ൗണàµà´Ÿàµà´•ൾ + unconfirmed_email: à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•ാതàµà´¤ ഇമെയിൽ + username: ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ + web: വെബൠ+ action_logs: + action_types: + confirm_user: ഉപയോകàµà´¤à´¾à´µà´¿à´¨àµ† à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´• + remove_avatar_user: അവതാർ നീകàµà´•ംചെയàµà´¯àµà´• + reset_password_user: പാസàµâ€Œà´µàµ‡à´¡àµ à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´• + custom_emojis: + copy: പകരàµâ€à´¤àµà´¤àµà´• + create_new_category: à´ªàµà´¤à´¿à´¯ വിà´à´¾à´—à´‚ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´• + delete: ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• + emoji: ഇമോജി + dashboard: + feature_profile_directory: à´ªàµà´°àµŠà´«àµˆàµ½ ഡയറകàµà´Ÿà´±à´¿ + features: സവിശേഷതകൾ + title: ഡാഷàµà´¬àµ‡à´¾àµ¼à´¡àµ + total_users: മൊതàµà´¤à´‚ ഉപയോകàµà´¤à´¾à´•àµà´•ൾ + trends: à´Ÿàµà´°àµ†àµ»à´¡àµà´•ൾ + email_domain_blocks: + add_new: à´ªàµà´¤à´¿à´¯à´¤àµ ചേരàµâ€à´•àµà´•àµà´• + delete: ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• + domain: ഡൊമൈനàµâ€ + new: + create: ഡൊമൈൻ ചേരàµâ€à´•àµà´•àµà´• + invites: + filter: + all: à´Žà´²àµà´²à´¾à´‚ + authorize_follow: + following: 'വിജയകരം! നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ:' + directories: + directory: à´ªàµà´°àµŠà´«àµˆàµ½ ഡയറകàµà´Ÿà´±à´¿ errors: '400': The request you submitted was invalid or malformed. '403': You don't have permission to view this page. @@ -54,11 +126,18 @@ ml: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day + filters: + contexts: + notifications: അറിയിപàµà´ªàµà´•ൾ + generic: + all: à´Žà´²àµà´²à´¾à´‚ + notification_mailer: + digest: + action: à´Žà´²àµà´²à´¾ അറിയിപàµà´ªàµà´•à´³àµà´‚ കാണികàµà´•àµà´• + follow: + body: "%{name} ഇപàµà´ªàµ‹àµ¾ നിങàµà´™à´³àµ† പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ!" + subject: "%{name} ഇപàµà´ªàµ‹àµ¾ നിങàµà´™à´³àµ† പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ" + relationships: + following: പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨àµ + settings: + notifications: അറിയിപàµà´ªàµà´•ൾ diff --git a/config/locales/mr.yml b/config/locales/mr.yml index 72228df520f88b3667e7703b3943542255f90e0f..9d7609ea4ba181791d2d737b845568c841e1a3c5 100644 --- a/config/locales/mr.yml +++ b/config/locales/mr.yml @@ -10,11 +10,3 @@ mr: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 3ab48184655f02629445cd8a91bad7fc7513ed5b..089707d03b35435ad45710d5ca00447692a775f3 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -297,14 +297,6 @@ ms: exports: archive_takeout: in_progress: Mengkompil arkib anda... - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day notification_mailer: digest: title: Ketika anda tiada di sini... diff --git a/config/locales/nl.yml b/config/locales/nl.yml index c92b6c1db527ebb674375dc21381beee9bf7af2a..a419e0b47d12ec48402613272bbb12a6b64c6b7b 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -21,7 +21,9 @@ nl: federation_hint_html: Met een account op %{instance} ben je in staat om mensen die zich op andere Mastodonservers (en op andere plekken) bevinden te volgen. get_apps: Mobiele apps hosted_on: Mastodon op %{domain} - instance_actor_flash: Dit account is een virtuel actor dat wordt gebruikt om de server zelf te vertegenwoordigen en is geen individuele gebruiker. Het wordt voor federatiedoeleinden gebruikt en moet niet worden geblokkeerd, tenzij je de hele server wilt blokkeren. In zo'n geval dien je echter een domeinblokkade te gebruiken. + instance_actor_flash: 'Dit account is een virtuel actor dat wordt gebruikt om de server zelf te vertegenwoordigen en is geen individuele gebruiker. Het wordt voor federatiedoeleinden gebruikt en moet niet worden geblokkeerd, tenzij je de hele server wilt blokkeren. In zo''n geval dien je echter een domeinblokkade te gebruiken. + +' learn_more: Meer leren privacy_policy: Privacybeleid see_whats_happening: Kijk wat er aan de hand is @@ -58,6 +60,7 @@ nl: one: Volger other: Volgers following: Volgend + instance_actor_flash: Dit account is een 'virtual actor' waarmee de server zichzelf vertegenwoordigd en is dus geen individuele gebruiker. Het wordt voor federatiedoeleinden gebruikt en moet niet worden opgeschort. joined: Geregistreerd in %{date} last_active: laatst actief link_verified_on: Eigendom van deze link is gecontroleerd op %{date} @@ -96,6 +99,7 @@ nl: add_email_domain_block: E-maildomein blokkeren approve: Goedkeuren approve_all: Alles goedkeuren + approved_msg: Het goedkeuren van het registratieverzoek van %{username} is geslaagd are_you_sure: Weet je het zeker? avatar: Avatar by_domain: Domein @@ -109,22 +113,26 @@ nl: confirm: Bevestigen confirmed: Bevestigd confirming: Bevestiging + delete: Gegevens verwijderen deleted: Verwijderd demote: Degraderen - disable: Uitschakelen + destroyed_msg: De verwijdering van de gegevens van %{username} staat nu in de wachtrij + disable: Bevriezen disable_two_factor_authentication: 2FA uitschakelen - disabled: Uitgeschakeld + disabled: Bevroren display_name: Weergavenaam domain: Domein edit: Bewerken email: E-mail email_status: E-mailstatus - enable: Inschakelen + enable: Ontdooien enabled: Ingeschakeld + enabled_msg: Het ontdooien van het account van %{username} is geslaagd followers: Volgers follows: Volgt header: Omslagfoto inbox_url: Inbox-URL + invite_request_text: Redenen om te registreren invited_by: Uitgenodigd door ip: IP joined: Geregistreerd in @@ -135,7 +143,9 @@ nl: title: Locatie login_status: Loginstatus media_attachments: Mediabijlagen - memorialize: In gedenkpagina veranderen + memorialize: Naar een In memoriam veranderen + memorialized: In memoriam + memorialized_msg: Het naar een In memoriam veranderen van het account van %{username} is geslaagd moderation: active: Actief all: Alles @@ -156,10 +166,14 @@ nl: public: Openbaar push_subscription_expires: PuSH-abonnement verloopt op redownload: Profiel vernieuwen + redownloaded_msg: Het herstellen van het oorspronkelijke profiel van %{username} is geslaagd reject: Afkeuren reject_all: Alles afkeuren + rejected_msg: Het afwijzen van het registratieverzoek van %{username} is geslaagd remove_avatar: Avatar verwijderen remove_header: Omslagfoto verwijderen + removed_avatar_msg: Het verwijderen van de avatar van %{username} is geslaagd + removed_header_msg: Het verwijderen van de omslagfoto van %{username} is geslaagd resend_confirmation: already_confirmed: Deze gebruiker is al bevestigd send: Verzend bevestigingsmail opnieuw @@ -176,22 +190,30 @@ nl: search: Zoeken search_same_email_domain: Andere gebruikers met hetzelfde e-maildomein search_same_ip: Andere gebruikers met hetzelfde IP-adres + sensitive: Gevoelig + sensitized: als gevoelig gemarkeerd shared_inbox_url: Gedeelde inbox-URL show: created_reports: Aangemaakte rapportages targeted_reports: Door anderen gerapporteerd - silence: Negeren - silenced: Genegeerd + silence: Beperken + silenced: Beperkt statuses: Toots subscribe: Abonneren suspended: Opgeschort + suspension_irreversible: De gegevens van dit account zijn onomkeerbaar verwijderd. Je kunt het opschorten van dit account ongedaan maken zodat het weer valt te gebruiken, maar de verwijderde gegevens worden hiermee niet hersteld. + suspension_reversible_hint_html: Dit account is opgeschort en de gegevens worden volledig verwijderd op %{date}. Tot die tijd kan dit account worden hersteld zonder nadelige gevolgen. Wanneer je alle gegevens van dit account onmiddellijk wilt verwijderen, kun je dit hieronder doen. time_in_queue: "%{time} in de wachtrij" title: Accounts unconfirmed_email: Onbevestigd e-mailadres + undo_sensitized: Niet meer als gevoelig markeren undo_silenced: Niet langer negeren undo_suspension: Niet langer opschorten + unsilenced_msg: Het opheffen van de beperkingen van %{username} zijn geslaagd unsubscribe: Opzeggen + unsuspended_msg: Het niet langer opschorten van %{username} is geslaagd username: Gebruikersnaam + view_domain: Samenvatting voor domein bekijken warn: Waarschuwen web: Webapp whitelisted: Goedgekeurd voor federatie @@ -206,31 +228,36 @@ nl: create_domain_allow: Domeingoedkeuring aanmaken create_domain_block: Domeinblokkade aanmaken create_email_domain_block: E-maildomeinblokkade aanmaken + create_ip_block: IP-regel aanmaken demote_user: Gebruiker degraderen destroy_announcement: Mededeling verwijderen destroy_custom_emoji: Lokale emoji verwijderen destroy_domain_allow: Domeingoedkeuring verwijderen destroy_domain_block: Domeinblokkade verwijderen destroy_email_domain_block: E-maildomeinblokkade verwijderen + destroy_ip_block: IP-regel verwijderen destroy_status: Toot verwijderen disable_2fa_user: Tweestapsverificatie uitschakelen disable_custom_emoji: Lokale emojij uitschakelen disable_user: Gebruiker uitschakelen enable_custom_emoji: Lokale emoji inschakelen enable_user: Gebruiker inschakelen - memorialize_account: Account in gedenkpagina veranderen + memorialize_account: Het account in een In memoriam veranderen promote_user: Gebruiker promoveren remove_avatar_user: Avatar verwijderen reopen_report: Rapportage heropenen reset_password_user: Wachtwoord opnieuw instellen resolve_report: Rapportage oplossen + sensitive_account: De media in jouw account als gevoelig markeren silence_account: Account negeren suspend_account: Account opschorten unassigned_report: Rapportage niet langer toewijzen + unsensitive_account: De media in jouw account niet langer als gevoelig markeren unsilence_account: Account niet langer negeren unsuspend_account: Account niet langer opschorten update_announcement: Mededeling bijwerken update_custom_emoji: Lokale emoji bijwerken + update_domain_block: Domeinblokkade bijwerken update_status: Toot bijwerken actions: assigned_to_self_report: "%{name} heeft rapportage %{target} aan zichzelf toegewezen" @@ -254,7 +281,7 @@ nl: disable_user: Inloggen voor %{target} is door %{name} uitgeschakeld enable_custom_emoji: Emoji %{target} is door %{name} ingeschakeld enable_user: Inloggen voor %{target} is door %{name} ingeschakeld - memorialize_account: Account %{target} is door %{name} in een gedenkpagina veranderd + memorialize_account: Het account %{target} is door %{name} in een In memoriam veranderd promote_user: Gebruiker %{target} is door %{name} gepromoveerd remove_avatar_user: "%{name} verwijderde de avatar van %{target}" reopen_report: "%{name} heeft rapportage %{target} heropend" @@ -409,6 +436,7 @@ nl: instances: by_domain: Domein delivery_available: Bezorging is mogelijk + empty: Geen domeinen gevonden. known_accounts: one: "%{count} bekend account" other: "%{count} bekende accounts" @@ -432,6 +460,21 @@ nl: expired: Verlopen title: Filter title: Uitnodigingen + ip_blocks: + add_new: Regel aanmaken + created_msg: Het toevoegen van een nieuwe IP-regel is geslaagd + delete: Verwijderen + expires_in: + '1209600': 2 weken + '15778476': 6 maanden + '2629746': 1 maand + '31556952': 1 jaar + '86400': 1 dag + '94670856': 3 jaar + new: + title: Nieuwe IP-regel aanmaken + no_ip_block_selected: Er zijn geen IP-regels veranderd, omdat er geen een was geselecteerd + title: IP-regels pending_accounts: title: Accounts in afwachting (%{count}) relationships: @@ -471,6 +514,8 @@ nl: comment: none: Geen created_at: Gerapporteerd op + forwarded: Doorgestuurd + forwarded_to: Doorgestuurd naar %{domain} mark_as_resolved: Markeer als opgelost mark_as_unresolved: Markeer als onopgelost notes: @@ -679,8 +724,11 @@ nl: prefix_sign_up: Registreer je vandaag nog op Mastodon! suffix: Met een account ben je in staat om mensen te volgen, berichten te plaatsen en uit te wisselen met mensen die zich op andere Mastodonservers bevinden en meer! didnt_get_confirmation: Geen bevestigingsinstructies ontvangen? + dont_have_your_security_key: Heb je jouw beveiligingssleutel niet bij de hand? forgot_password: Wachtwoord vergeten? invalid_reset_password_token: De code om jouw wachtwoord opnieuw in te stellen is verlopen. Vraag een nieuwe aan. + link_to_otp: Voer een tweestapsverificatiecode van je telefoon of een herstelcode in + link_to_webauth: Jouw apparaat met de authenticatie-app gebruiken login: Inloggen logout: Uitloggen migrate_account: Naar een ander account verhuizen @@ -705,7 +753,9 @@ nl: functional: Jouw account is volledig operationeel. pending: Jouw aanvraag moet nog worden beoordeeld door een van onze medewerkers. Dit kan misschien eventjes duren. Je ontvangt een e-mail wanneer jouw aanvraag is goedgekeurd. redirecting_to: Jouw account is inactief omdat het momenteel wordt doorverwezen naar %{acct}. + too_fast: Formulier is te snel ingediend. Probeer het nogmaals. trouble_logging_in: Problemen met inloggen? + use_security_key: Beveiligingssleutel gebruiken authorize_follow: already_following: Je volgt dit account al already_requested: Je hebt al een volgverzoek naar dat account verstuurd @@ -730,6 +780,7 @@ nl: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}u" @@ -794,6 +845,7 @@ nl: request: Jouw archief opvragen size: Omvang blocks: Jij blokkeert + bookmarks: Bladwijzers csv: CSV domain_blocks: Domeinblokkades lists: Lijsten @@ -807,7 +859,7 @@ nl: filters: contexts: account: Profielen - home: Starttijdlijn + home: Starttijdlijn en lijsten notifications: Meldingen public: Openbare tijdlijnen thread: Gesprekken @@ -861,6 +913,8 @@ nl: status: Verificatiestatus view_proof: Bekijk bewijs imports: + errors: + over_rows_processing_limit: bevat meer dan %{count} rijen modes: merge: Samenvoegen merge_long: Bestaande gegevens behouden en nieuwe toevoegen @@ -870,6 +924,7 @@ nl: success: Jouw gegevens zijn succesvol geüpload en worden binnenkort verwerkt types: blocking: Blokkeerlijst + bookmarks: Bladwijzers domain_blocking: Lijst met genegeerde servers following: Volglijst muting: Negeerlijst @@ -990,6 +1045,14 @@ nl: quadrillion: qdn. thousand: K trillion: bln. + otp_authentication: + code_hint: Voer de code in die door de authenticatie-app werd gegenereerd + description_html: Na het instellen van <strong>tweestapsverificatie</strong> met een authenticatie-app, kun je alleen inloggen als je jouw mobiele telefoon bij je hebt. Hiermee genereer je namelijk de in te voeren aanmeldcode. + enable: Inschakelen + instructions_html: "<strong>Scan deze QR-code in Google Authenticator of een soortgelijke app op jouw mobiele telefoon</strong>. Van nu af aan genereert deze app aanmeldcodes die je bij het inloggen moet invoeren." + manual_instructions: 'Voor het geval je de QR-code niet kunt scannen en het handmatig moet invoeren, vind je hieronder de geheime code in platte tekst:' + setup: Instellen + wrong_code: De ingevoerde code is ongeldig! Klopt de systeemtijd van de server en die van jouw apparaat? pagination: newer: Nieuwer next: Volgende @@ -1018,6 +1081,7 @@ nl: relationships: activity: Accountactiviteit dormant: Sluimerend + follow_selected_followers: Geselecteerde volgers volgen followers: Volgers following: Volgend invited: Uitgenodigd @@ -1114,6 +1178,7 @@ nl: profile: Profiel relationships: Volgers en gevolgden two_factor_authentication: Tweestapsverificatie + webauthn_authentication: Beveiligingssleutels spam_check: spam_detected: Dit is een automatisch gegenereerde rapportage. Er is spam gedetecteerd. statuses: @@ -1152,6 +1217,8 @@ nl: other: "%{count} stemmen" vote: Stemmen show_more: Meer tonen + show_newer: Nieuwere tonen + show_older: Oudere tonen show_thread: Gesprek tonen sign_in_to_participate: Meld je aan om aan dit gesprek mee te doen title: '%{name}: "%{quote}"' @@ -1260,21 +1327,20 @@ nl: default: "%d %B %Y om %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Voer de code in die door de authenticatie-app gegenereerd is - description_html: Na het instellen van <strong>tweestapsverificatie</strong>, kun je alleen inloggen als je jouw mobiele telefoon bij je hebt. Hiermee genereer je namelijk de in te voeren aanmeldcode. - disable: Uitschakelen - enable: Inschakelen + add: Toevoegen + disable: Tweestapsverificatie uitschakelen + disabled_success: Uitschakelen tweestapsverificatie is geslaagd + edit: Bewerken enabled: Tweestapsverificatie is ingeschakeld enabled_success: Inschakelen tweestapsverificatie geslaagd generate_recovery_codes: Herstelcodes genereren - instructions_html: "<strong>Scan deze QR-code in Google Authenticator of een soortgelijke app op jouw mobiele telefoon</strong>. Van nu af aan genereert deze app aanmeldcodes die je bij het inloggen moet invoeren." lost_recovery_codes: Met herstelcodes kun je toegang tot jouw account krijgen wanneer je jouw telefoon bent kwijtgeraakt. Wanneer je jouw herstelcodes bent kwijtgeraakt, kan je ze hier opnieuw genereren. Jouw oude herstelcodes zijn daarna ongeldig. - manual_instructions: Voor het geval je de QR-code niet kunt scannen en het handmatig moet invoeren, vind je hieronder de geheime code in platte tekst. + methods: Methoden voor tweestapsverificatie + otp: Authenticatie-app recovery_codes: Herstelcodes back-uppen recovery_codes_regenerated: Opnieuw genereren herstelcodes geslaagd recovery_instructions_html: Wanneer je ooit de toegang verliest tot jouw telefoon, kan je met behulp van een van de herstelcodes hieronder opnieuw toegang krijgen tot jouw account. <strong>Zorg ervoor dat je de herstelcodes op een veilige plek bewaard</strong>. Je kunt ze bijvoorbeeld printen en ze samen met andere belangrijke documenten bewaren. - setup: Instellen - wrong_code: De ingevoerde code is ongeldig! Klopt de systeemtijd van de server en die van jouw apparaat? + webauthn: Beveiligingssleutels user_mailer: backup_ready: explanation: Je hebt een volledige back-up van jouw Mastodon-account opgevraagd. Het staat nu klaar om te worden gedownload! @@ -1282,9 +1348,14 @@ nl: title: Archief ophalen sign_in_token: details: 'Hier zijn details van de poging:' + explanation: 'We hebben een inlogpoging op je account ontdekt vanaf een onbekend IP-adres. Als jij dit bent, vul dan de beveiligingscode hieronder in op de inlog-uitdagingspagina:' + further_actions: 'Als jij dit niet was, verander dan je wachtwoord en schakel tweestapsverificatie voor je account in. Dat kun je hier doen:' + subject: Bevestig de inlogpoging + title: Inlogpoging warning: explanation: disable: Zolang jouw account is bevroren blijven jouw accountgegevens intact, maar kun je geen handelingen uitvoeren totdat het account is vrijgegeven. + sensitive: De mediabestanden die je upload en gekoppelde media worden als gevoelig behandeld. silence: Zolang jouw account wordt beperkt, kunnen alleen mensen die jou al volgen jouw toots op deze server zien. Tevens ben je niet zichtbaar in meldingen, gesprekken en op openbare tijdlijnen. Anderen kunnen je echter wel handmatig volgen. suspend: Jouw account is opgeschort. Jouw toots en geüploade media zijn onomkeerbaar van deze server verwijderd, en ook o.a. van de servers waar jij volgers had. get_in_touch: Je kunt deze e-mail beantwoorden om in contact te komen met de medewerkers van %{instance}. @@ -1293,11 +1364,13 @@ nl: subject: disable: Jouw account %{acct} is bevroren none: Waarschuwing voor %{acct} + sensitive: De door jouw account %{acct} geplaatste media is als gevoelig gemarkeerd silence: Jouw account %{acct} is nu beperkt suspend: Jouw account %{acct} is opgeschort title: disable: Account bevroren none: Waarschuwing + sensitive: Jouw media is als gevoelig gemarkeerd silence: Account beperkt suspend: Account opgeschort welcome: @@ -1318,12 +1391,34 @@ nl: tips: Tips title: Welkom aan boord %{name}! users: + blocked_email_provider: Deze e-mailprovider is niet toegestaan follow_limit_reached: Je kunt niet meer dan %{limit} accounts volgen + generic_access_help_html: Problemen met toegang tot je account? Neem dan contact op met %{email} voor assistentie invalid_email: E-mailadres is ongeldig + invalid_email_mx: Het e-mailadres lijkt niet te bestaan invalid_otp_token: Ongeldige tweestaps-aanmeldcode + invalid_sign_in_token: Ongeldige beveiligingscode otp_lost_help_html: Als je toegang tot beiden kwijt bent geraakt, neem dan contact op via %{email} seamless_external_login: Je bent ingelogd via een externe dienst, daarom zijn wachtwoorden en e-mailinstellingen niet beschikbaar. signed_in_as: 'Ingelogd als:' + suspicious_sign_in_confirmation: Het lijkt er op dat je nog niet eerder op dit apparaat bent ingelogd, en je bent een tijdje niet ingelogd, dus sturen we een beveiligingscode naar je e-mailadres om te bevestigen dat jij het bent. verification: explanation_html: 'Je kunt <strong>jezelf verifiëren als de eigenaar van de links in de metadata van jouw profiel</strong>. Hiervoor moet op de gelinkte website een link terug naar jouw Mastodonprofiel staan. Deze link <strong>moet</strong> het <code>rel="me"</code>-attribuut bevatten. De omschrijving van de link maakt niet uit. Hier is een voorbeeld:' verification: Verificatie + webauthn_credentials: + add: Nieuwe beveiligingssleutel toevoegen + create: + error: Er deed zich een probleem voor met het toevoegen van jouw beveiligingssleutel. Probeer het nogmaals. + success: Het toevoegen van je beveiligingssleutel is geslaagd. + delete: Verwijderen + delete_confirmation: Weet je zeker dat je deze beveiligingssleutel wilt verwijderen? + description_html: Wanneer je <strong>verificatie met beveiligingssleutels</strong> inschakelt, moet je tijdens het inloggen een van jouw beveiligingssleutels gebruiken. + destroy: + error: Er deed zich een probleem voor met het verwijderen van jouw beveiligingssleutel. Probeer het nogmaals. + success: Het verwijderen van jouw beveiligingssleutel is geslaagd. + invalid_credential: Ongeldige beveiligingssleutel + nickname_hint: Voer de bijnaam in van jouw nieuwe beveiligingssleutel + not_enabled: Je hebt WebAuthn nog niet ingeschakeld + not_supported: Deze browser ondersteunt geen beveiligingssleutels + otp_required: Om beveiligingssleutels te kunnen gebruiken, moet je eerst tweestapsverificatie inschakelen. + registered_on: Geregistreerd op %{date} diff --git a/config/locales/nn.yml b/config/locales/nn.yml index 13a6d1911a5063792ed90174fd7e7286125612da..463364e3d523b170b222ebb1da5f256bd25c27d7 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -38,8 +38,11 @@ nn: domain: Sørvar reason: Grunn rejecting_media: 'Mediafiler fra disse tjenerne vil ikke bli behandlet eller lagret, og ingen miniatyrbilder vil bli vist, noe som vil kreve manuell klikking for Ã¥ besøke den opprinnelige filen:' + rejecting_media_title: Filtrert media silenced: 'Innlegg frÃ¥ desse tenarane vert gøymde frÃ¥ offentlege tidsliner og samtalar, og det kjem ingen varsel frÃ¥ samhandlingane til brukarane deira, med mindre du fylgjer dei:' + silenced_title: Stilnede tjenere suspended: 'Ingen data frÃ¥ desse tenarane vert handsama, lagra eller sende til andre, som gjer det umogeleg Ã¥ samhandla eller kommunisera med andre brukarar frÃ¥ desse tenarane:' + suspended_title: Suspenderte tjenere unavailable_content_html: Mastodon gjev deg som regel lov til Ã¥ sjÃ¥ innhald og samhandla med brukarar frÃ¥ alle andre tenarar i fødiverset. Dette er unnataka som er valde for akkurat denne tenaren. user_count_after: one: brukar @@ -90,7 +93,7 @@ nn: delete: Slett destroyed_msg: Moderatormerknad er utsletta! accounts: - add_email_domain_block: Svartelist E-postdomenet + add_email_domain_block: Gøym e-postdomene approve: Godtak approve_all: Godtak alle are_you_sure: Er du sikker? @@ -106,6 +109,7 @@ nn: confirm: Stadfest confirmed: Stadfesta confirming: Stadfestar + delete: Slett data deleted: Sletta demote: Degrader disable: SlÃ¥ av @@ -171,7 +175,7 @@ nn: staff: Personell user: Brukar search: Søk - search_same_email_domain: Andre brukere med samme E-postdomene + search_same_email_domain: Andre brukarar med same e-postdomene search_same_ip: Andre brukarar med same IP shared_inbox_url: Delt Innboks URL show: @@ -187,40 +191,50 @@ nn: unconfirmed_email: E-post utan stadfesting undo_silenced: Angr mÃ¥lbinding undo_suspension: Angr utvising + unsilenced_msg: Opphevde vellykket begrensningen av %{username} sin konto unsubscribe: Avmeld + unsuspended_msg: Opphevde vellykket suspenderingen av %{username} sin konto username: Brukarnamn + view_domain: Vis sammendrag for domenet warn: Ã…tvar web: Nett whitelisted: Kvitlista action_logs: action_types: assigned_to_self_report: Tilordne rapport - change_email_user: Endre brukerens E-postadresse - confirm_user: Bekreft brukeren - create_account_warning: Opprett en advarsel - create_announcement: Opprett en kunngjøring - create_custom_emoji: Opprett en tilpasset emoji + change_email_user: Byt e-post for brukar + confirm_user: Stadfest brukar + create_account_warning: Opprett Ã¥tvaring + create_announcement: Opprett lysing + create_custom_emoji: Opprett tilpassa emoji create_domain_allow: Opprett domene tillatt create_domain_block: Opprett domene-blokk create_email_domain_block: Opprett e-post domeneblokk - demote_user: Degrader bruker - destroy_announcement: Slett kunngjøringen - destroy_custom_emoji: Slett den tilpassede emojien - destroy_status: Slett statusen - disable_2fa_user: Skru av 2-trinnsinnlogging - disable_user: Deaktiver bruker - enable_user: Aktiver bruker - promote_user: Promoter bruker - remove_avatar_user: Fjern Avatar - reopen_report: GjenÃ¥pne rapporten + create_ip_block: Opprett IP-regel + demote_user: Degrader brukar + destroy_announcement: Slett lysinga + destroy_custom_emoji: Slett tilpassa emoji + destroy_domain_allow: Slett domenegodkjenning + destroy_domain_block: Slett domenesperring + destroy_email_domain_block: Slett e-postdomenesperring + destroy_ip_block: Slett IP-regel + destroy_status: Slett status + disable_2fa_user: Skruv av 2FA + disable_custom_emoji: Skruv av tilpassa emoji + disable_user: Skruv av brukar + enable_custom_emoji: Skruv pÃ¥ tilpassa emoji + enable_user: Skruv pÃ¥ brukar + promote_user: Forfrem brukar + remove_avatar_user: Fjern avatar + reopen_report: Opn rapport opp att reset_password_user: Tilbakestill passord resolve_report: Løs rapport silence_account: Demp konto suspend_account: Suspender kontoen unsuspend_account: Opphev suspensjonen av kontoen update_announcement: Oppdater kunngjøringen - update_custom_emoji: Oppdater tilpasset Emoji - update_status: Oppdater statusen + update_custom_emoji: Oppdater tilpassa emoji + update_status: Oppdater tut actions: assigned_to_self_report: "%{name} tilegnet rapport %{target} til seg selv" change_email_user: "%{name} endra e-postadressa til brukaren %{target}" @@ -231,12 +245,14 @@ nn: create_domain_allow: "%{name} kvitlista domenet %{target}" create_domain_block: "%{name} blokkerte domenet %{target}" create_email_domain_block: "%{name} svartelista e-postdomenet %{target}" + create_ip_block: "%{name} opprettet en regel for IP-en %{target}" demote_user: "%{name} degraderte brukaren %{target}" destroy_announcement: "%{name} slettet kunngjøring %{target}" destroy_custom_emoji: "%{name} utsletta kjensleteiknet %{target}" destroy_domain_allow: "%{name} fjerna domenet %{target} frÃ¥ kvitliste" destroy_domain_block: "%{name} slutta Ã¥ blokkera domenet %{target}" destroy_email_domain_block: "%{name} kvitlista e-postdomenet %{target}" + destroy_ip_block: "%{name} slettet en regel for IP-en %{target}" destroy_status: "%{name} sletta status av %{target}" disable_2fa_user: "%{name} tok vekk krav om tofaktorautentisering for brukaren %{target}" disable_custom_emoji: "%{name} deaktiverte emojien %{target}" @@ -258,9 +274,9 @@ nn: update_custom_emoji: "%{name} oppdaterte kjensleteiknet %{target}" update_status: "%{name} oppdaterte status for %{target}" deleted_status: "(sletta status)" - empty: Ingen loggføringer ble funnet. + empty: Ingen loggar funne. filter_by_action: Sorter etter handling - filter_by_user: Sorter etter bruker + filter_by_user: Sorter etter brukar title: Revisionslogg announcements: destroyed_msg: Kunngjøringen er slettet! @@ -299,7 +315,7 @@ nn: listed: Oppført new: title: Legg til eige kjensleteikn - not_permitted: Du har ikke rettigheter til Ã¥ utføre denne handlingen + not_permitted: Du har ikkje løyve til Ã¥ utføra denne handlinga overwrite: Skriv over shortcode: Stuttkode shortcode_hint: Minst 2 teikn, berre tal, bokstavar og understrek @@ -390,7 +406,7 @@ nn: destroyed_msg: E-postdomenet har blitt fjernet fra blokkeringslisten uten problemer domain: Domene empty: Ingen e-mail-domener er sortelistet pÃ¥ dette tidspunkt. - from_html: fra %{domain} + from_html: frÃ¥ %{domain} new: create: Legg til domene title: Ny blokkeringsoppføring av e-postdomene @@ -421,6 +437,20 @@ nn: expired: UtgÃ¥tt title: Filter title: Innbydingar + ip_blocks: + add_new: Opprett regel + created_msg: La vellykket til en ny IP-regel + delete: Slett + expires_in: + '1209600': 2 uker + '15778476': 6 mÃ¥neder + '2629746': 1 mÃ¥ned + '31556952': 1 Ã¥r + '86400': 1 dag + '94670856': 3 Ã¥r + new: + title: Opprett ny IP-regel + title: IP-regler pending_accounts: title: Kontoar som ventar (%{count}) relationships: @@ -564,7 +594,8 @@ nn: trends: title: Populære emneknaggar site_uploads: - delete: Slett den opplastede filen + delete: Slett opplasta fil + destroyed_msg: Vellukka sletting av sideopplasting! statuses: back_to_account: Tilbake til kontosida batch: @@ -618,7 +649,7 @@ nn: add_new: Lag psevdonym created_msg: Laga eit nytt kallenamn. No kan du setja i gang med flyttinga frÃ¥ den gamle kontoen. deleted_msg: Fjerna kallenamnet. No vert det ikkje lenger mogeleg Ã¥ flytta frÃ¥ den andre kontoen til denne. - empty: Du har ingen aliaser. + empty: Du har inkje alias. hint_html: Dersom du vil flytte fra en annen konto til den, kan du lage et alias her, som er pÃ¥krevd før du kan gÃ¥ videre med Ã¥ flytte følgere fra den gamle kontoen til den nye. Handlingen i seg selv er <strong>harmløs og reversibel</strong>. <strong>Kontoflyttingen har blitt satt i gang fra den gamle kontoen</strong>. remove: Fjern aliaslenking appearance: @@ -660,8 +691,11 @@ nn: prefix_sign_up: Meld deg pÃ¥ Mastodon i dag! suffix: Med ein konto kan du fylgja folk, skriva innlegg og veksla meldingar med brukarar frÃ¥ kva som helst annan Mastodon-tenar og meir! didnt_get_confirmation: Fekk du ikkje stadfestingsinstruksjonar? + dont_have_your_security_key: Har du ikke sikkerhetsnøkkelen din? forgot_password: Har du gløymt passordet ditt? invalid_reset_password_token: Tilgangsnykelen er ugyldig eller utgÃ¥tt. Ver venleg Ã¥ beda om ein ny ein. + link_to_otp: Skriv inn en 2-trinnskode fra din 2-trinnspÃ¥loggingsenhet eller en gjenopprettingskode + link_to_webauth: Bruk sikkerhetsnøkkel-enheten din login: Innlogging logout: Logg ut migrate_account: Flytt til ein annan konto @@ -687,8 +721,10 @@ nn: pending: Søknaden din ventar pÃ¥ gjennomgang frÃ¥ personalet vÃ¥rt. Dette kan taka litt tid. Du fÃ¥r ein e-post om søknaden din vert godkjend. redirecting_to: Kontoen din er inaktiv fordi den for øyeblikket omdirigerer til %{acct}. trouble_logging_in: FÃ¥r du ikkje logga inn? + use_security_key: Bruk sikkerhetsnøkkel authorize_follow: already_following: Du fylgjer allereie denne kontoen + already_requested: Du har allereie sendt ein fylgjespurnad til den kontoen error: Uheldigvis skjedde det en feil da vi prøvde Ã¥ fÃ¥ tak i en bruker fra en annen instans follow: Fylg follow_request: 'Du har sendt ein fylgjeførespurnad til:' @@ -703,6 +739,10 @@ nn: hint_html: "<strong>Tips:</strong> Vi skal ikkje spørja deg om passordet ditt igjen i laupet av den neste timen." invalid_password: Ugyldig passord prompt: Stadfest passord for Ã¥ halda fram + crypto: + errors: + invalid_key: er ikkje ein gild Ed25519 eller Curve25519 nykel + invalid_signature: er ikkje ein gild Ed25519-signatur date: formats: default: "%b %d, %Y" @@ -789,6 +829,8 @@ nn: thread: Samtalar edit: title: Endr filter + errors: + invalid_context: Ingen eller ugild kontekst gjeve index: delete: Slett empty: Du har ingen filtre. @@ -805,16 +847,20 @@ nn: changes_saved_msg: Alle endringane vart lagra! copy: Kopier delete: Slett + no_batch_actions_available: Ingen batch-handlingar tilgjengelege pÃ¥ denne sida order_by: Sorter etter save_changes: Lagr endringar validation_errors: one: Noe er ikke helt riktig ennÃ¥. Vennligst se etter en gang til other: Noe er ikke helt riktig ennÃ¥. Det er ennÃ¥ %{count} feil Ã¥ rette pÃ¥ + html_validator: + invalid_markup: 'rommar ugild HTML-kode: %{error}' identity_proofs: active: Aktiv authorize: Ja, stadfest authorize_connection_prompt: Vil du autorisere denne kryptografiske forbindelsen? errors: + failed: Den kryptografiske tilkoplinga gjekk gale. Venlegast prøv om att frÃ¥ %{provider}. keybase: verification_failed: Keybase kjenner ikke igjen denne sjetongen som en signatur for Keybase-brukeren %{kb_username}. Vennligst prøv igjen gjennom Keybase. wrong_user: Kan ikke lage et bevis for %{proving} mens du er logget pÃ¥ som %{current}. Logg pÃ¥ som %{proving} og prøv igjen. @@ -824,12 +870,14 @@ nn: inactive: Uaktiv publicize_checkbox: 'Og tut dette:' publicize_toot: 'Det er prova! Eg er %{username} pÃ¥ %{service}: %{url}' - remove: Fjern bevis fra kontoen + remove: Fjern prov frÃ¥ konto + removed: Vellukka fjerning av prov frÃ¥ konto status: Stadfestingsstatus view_proof: SjÃ¥ prov imports: modes: merge: Set saman + merge_long: Hald pÃ¥ eksisterande data og legg til nye overwrite: Skriv over preface: Du kan henta inn data som du har eksportert frÃ¥ ein annan tenar, som t.d. ei liste over folka du fylgjer eller blokkerer. success: Dataa dine vart lasta opp og vert no handsama sÃ¥ fort som mogeleg @@ -873,23 +921,39 @@ nn: acct: Flytta til cancel: Avbryt omdirigeringen cancel_explanation: Ã… avbryte omdirigeringen vil reaktivere din nÃ¥værende konto, men vil ikke bringe tilbake følgere som har blitt flyttet til den kontoen. + cancelled_msg: Avbrøt omdirigeringen med suksess. errors: already_moved: er den same kontoen som du allereie har flytta til + missing_also_known_as: er ikkje eit alias til denne kontoen move_to_self: kan ikkje vera denne kontoen not_found: fann ikkje on_cooldown: Du er i en nedkjølingsperiode followers_count: Fylgjarar dÃ¥ kontoen vart flytta incoming_migrations: Flyttar frÃ¥ ein annan konto incoming_migrations_html: For Ã¥ flytta frÃ¥ ein annnan konto til denne mÃ¥ du fyrst <a href="%{path}">laga eit kallenamn til kontoen</a>. + moved_msg: Kontoen din omdirigeres nÃ¥ til %{acct}, og følgerne dine blir flyttet over. + not_redirecting: Kontoen din omdirigeres ikke til noen andre kontoer for øyeblikket. + on_cooldown: Du har nylig overført kontoen din. Denne funksjonen blir tilgjengelig igjen om %{count} dager. past_migrations: Tidlegare vandringar proceed_with_move: Flytt fylgjarar + redirected_msg: Kontoen din omdirigerer no til %{acct}. + redirecting_to: Kontoen din omdirigerer til %{acct}. set_redirect: Bestem omdirigering warning: + backreference_required: Den nye kontoen mÃ¥ fyrst konfigurerast til Ã¥ visa til denne before: 'Før du fortsetter, vennligst les disse notisene nøye:' + cooldown: Etter flytting er det en nedkjølingsperiode der du ikke vil kunne flytte igjen disabled_account: Din nÃ¥værende konto vil ikke være fullt brukbar etterpÃ¥. Men du vil ha tilgang til dataeksportering sÃ¥vel som reaktivering. - other_data: Ingen andre data vil bli flyttet automatisk + followers: Denne handlingen vil flytte alle følgere fra den nÃ¥værende kontoen til den nye kontoen + only_redirect_html: Alternativt kan du velge Ã¥ <a href="%{path}">bare legge ut en omdirigering pÃ¥ profilen din</a>. + other_data: Inkje anna data flyttast av seg sjølve + redirect: Profilen til din nÃ¥værende konto vil bli oppdatert med en omdirigeringsnotis og bli fjernet fra søk moderation: title: Moderasjon + move_handler: + carry_blocks_over_text: Denne brukaren flytta frÃ¥ %{acct}, som du gøymde. + carry_mutes_over_text: Denne brukeren flyttet fra %{acct}, som du hadde dempet. + copy_account_note_text: 'Denne brukeren flyttet fra %{acct}, her var dine tidligere notater om dem:' notification_mailer: digest: action: SjÃ¥ alle varsel @@ -938,6 +1002,14 @@ nn: quadrillion: Bil thousand: K trillion: Bil + otp_authentication: + code_hint: Skriv inn koden generert av autentiseringsappen din for Ã¥ bekrefte + description_html: Hvis du skrur pÃ¥ <strong>2-trinnsautentisering</strong> ved hjelp av en autentiseringsapp, vil pÃ¥logging kreve at du er i besittelse av autentiseringsenheten din, som genererer sjetonger som du skal skrive inn. + enable: Aktiver + instructions_html: "<strong>Skann denne QR-koden i Authy, Google Autentisering, eller en lignende TOTP-app pÃ¥ en av dine enheter</strong>. Fra nÃ¥ av, vil den appen generere sjetonger som du vil mÃ¥tte skrive inn nÃ¥r du logger pÃ¥." + manual_instructions: 'Hvis du ikke kan skanne QR-koden og mÃ¥ skrive den inn manuelt, her er tekstkoden i ren tekst:' + setup: Sett opp + wrong_code: Den innskrevne koden var ugyldig! Er tjenertiden og enhetstiden riktige? pagination: newer: Nyare next: Neste @@ -996,6 +1068,10 @@ nn: reply: proceed: Svar prompt: 'Du vil svara pÃ¥ dette tutet:' + scheduled_statuses: + over_daily_limit: Du har overskredet grensen pÃ¥ %{limit} planlagte tuter for den dagen + over_total_limit: Du har overskredet grensen pÃ¥ %{limit} planlagte tuter + too_soon: Den planlagte datoen mÃ¥ være i fremtiden sessions: activity: Siste aktivitet browser: Nettlesar @@ -1058,10 +1134,14 @@ nn: profile: Profil relationships: Fylgjar og fylgjarar two_factor_authentication: Tostegsautorisering + webauthn_authentication: Sikkerhetsnøkler spam_check: spam_detected: Dette er en automatisert rapport. Spam har blitt oppdaget. statuses: attached: + audio: + one: "%{count} ljod" + other: "%{count} ljodar" description: 'Vedlagt: %{attached}' image: one: "%{count} bilete" @@ -1074,6 +1154,8 @@ nn: disallowed_hashtags: one: 'inneheldt ein emneknagg som ikkje var tillaten: %{tags}' other: 'inneheldt emneknaggen som ikkje var tillaten: %{tags}' + errors: + in_reply_not_found: Det ser ut til at tutet du freistar Ã¥ svara ikkje finst. language_detection: Kjenn att sprÃ¥k automatisk open_in_web: Opn pÃ¥ nett over_character_limit: øvregrensa for teikn, %{max}, er nÃ¥dd @@ -1199,25 +1281,29 @@ nn: default: "%d.%b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Skriv inn koden frÃ¥ autentiseringsappen for Ã¥ stadfesta - description_html: Hvis du skrur pÃ¥ <strong>tofaktorautentisering</strong> mÃ¥ du ha din telefon for Ã¥ logge inn. Denne vil generere koder som du mÃ¥ taste inn. + add: Legg til disable: SlÃ¥ av - enable: SlÃ¥ pÃ¥ + disabled_success: 2-trinnsautentisering ble vellykket skrudd av + edit: Redigering enabled: Tostegsinnlogging er slege pÃ¥ enabled_success: Aktivering av tofaktorautentisering vellykket generate_recovery_codes: Generér gjenopprettingskoder - instructions_html: "<strong>Scan denne QR-koden med Google Authenticator eller en lignende app pÃ¥ telefonen din</strong>. Fra nÃ¥ av vil denne applikasjonen generere koder for deg som skal brukes under innlogging." lost_recovery_codes: Gjenopprettingskoder lar deg gjenoppnÃ¥ tilgang til din konto hvis du mister din telefon. Hvis du har mistet gjenopprettingskodene, kan du regenerere dem her. Dine gamle gjenopprettingskoder vil bli ugyldige. - manual_instructions: 'Hvis du ikke fÃ¥r scannet QR-koden mÃ¥ du skrive inn følgende kode manuelt:' + methods: 2-trinnsmetoder + otp: Autentiseringsapp recovery_codes: Reservekoder recovery_codes_regenerated: Generering av reservekoder fullført recovery_instructions_html: Hvis du skulle miste tilgang til telefonen din, kan du bruke en av gjenopprettingskodene nedenfor til Ã¥ gjenopprette tilgang til din konto. <strong>Oppbevar gjenopprettingskodene sikkert</strong>, for eksempel ved Ã¥ skrive dem ut og gjemme dem pÃ¥ et lurt sted bare du vet om. - setup: Sett opp - wrong_code: Den angitte koden var ugyldig! Stemmer instansens tid overalt med enhetens tid? + webauthn: Sikkerhetsnøkler user_mailer: backup_ready: explanation: Du ba om en fullstendig sikkerhetskopi av Mastodon-kontoen din. Den er nÃ¥ klar for nedlasting! subject: Arkivet ditt er klart til Ã¥ lastes ned + sign_in_token: + details: 'Her er forsøksdetaljane:' + further_actions: 'Om dette ikkje var deg, so venlegast endra passordet ditt og skruv pÃ¥ tostegsgodkjenning pÃ¥ kontoen din. Du kan gjera det her:' + subject: Venlegast stadfest forsøket pÃ¥ Ã¥ logga inn + title: Forsøk pÃ¥ Ã¥ logga inn warning: explanation: disable: Mens kontoen din er fryst, forblir dine kontodata intakt, men du kan ikke utføre noen handlinger før den har blitt tint opp. @@ -1254,11 +1340,27 @@ nn: tips: Tips title: Velkomen om bord, %{name}! users: + blocked_email_provider: Denne E-postleverandøren er ikke tillatt follow_limit_reached: Du kan ikkje fylgja fleire enn %{limit} folk + generic_access_help_html: Har du vanskar med tilgjenge til kontoen din? Tak gjerne kontakt med %{email} invalid_email: E-mailadressa er ugyldig invalid_otp_token: Ugyldig tostegskode + invalid_sign_in_token: Ugild trygdenykel otp_lost_help_html: Hvis du mistet tilgangen til begge deler, kan du komme i kontakt med %{email} + seamless_external_login: Du er logga inn gjennom eit eksternt reiskap, so passord og e-postinstillingar er ikkje tilgjengelege. signed_in_as: 'Logga inn som:' + suspicious_sign_in_confirmation: Det verkar ikkje som du har logga inn frÃ¥ dette reiskapet før, og du har ikkje logga inn pÃ¥ ei stund, difor sender me deg ein trygdekode til e-post-addressa di for Ã¥ stadfesta at det er deg. verification: explanation_html: 'Du kan <strong>bekrefte at du selv er eieren av lenkene i din profilmetadata</strong>. For Ã¥ gjøre det, mÃ¥ det tillenkede nettstedet inneholde en lenke som fører tilbake til Mastodon-profilen din. Lenken tilbake <strong>mÃ¥</strong> ha en <code>rel="me"</code>-attributt. Tekstinnholdet til lenken er irrelevant. Her er et eksempel:' verification: Stadfesting + webauthn_credentials: + add: Legg til ny sikkerhetsnøkkel + create: + success: Sikkerhetsnøkkelen din ble vellykket lagt til. + delete: Slett + delete_confirmation: Er du sikker pÃ¥ at du vil slette denne sikkerhetsnøkkelen? + destroy: + success: Sikkerhetsnøkkelen din ble vellykket slettet. + invalid_credential: Ugyldig sikkerhetsnøkkel + not_supported: Denne nettleseren støtter ikke sikkerhetsnøkler + registered_on: Registrert den %{date} diff --git a/config/locales/no.yml b/config/locales/no.yml index 32368fc9a2bd2403f6d27423eace4262127e9138..b70eb167c442e6ca13a8186c37e7415b64be746e 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -21,7 +21,9 @@ federation_hint_html: Med en konto pÃ¥ %{instance} vil du kunne følge folk pÃ¥ enhver Mastodon-tjener, og mer til. get_apps: Prøv en mobilapp hosted_on: Mastodon driftet pÃ¥ %{domain} - instance_actor_flash: Denne brukeren er en virtuell aktør brukt til Ã¥ representere selve serveren og ingen individuell bruker. Det brukes til foreningsformÃ¥l og bør ikke blokkeres med mindre du vil blokkere hele instansen, hvor domeneblokkering bør brukes i stedet. + instance_actor_flash: 'Denne brukeren er en virtuell aktør brukt til Ã¥ representere selve serveren og ingen individuell bruker. Det brukes til foreningsformÃ¥l og bør ikke blokkeres med mindre du vil blokkere hele instansen, hvor domeneblokkering bør brukes i stedet. + +' learn_more: Lær mer privacy_policy: Privatlivsretningslinjer see_whats_happening: Se hva som skjer @@ -38,8 +40,11 @@ domain: Tjener reason: Ã…rsak rejecting_media: 'Mediafiler fra disse tjenerne vil ikke bli behandlet eller lagret, og ingen miniatyrbilder vil bli vist, noe som vil kreve manuell klikking for Ã¥ besøke den opprinnelige filen:' + rejecting_media_title: Filtrert media silenced: 'Innlegg fra disse tjenerne vil bli skjult fra offentlige tidslinjer og samtaler, og ingen varslinger vil bli generert fra disse brukernes samhandlinger, med mindre du følger dem:' + silenced_title: Stilnede tjenere suspended: 'Ingen data fra disse tjenerne vil bli behandlet, lagret, eller utvekslet, noe som vil gjøre enhver samhandling eller kommunikasjon med brukere fra disse tjenerne umulig:' + suspended_title: Suspenderte tjenere unavailable_content_html: Mastodon lar deg vanligvis se innhold fra og samhandle med brukere fra enhver annen tjener i strømiverset. Dette er unntakene som har blitt gjort pÃ¥ denne spesifikke tjeneren. user_count_after: one: bruker @@ -106,6 +111,7 @@ confirm: Bekreft confirmed: Bekreftet confirming: Bekrefte + delete: Slett data deleted: Slettet demote: Degrader disable: Deaktiver @@ -187,8 +193,11 @@ unconfirmed_email: Ubekreftet E-postadresse undo_silenced: Angre mÃ¥lbinding undo_suspension: Angre utvisning + unsilenced_msg: Opphevde vellykket begrensningen av %{username} sin konto unsubscribe: Avslutt abonnementet + unsuspended_msg: Opphevde vellykket suspenderingen av %{username} sin konto username: Brukernavn + view_domain: Vis sammendrag for domenet warn: Advar web: Nett whitelisted: Hvitelistet @@ -203,12 +212,16 @@ create_domain_allow: Opprett domene tillatt create_domain_block: Opprett domene-blokk create_email_domain_block: Opprett e-post domeneblokk + create_ip_block: Opprett IP-regel demote_user: Degrader bruker destroy_announcement: Slett kunngjøringen destroy_custom_emoji: Slett den tilpassede emojien + destroy_ip_block: Slett IP-regel destroy_status: Slett statusen disable_2fa_user: Skru av 2-trinnsinnlogging + disable_custom_emoji: Skru av tilpassede emojier disable_user: Deaktiver bruker + enable_custom_emoji: Skru pÃ¥ tilpassede emojier enable_user: Aktiver bruker promote_user: Promoter bruker remove_avatar_user: Fjern Avatar @@ -231,12 +244,14 @@ create_domain_allow: "%{name} hvitelistet domenet %{target}" create_domain_block: "%{name} blokkerte domenet %{target}" create_email_domain_block: "%{name} svartelistet e-postdomenet %{target}" + create_ip_block: "%{name} opprettet en regel for IP-en %{target}" demote_user: "%{name} degraderte bruker %{target}" destroy_announcement: "%{name} slettet kunngjøring %{target}" destroy_custom_emoji: "%{name} ødela emojien %{target}" destroy_domain_allow: "%{name} fjernet domenet %{target} fra hvitelisten" destroy_domain_block: "%{name} fjernet blokkeringen av domenet %{target}" destroy_email_domain_block: "%{name} hvitelistet e-postdomenet %{target}" + destroy_ip_block: "%{name} slettet en regel for IP-en %{target}" destroy_status: "%{name} fjernet status av %{target}" disable_2fa_user: "%{name} deaktiverte tofaktor-autentiseringskravet for bruker %{target}" disable_custom_emoji: "%{name} deaktiverte emoji %{target}" @@ -421,6 +436,20 @@ expired: Utløpt title: Filtrer title: Invitasjoner + ip_blocks: + add_new: Opprett regel + created_msg: La vellykket til en ny IP-regel + delete: Slett + expires_in: + '1209600': 2 uker + '15778476': 6 mÃ¥neder + '2629746': 1 mÃ¥ned + '31556952': 1 Ã¥r + '86400': 1 dag + '94670856': 3 Ã¥r + new: + title: Opprett ny IP-regel + title: IP-regler pending_accounts: title: Avventende brukere (%{count}) relationships: @@ -650,8 +679,11 @@ prefix_sign_up: Meld deg opp pÃ¥ Mastodon i dag! suffix: Med en konto, vil kunne følge folk, legge ut oppdateringer, og utveksle meldinger med brukere fra enhver Mastodon-tjener, og mer til! didnt_get_confirmation: Mottok du ikke instruksjoner om bekreftelse? + dont_have_your_security_key: Har du ikke sikkerhetsnøkkelen din? forgot_password: Har du glemt passordet ditt? invalid_reset_password_token: Tilbakestillingsnøkkelen for passord er ugyldig eller utløpt. Vennligst be om en ny. + link_to_otp: Skriv inn en 2-trinnskode fra din 2-trinnspÃ¥loggingsenhet eller en gjenopprettingskode + link_to_webauth: Bruk sikkerhetsnøkkel-enheten din login: Logg pÃ¥ logout: Logg ut migrate_account: Flytt til en annen konto @@ -677,6 +709,7 @@ pending: Søknaden din avventer gjennomgang av styret vÃ¥rt. Dette kan ta litt tid. Du vil motta en E-post dersom søknaden din blir godkjent. redirecting_to: Kontoen din er inaktiv fordi den for øyeblikket omdirigerer til %{acct}. trouble_logging_in: Har du problemer med Ã¥ logge pÃ¥? + use_security_key: Bruk sikkerhetsnøkkel authorize_follow: already_following: Du følger allerede denne kontoen error: Uheldigvis skjedde det en feil da vi prøvde Ã¥ fÃ¥ tak i en bruker fra en annen instans @@ -693,6 +726,10 @@ hint_html: "<strong>Tips:</strong> Vi ber deg ikke om passordet ditt igjen i løpet av neste time." invalid_password: Ugyldig passord prompt: Bekreft passordet for Ã¥ fortsette + crypto: + errors: + invalid_key: er ikke en gyldig Ed25519- eller Curve25519-nøkkel + invalid_signature: er ikke en gyldig Ed25519-signatur date: formats: default: "%b %d, %Y" @@ -861,23 +898,39 @@ acct: brukernavn@domene til den nye kontoen cancel: Avbryt omdirigeringen cancel_explanation: Ã… avbryte omdirigeringen vil reaktivere din nÃ¥værende konto, men vil ikke bringe tilbake følgere som har blitt flyttet til den kontoen. + cancelled_msg: Avbrøt omdirigeringen med suksess. errors: already_moved: er den samme kontoen du allerede har flyttet til + missing_also_known_as: er ikke en av denne kontoens aliaser move_to_self: kan ikke være den nÃ¥værende kontoen not_found: ble ikke funnet on_cooldown: Du er i en nedkjølingsperiode followers_count: Følgere pÃ¥ flyttetidspunktet incoming_migrations: Flytte fra en annen konto incoming_migrations_html: For Ã¥ flytte fra en annen konto til denne, mÃ¥ du først <a href="%{path}">sette opp et kontoalias</a>. + moved_msg: Kontoen din omdirigeres nÃ¥ til %{acct}, og følgerne dine blir flyttet over. + not_redirecting: Kontoen din omdirigeres ikke til noen andre kontoer for øyeblikket. + on_cooldown: Du har nylig overført kontoen din. Denne funksjonen blir tilgjengelig igjen om %{count} dager. past_migrations: Tidligere migreringer proceed_with_move: Flytt følgere + redirected_msg: Kontoen din omdirigeres nÃ¥ til %{acct}. + redirecting_to: Kontoen din omdirigeres til %{acct}. set_redirect: Bestem omdirigering warning: + backreference_required: Den nye kontoen mÃ¥ først settes opp til Ã¥ henvise tilbake til denne before: 'Før du fortsetter, vennligst les disse notisene nøye:' + cooldown: Etter flytting er det en nedkjølingsperiode der du ikke vil kunne flytte igjen disabled_account: Din nÃ¥værende konto vil ikke være fullt brukbar etterpÃ¥. Men du vil ha tilgang til dataeksportering sÃ¥vel som reaktivering. + followers: Denne handlingen vil flytte alle følgere fra den nÃ¥værende kontoen til den nye kontoen + only_redirect_html: Alternativt kan du velge Ã¥ <a href="%{path}">bare legge ut en omdirigering pÃ¥ profilen din</a>. other_data: Ingen andre data vil bli flyttet automatisk + redirect: Profilen til din nÃ¥værende konto vil bli oppdatert med en omdirigeringsnotis og bli fjernet fra søk moderation: title: Moderasjon + move_handler: + carry_blocks_over_text: Denne brukeren flyttet fra %{acct}, som du hadde blokkert. + carry_mutes_over_text: Denne brukeren flyttet fra %{acct}, som du hadde dempet. + copy_account_note_text: 'Denne brukeren flyttet fra %{acct}, her var dine tidligere notater om dem:' notification_mailer: digest: action: Vis alle varslinger @@ -926,6 +979,14 @@ quadrillion: Kvd thousand: T trillion: Trl + otp_authentication: + code_hint: Skriv inn koden generert av autentiseringsappen din for Ã¥ bekrefte + description_html: Hvis du skrur pÃ¥ <strong>2-trinnsautentisering</strong> ved hjelp av en autentiseringsapp, vil pÃ¥logging kreve at du er i besittelse av autentiseringsenheten din, som genererer sjetonger som du skal skrive inn. + enable: Aktiver + instructions_html: "<strong>Skann denne QR-koden i Authy, Google Autentisering, eller en lignende TOTP-app pÃ¥ en av dine enheter</strong>. Fra nÃ¥ av, vil den appen generere sjetonger som du vil mÃ¥tte skrive inn nÃ¥r du logger pÃ¥." + manual_instructions: 'Hvis du ikke kan skanne QR-koden og mÃ¥ skrive den inn manuelt, her er tekstkoden i ren tekst:' + setup: Sett opp + wrong_code: Den innskrevne koden var ugyldig! Er tjenertiden og enhetstiden riktige? pagination: newer: Nyere next: Neste @@ -984,6 +1045,10 @@ reply: proceed: Fortsett til svaret prompt: 'Du ønsker Ã¥ svare pÃ¥ denne tuten:' + scheduled_statuses: + over_daily_limit: Du har overskredet grensen pÃ¥ %{limit} planlagte tuter for den dagen + over_total_limit: Du har overskredet grensen pÃ¥ %{limit} planlagte tuter + too_soon: Den planlagte datoen mÃ¥ være i fremtiden sessions: activity: Siste aktivitet browser: Nettleser @@ -1046,10 +1111,14 @@ profile: Profil relationships: Følginger og følgere two_factor_authentication: Tofaktorautentisering + webauthn_authentication: Sikkerhetsnøkler spam_check: spam_detected: Dette er en automatisert rapport. Spam har blitt oppdaget. statuses: attached: + audio: + one: "%{count} lyd" + other: "%{count} lyd" description: 'Vedlagt: %{attached}' image: one: "%{count} bilde" @@ -1183,25 +1252,27 @@ default: "%-d. %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Tast koden som ble generert av din autentiseringsapp for Ã¥ bekrefte - description_html: Hvis du skrur pÃ¥ <strong>tofaktorautentisering</strong> mÃ¥ du ha din telefon for Ã¥ logge inn. Denne vil generere koder som du mÃ¥ taste inn. + add: Legg til disable: Skru av - enable: Skru pÃ¥ + disabled_success: 2-trinnsautentisering ble vellykket skrudd av + edit: Redigering enabled: To-faktor autentisering er aktivert enabled_success: Aktivering av tofaktorautentisering vellykket generate_recovery_codes: Generér gjenopprettingskoder - instructions_html: "<strong>Scan denne QR-koden med Google Authenticator eller en lignende app pÃ¥ telefonen din</strong>. Fra nÃ¥ av vil denne applikasjonen generere koder for deg som skal brukes under innlogging." lost_recovery_codes: Gjenopprettingskoder lar deg gjenoppnÃ¥ tilgang til din konto hvis du mister din telefon. Hvis du har mistet gjenopprettingskodene, kan du regenerere dem her. Dine gamle gjenopprettingskoder vil bli ugyldige. - manual_instructions: 'Hvis du ikke fÃ¥r scannet QR-koden mÃ¥ du skrive inn følgende kode manuelt:' + methods: 2-trinnsmetoder + otp: Autentiseringsapp recovery_codes: Reservekoder recovery_codes_regenerated: Generering av reservekoder fullført recovery_instructions_html: Hvis du skulle miste tilgang til telefonen din, kan du bruke en av gjenopprettingskodene nedenfor til Ã¥ gjenopprette tilgang til din konto. <strong>Oppbevar gjenopprettingskodene sikkert</strong>, for eksempel ved Ã¥ skrive dem ut og gjemme dem pÃ¥ et lurt sted bare du vet om. - setup: Sett opp - wrong_code: Den angitte koden var ugyldig! Stemmer instansens tid overalt med enhetens tid? + webauthn: Sikkerhetsnøkler user_mailer: backup_ready: explanation: Du ba om en fullstendig sikkerhetskopi av Mastodon-kontoen din. Den er nÃ¥ klar for nedlasting! subject: Arkivet ditt er klart til Ã¥ lastes ned + sign_in_token: + details: 'Her er detaljene om forsøket:' + title: PÃ¥loggingsforsøk warning: explanation: disable: Mens kontoen din er fryst, forblir dine kontodata intakt, men du kan ikke utføre noen handlinger før den har blitt tint opp. @@ -1238,11 +1309,24 @@ tips: Tips title: Velkommen ombord, %{name}! users: + blocked_email_provider: Denne E-postleverandøren er ikke tillatt follow_limit_reached: Du kan ikke følge mer enn %{limit} personer invalid_email: E-postaddressen er ugyldig invalid_otp_token: Ugyldig to-faktorkode + invalid_sign_in_token: Ugyldig sikkerhetskode otp_lost_help_html: Hvis du mistet tilgangen til begge deler, kan du komme i kontakt med %{email} signed_in_as: 'Innlogget som:' verification: explanation_html: 'Du kan <strong>bekrefte at du selv er eieren av lenkene i din profilmetadata</strong>. For Ã¥ gjøre det, mÃ¥ det tillenkede nettstedet inneholde en lenke som fører tilbake til Mastodon-profilen din. Lenken tilbake <strong>mÃ¥</strong> ha en <code>rel="me"</code>-attributt. Tekstinnholdet til lenken er irrelevant. Her er et eksempel:' verification: Bekreftelse + webauthn_credentials: + add: Legg til ny sikkerhetsnøkkel + create: + success: Sikkerhetsnøkkelen din ble vellykket lagt til. + delete: Slett + delete_confirmation: Er du sikker pÃ¥ at du vil slette denne sikkerhetsnøkkelen? + destroy: + success: Sikkerhetsnøkkelen din ble vellykket slettet. + invalid_credential: Ugyldig sikkerhetsnøkkel + not_supported: Denne nettleseren støtter ikke sikkerhetsnøkler + registered_on: Registrert den %{date} diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 95d15ef85edbfe6cbc24c35373c13e00bc053326..3837ce56a559ccefe69365cd77a68f5fe9e56b0b 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -47,6 +47,7 @@ oc: what_is_mastodon: Qu’es Mastodon ? accounts: choices_html: 'Recomandacions de %{name} :' + endorsements_hint: Podètz recomandar personas que seguètz a partir de l’interfà cia web, apreissarà n aquÃ. featured_tags_hint: Podètz indicar d’etiquetas que mostrarem aquÃ. follow: Sègre followers: @@ -104,6 +105,7 @@ oc: confirm: Confirmar confirmed: Confirmat confirming: Confirmacion + delete: Suprimir donadas deleted: Suprimits demote: Retrogradar disable: Desactivar @@ -131,6 +133,7 @@ oc: login_status: Estat formulari de connexion media_attachments: Mèdias enviats memorialize: Passar en memorial + memorialized: Memorizat moderation: active: Actius all: Totes @@ -170,6 +173,8 @@ oc: user: Uitlizaire search: Cercar search_same_ip: Autres utilizaires amb la meteissa IP + sensitive: Sensible + sensitized: marcar coma sensible shared_inbox_url: URL de recepcion partejada show: created_reports: Senhalaments creats @@ -182,6 +187,7 @@ oc: time_in_queue: En espèra a la fila %{time} title: Comptes unconfirmed_email: Adreça pas confirmada + undo_sensitized: Desmarcar coma sensible undo_silenced: Levar lo silenci undo_suspension: Levar la suspension unsubscribe: Se desabonar @@ -197,6 +203,7 @@ oc: create_account_warning: Crear un avertiment create_announcement: Crear una anóncia create_custom_emoji: Crear un emoji personalizat + create_ip_block: Crear una règla IP demote_user: Retrogradar l’utilizaire destroy_announcement: Suprimir l’anóncia destroy_custom_emoji: Suprimir l’emoji personalizat @@ -417,6 +424,19 @@ oc: expired: Expirats title: Filtre title: Convits + ip_blocks: + add_new: Crear una règla + delete: Suprimir + expires_in: + '1209600': 2 setmanas + '15778476': 6 meses + '2629746': 1 mes + '31556952': 1 an + '86400': 1 jorn + '94670856': 3 ans + new: + title: Crear una règlas IP novèla + title: Règlas IP pending_accounts: title: Comptes en espèra (%{count}) relationships: @@ -672,6 +692,7 @@ oc: account_status: Estat del compte functional: Vòstre compte es complètament foncional. trouble_logging_in: Problèmas de connexion ? + use_security_key: Utilizar clau de seguretat authorize_follow: already_following: Seguètz ja aqueste compte error: O planhèm, i a agut una error al moment de cercar lo compte @@ -690,7 +711,8 @@ oc: prompt: Confirmatz lo senhal per dire de contunhar date: formats: - default: "%d %B de %Y" + default: "%-d %B de %Y" + with_month_name: "%-d %B de %Y" datetime: distance_in_words: about_x_hours: "%{count} h" @@ -753,6 +775,7 @@ oc: request: Demandar vòstre archiu size: Talha blocks: Personas que blocatz + bookmarks: Marcadors csv: CSV domain_blocks: Blocatge de domenis lists: Listas @@ -827,6 +850,7 @@ oc: success: Vòstras donadas son ben estadas mandadas e serà n tractadas tre que possible types: blocking: Lista de blocatge + bookmarks: Marcadors domain_blocking: Lista dels domenis blocats following: Lista de monde que seguètz muting: Lista de monde que volètz pas legir @@ -931,6 +955,9 @@ oc: quadrillion: Q thousand: K trillion: T + otp_authentication: + enable: Activar + setup: Parametrar pagination: newer: Mai recents next: Seguent @@ -960,13 +987,13 @@ oc: activity: Activitat del compte dormant: Inactiu followers: Seguidors - following: Aboanements + following: Abonaments invited: Convidat last_active: Darrièra activitat most_recent: Mai recenta moved: Mudat mutual: Mutuala - primary: Pirmà ria + primary: Primà ria relationship: Relacion remove_selected_domains: Levar totes los seguidors dels domenis seleccionats remove_selected_followers: Levar los seguidors seleccionats @@ -1055,10 +1082,14 @@ oc: profile: Perfil relationships: Abonaments e seguidors two_factor_authentication: Autentificacion en dos temps + webauthn_authentication: Claus de seguretat spam_check: spam_detected: Aquò es un senhalament automatic. D’spam es estat detectat. statuses: attached: + audio: + one: "%{count} à udio" + other: "%{count} à udios" description: 'Ajustat : %{attached}' image: one: "%{count} imatge" @@ -1195,24 +1226,20 @@ oc: mastodon-light: Mastodon (Clar) time: formats: - default: Lo %d %b de %Y a %Ho%M - month: "%b de %Y" + default: Lo %-d %B de %Y a %Ho%M + month: "%B de %Y" two_factor_authentication: - code_hint: Picatz lo còdi generat per vòstra aplicacion d’autentificacion per confirmar - description_html: S’activatz <strong> l’autentificacion two-factor</strong>, vos caldrà vòstre mobil per vos connectar perque generarà un geton per vos daissar dintrar. + add: Ajustar disable: Desactivar - enable: Activar + edit: Modificar enabled: Autentificacion en dos temps activada enabled_success: L’autentificacion en dos temps es ben activada generate_recovery_codes: Generar los còdis de recuperacion - instructions_html: "<strong>Escanatz aqueste còdi QR amb Google Authenticator o una aplicacion similà ria sus vòstre mobil</strong>. A partir d’ara, aquesta aplicacion generarà un geton que vos caldrà picar per vos connectar." lost_recovery_codes: Los còdi de recuperacion vos permeton d’accedir a vòstre compte se perdètz vòstre mobil. S’avètz perdut vòstres còdis de recuperacion los podètz tornar generar aquÃ. Los ancians còdis serà n pas mai valides. - manual_instructions: 'Se podètz pas numerizar lo còdi QR e que vos cal picar lo còdi a la man, vaquà lo còdi en clar :' recovery_codes: Salvar los còdis de recuperacion recovery_codes_regenerated: Los còdis de recuperacion son ben estats tornats generar recovery_instructions_html: Se vos arriba de perdre vòstre mobil, podètz utilizar un dels còdis de recuperacion cai-jos per poder tornar accedir a vòstre compte. <strong>Gardatz los còdis en seguretat</strong>, per exemple, imprimissètz los e gardatz los amb vòstres documents importants. - setup: Parametrar - wrong_code: Lo còdi picat es invalid ! L’ora es bona sul servidor e lo mobil ? + webauthn: Claus de seguretat user_mailer: backup_ready: explanation: Avètz demandat una salvagarda complèta de vòstre compte Mastodon. Es prèsta per telecargament ! @@ -1264,3 +1291,8 @@ oc: verification: explanation_html: 'Podètz <strong>verificar vosautres meteisses coma proprietari dels ligams per las metadonadas de vòstre perfil</strong>. Per aquò far, lo site Web ligat deu conténer un ligam cap a vòstre perfil Mastodon. Lo ligam <strong>deu</strong> aver un atribut <code>rel="me"</code>. Lo contengut tèxte del ligam impòrta pas. Vaquà un exemple :' verification: Verificacion + webauthn_credentials: + add: Apondre una clau de seguretat novèla + delete: Suprimir + invalid_credential: Cau de seguretat invalida + registered_on: Inscripcion del %{date} diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 7d0b3f214ba4ffba0d13e4d7fc444177c05774d4..23c67267e0eda9f2e2dd8bf6bb57cd9e98cad4b2 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -66,6 +66,7 @@ pl: one: Å›ledzÄ…cy other: ÅšledzÄ…cych following: Å›ledzonych + instance_actor_flash: To konto jest wirtualnym profilem używanym do reprezentowania samego serwera, a nie żadnego indywidualnego użytkownika. Jest ono stosowane do celów federacji i nie powinien być zawieszany. joined: DołączyÅ‚(a) %{date} last_active: ostatnio aktywny(-a) link_verified_on: WÅ‚asność tego odnoÅ›nika zostaÅ‚a sprawdzona %{date} @@ -106,6 +107,7 @@ pl: add_email_domain_block: Dodaj domenÄ™ e-mail na czarnÄ… listÄ™ approve: Przyjmij approve_all: Zatwierdź wszystkie + approved_msg: PomyÅ›lnie zaakceptowano wniosek o rejestracjÄ™ %{username} are_you_sure: JesteÅ› tego pewien? avatar: Awatar by_domain: Domena @@ -119,8 +121,10 @@ pl: confirm: Potwierdź confirmed: Potwierdzono confirming: Potwierdzanie + delete: UsuÅ„ dane deleted: UsuniÄ™to demote: Degraduj + destroyed_msg: Dane %{username} sÄ… teraz w kolejce do natychmiastowego usuniÄ™cia disable: Dezaktywuj disable_two_factor_authentication: Wyłącz uwierzytelnianie dwuetapowe disabled: Dezaktywowano @@ -131,10 +135,12 @@ pl: email_status: Stan e-maila enable: Aktywuj enabled: Aktywowano + enabled_msg: PomyÅ›lnie odblokowano konto %{username} followers: ÅšledzÄ…cy follows: Åšledzeni header: Nagłówek inbox_url: Adres skrzynki + invite_request_text: Powody rejestracji invited_by: Zaproszony(-a) przez ip: Adres IP joined: DołączyÅ‚(-a) @@ -146,6 +152,8 @@ pl: login_status: Stan logowania media_attachments: Załączniki multimedialne memorialize: Przełącz na „In Memoriam†+ memorialized: UpamiÄ™tniono + memorialized_msg: PomyÅ›lnie przełączono %{username} w konto in memoriam moderation: active: Aktywne all: Wszystkie @@ -166,10 +174,14 @@ pl: public: Publiczne push_subscription_expires: Subskrypcja PuSH wygasa redownload: OdÅ›wież profil + redownloaded_msg: PomyÅ›lnie odÅ›wieżono profil %{username} z miejsca pochodzenia reject: Odrzuć reject_all: Odrzuć wszystkie + rejected_msg: PomyÅ›lnie odrzucono wniosek o rejestracjÄ™ %{username} remove_avatar: Usun awatar remove_header: UsuÅ„ nagłówek + removed_avatar_msg: PomyÅ›lnie usuniÄ™to awatar %{username} + removed_header_msg: PomyÅ›lnie usuniÄ™to obraz nagłówka %{username} resend_confirmation: already_confirmed: To konto zostaÅ‚o już potwierdzone send: WyÅ›lij ponownie e-mail z potwierdzeniem @@ -186,6 +198,8 @@ pl: search: Szukaj search_same_email_domain: Inni użytkownicy z e-mail w tej domenie search_same_ip: Inni użytkownicy z tym samym IP + sensitive: Wrażliwe + sensitized: oznaczono jako wrażliwe shared_inbox_url: Adres udostÄ™pnianej skrzynki show: created_reports: ZgÅ‚oszenia tego użytkownika @@ -195,13 +209,19 @@ pl: statuses: Wpisy subscribe: Subskrybuj suspended: Zawieszono + suspension_irreversible: Dane tego konta zostaÅ‚y bezpowrotnie usuniÄ™te. Możesz cofnąć zawieszenie tego konta aby można byÅ‚o z niego ponownie korzystać, lecz nie przywróci to danych które poprzednio siÄ™ na nim znajdowaÅ‚y. + suspension_reversible_hint_html: Twoje konto zostaÅ‚o zawieszone, a dane zostanÄ… caÅ‚kowicie usuniÄ™te %{date}. Do tego czasu, konto może zostać przywrócone bez żadnych negatywnych skutków. Jeżeli chcesz natychmiastowo usunąć wszystkie dane, możesz zrobić to niżej. time_in_queue: Czekanie w kolejce %{time} title: Konta unconfirmed_email: Niepotwierdzony adres e-mail + undo_sensitized: Cofnij oznaczenie undo_silenced: Cofnij wyciszenie undo_suspension: Cofnij zawieszenie + unsilenced_msg: PomyÅ›lnie zwolniono z ograniczeÅ„ konto %{username} unsubscribe: PrzestaÅ„ subskrybować + unsuspended_msg: PomyÅ›lnie cofniÄ™to zawieszenie konto %{username} username: Nazwa użytkownika + view_domain: Zobacz podsumowanie domeny warn: Ostrzeż web: Sieć whitelisted: Na biaÅ‚ej liÅ›cie @@ -216,12 +236,14 @@ pl: create_domain_allow: Utwórz zezwolenie dla domeny create_domain_block: Utwórz blokadÄ™ domeny create_email_domain_block: Utwórz blokadÄ™ domeny e-mail + create_ip_block: Utwórz regułę IP demote_user: Zdegraduj użytkownika destroy_announcement: UsuÅ„ ogÅ‚oszenie destroy_custom_emoji: UsuÅ„ niestandardowe emoji destroy_domain_allow: UsuÅ„ zezwolenie dla domeny destroy_domain_block: UsuÅ„ blokadÄ™ domeny destroy_email_domain_block: UsuÅ„ blokadÄ™ domeny e-mail + destroy_ip_block: UsuÅ„ regułę IP destroy_status: UsuÅ„ wpis disable_2fa_user: Wyłącz 2FA disable_custom_emoji: Wyłącz niestandardowe emoji @@ -234,13 +256,16 @@ pl: reopen_report: Otwórz zgÅ‚oszenie ponownie reset_password_user: Resetuj hasÅ‚o resolve_report: Rozwiąż zgÅ‚oszenie + sensitive_account: Oznacz zawartość multimedialnÄ… swojego konta jako wrażliwÄ… silence_account: Wycisz konto suspend_account: ZawieÅ› konto unassigned_report: Cofnij przypisanie zgÅ‚oszenia + unsensitive_account: Cofnij oznaczenie zawartoÅ›ci multimedialnej swojego konta jako wrażliwÄ… unsilence_account: Cofnij wyciszenie konta unsuspend_account: Cofnij zawieszenie konta update_announcement: Aktualizuj ogÅ‚oszenie update_custom_emoji: Aktualizuj niestandardowe emoji + update_domain_block: Zaktualizuj blokadÄ™ domeny update_status: Aktualizuj wpis actions: assigned_to_self_report: "%{name} przypisaÅ‚(a) sobie zgÅ‚oszenie %{target}" @@ -252,12 +277,14 @@ pl: create_domain_allow: "%{name} dodaÅ‚(a) na białą listÄ™ domenÄ™ %{target}" create_domain_block: "%{name} zablokowaÅ‚(a) domenÄ™ %{target}" create_email_domain_block: "%{name} dodaÅ‚(a) domenÄ™ e-mail %{target} na czarnÄ… listÄ™" + create_ip_block: "%{name} stworzyÅ‚ dla IP %{target}" demote_user: "%{name} zdegradowaÅ‚(a) użytkownika %{target}" destroy_announcement: "%{name} usunÄ…Å‚(-ęła) ogÅ‚oszenie %{target}" destroy_custom_emoji: "%{name} usunÄ…Å‚(-ęła) emoji %{target}" destroy_domain_allow: "%{name} usunÄ…Å‚(-ęła) domenÄ™ %{target} z biaÅ‚ej listy" destroy_domain_block: "%{name} odblokowaÅ‚(a) domenÄ™ %{target}" destroy_email_domain_block: "%{name} usunÄ…Å‚(-ęła) domenÄ™ e-mail %{target} z czarnej listy" + destroy_ip_block: "%{name} usunÄ…Å‚ regułę dla IP %{target}" destroy_status: "%{name} usunÄ…Å‚(-ęła) wpis użytkownika %{target}" disable_2fa_user: "%{name} wyłączyÅ‚(a) uwierzytelnianie dwustopniowe użytkownikowi %{target}" disable_custom_emoji: "%{name} wyłączyÅ‚(a) emoji %{target}" @@ -270,13 +297,16 @@ pl: reopen_report: "%{name} otworzyÅ‚(a) ponownie zgÅ‚oszenie %{target}" reset_password_user: "%{name} przywróciÅ‚(a) hasÅ‚o użytkownikowi %{target}" resolve_report: "%{name} rozwiÄ…zaÅ‚(a) zgÅ‚oszenie %{target}" + sensitive_account: "%{name} oznaczyÅ‚(a) zawartość multimedialnÄ… %{target} jako wrażliwÄ…" silence_account: "%{name} wyciszyÅ‚(a) konto %{target}" suspend_account: "%{name} zawiesiÅ‚(a) konto %{target}" unassigned_report: "%{name} cofnÄ…Å‚(-ęła) przypisanie zgÅ‚oszenia %{target}" + unsensitive_account: "%{name} cofnÄ…Å‚(-ęła) oznaczenie zawartoÅ›ci multimedialnej %{target} jako wrażliwÄ…" unsilence_account: "%{name} cofnÄ…Å‚(-ęła) wyciszenie konta %{target}" unsuspend_account: "%{name} cofnÄ…Å‚(-ęła) zawieszenie konta %{target}" update_announcement: "%{name} zaktualizowaÅ‚(-a) ogÅ‚oszenie %{target}" update_custom_emoji: "%{name} zaktualizowaÅ‚(a) emoji %{target}" + update_domain_block: "%{name} zaktualizowaÅ‚(-a) blokadÄ™ domeny dla %{target}" update_status: "%{name} zaktualizowaÅ‚(a) wpis użytkownika %{target}" deleted_status: "(usuniÄ™ty wpis)" empty: Nie znaleziono aktywnoÅ›ci w dzienniku. @@ -380,6 +410,8 @@ pl: silence: Wycisz suspend: ZawieÅ› title: Nowa blokada domen + obfuscate: Ukryj nazwÄ™ domeny + obfuscate_hint: Częściowo ukryj nazwÄ™ domeny na liÅ›cie, gdy reklamowanie listy limitów domen jest włączone private_comment: Prywatny komentarz private_comment_hint: Komentarz na temat ograniczeÅ„ dla tej domeny do wewnÄ™trznej informacji dla moderatorów. public_comment: Publiczny komentarz @@ -421,6 +453,7 @@ pl: instances: by_domain: Domena delivery_available: DorÄ™czanie jest dostÄ™pne + empty: Nie znaleziono domen. known_accounts: few: "%{count} znane konta" many: "%{count} znane konta" @@ -446,6 +479,21 @@ pl: expired: WygasÅ‚e title: Filtruj title: Zaproszenia + ip_blocks: + add_new: Stwórz regułę + created_msg: PomyÅ›lnie dodano nowÄ… regułę IP + delete: UsuÅ„ + expires_in: + '1209600': 2 tygodnie + '15778476': 6 miesiÄ™cy + '2629746': 1 miesiÄ…c + '31556952': 1 rok + '86400': 1 dzieÅ„ + '94670856': 3 lata + new: + title: Utwórz nowÄ… regułę IP + no_ip_block_selected: Å»adna reguÅ‚a nie zostaÅ‚a zmieniona, ponieważ żadna nie zostaÅ‚a wybrana + title: ReguÅ‚y adresów IP pending_accounts: title: OczekujÄ…ce konta (%{count}) relationships: @@ -489,6 +537,8 @@ pl: comment: none: Brak created_at: ZgÅ‚oszono + forwarded: Przekazano + forwarded_to: Przekazano do %{domain} mark_as_resolved: Oznacz jako rozwiÄ…zane mark_as_unresolved: Oznacz jako nierozwiÄ…zane notes: @@ -532,6 +582,7 @@ pl: domain_blocks_rationale: title: Pokaż uzasadnienia enable_bootstrap_timeline_accounts: + desc_html: Niech nowi użytkownicy automatycznie Å›ledzÄ… ustawione konta, aby ich główna oÅ› czasu nie byÅ‚ poczÄ…tkowo pusta title: Dodawaj domyÅ›lne obserwacje nowym użytkownikom hero: desc_html: WyÅ›wietlany na stronie głównej. Zalecany jest rozmiar przynajmniej 600x100 pikseli. Jeżeli nie ustawiony, zostanie użyta miniatura serwera @@ -558,6 +609,9 @@ pl: min_invite_role: disabled: Nikt title: Kto może zapraszać użytkowników + require_invite_text: + desc_html: Kiedy rejestracje wymagajÄ… rÄ™cznego zatwierdzenia, ustaw pole "Dlaczego chcesz dołączyć?" jako obowiÄ…zkowe, a nie opcjonalne + title: Wymagaj od nowych użytkowników wypeÅ‚nienia tekstu proÅ›by o zaproszenie registrations_mode: modes: approved: PrzyjÄ™cie jest wymagane do rejestracji @@ -697,8 +751,11 @@ pl: prefix_sign_up: Zarejestruj siÄ™ na Mastodon już dziÅ›! suffix: MajÄ…c konto, możesz Å›ledzić ludzi, publikować wpisy i wymieniać siÄ™ wiadomoÅ›ciami z użytkownikami innych serwerów Mastodona i nie tylko! didnt_get_confirmation: Nie otrzymaÅ‚eÅ›(-aÅ›) instrukcji weryfikacji? + dont_have_your_security_key: Nie masz klucza bezpieczeÅ„stwa? forgot_password: Nie pamiÄ™tasz hasÅ‚a? invalid_reset_password_token: Token do resetowania hasÅ‚a jest nieprawidÅ‚owy lub utraciÅ‚ ważność. Spróbuj uzyskać nowy. + link_to_otp: Wprowadź kod dwustopniowego uwierzytelniania z telefonu lub użyj zapasowego kodu + link_to_webauth: Użyj swojego urzÄ…dzenia z kluczem bezpieczeÅ„stwa login: Zaloguj siÄ™ logout: Wyloguj siÄ™ migrate_account: PrzenieÅ› konto @@ -723,7 +780,9 @@ pl: functional: Twoje konto caÅ‚kowicie funkcjonuje. pending: Twoje zgÅ‚oszenie czeka na zatwierdzenie przez nas. Może to trochÄ™ potrwać. Jeżeli zgÅ‚oszenie zostanie przyjÄ™te, otrzymasz wiadomość e-mail. redirecting_to: Twoje konto jest nieaktywne, ponieważ obecnie przekierowuje je na %{acct}. + too_fast: Zbyt szybko przesÅ‚ano formularz, spróbuj ponownie. trouble_logging_in: Masz problem z zalogowaniem siÄ™? + use_security_key: Użyj klucza bezpieczeÅ„stwa authorize_follow: already_following: Już Å›ledzisz to konto already_requested: Już wysÅ‚aÅ‚eÅ›(-aÅ›) proÅ›bÄ™ o możliwość Å›ledzenia tego konta @@ -748,6 +807,7 @@ pl: date: formats: default: "%d. %b %Y" + with_month_name: "%d. %B %Y" datetime: distance_in_words: about_x_hours: "%{count}g" @@ -812,6 +872,7 @@ pl: request: Uzyskaj archiwum size: Rozmiar blocks: Zablokowani + bookmarks: ZakÅ‚adki csv: CSV domain_blocks: Blokady domen lists: Listy @@ -881,6 +942,8 @@ pl: status: Stan weryfikacji view_proof: WyÅ›wietl dowód imports: + errors: + over_rows_processing_limit: zawiera wiÄ™cej niż %{count} wierszy modes: merge: Połącz merge_long: Zachowaj obecne wpisy i dodaj nowe @@ -890,6 +953,7 @@ pl: success: Twoje dane zostaÅ‚y zaÅ‚adowane i zostanÄ… niebawem przetworzone types: blocking: Lista blokowanych + bookmarks: ZakÅ‚adki domain_blocking: Lista zablokowanych domen following: Lista Å›ledzonych muting: Lista wyciszonych @@ -960,6 +1024,10 @@ pl: redirect: Twoje obecne konto zostanie uaktualnione o informacjÄ™ o przeniesieniu i wyłączone z wyszukiwania moderation: title: Moderacja + move_handler: + carry_blocks_over_text: Ten użytkownik przeniósÅ‚ siÄ™ z konta %{acct}, które zablokowaÅ‚eÅ›(-aÅ›). + carry_mutes_over_text: Ten użytkownik przeniósÅ‚ siÄ™ z konta %{acct}, które wyciszyÅ‚eÅ›(-aÅ›). + copy_account_note_text: 'Ten użytkownik przeniósÅ‚ siÄ™ z konta %{acct}, oto Twoje poprzednie notatki o nim:' notification_mailer: digest: action: WyÅ›wietl wszystkie powiadomienia @@ -1012,6 +1080,14 @@ pl: quadrillion: bld thousand: tys trillion: bln + otp_authentication: + code_hint: Aby potwierdzić, wprowadź kod wygenerowany przez aplikacjÄ™ uwierzytelniajÄ…cÄ… + description_html: JeÅ›li włączysz <strong>uwierzytelnianie dwuetapowe</strong> używajÄ…c aplikacji uwierzytelniajÄ…cej, logowanie siÄ™ bÄ™dzie wymagaÅ‚o podania tokenu wyÅ›wietlonego na Twoim telefonie. + enable: Aktywuj + instructions_html: "<strong>Zeskanuj ten kod QR na swoim telefonie za pomocÄ… Google Authenticator lub podobnej aplikacji TOTP</strong>. Od teraz bÄ™dzie ona generowaÅ‚a kody wymagane przy logowaniu." + manual_instructions: 'JeÅ›li nie możesz zeskanować kodu QR i musisz wprowadzić go rÄ™cznie, oto klucz w formie tekstu:' + setup: Skonfiguruj + wrong_code: Wprowadzony kod jest nieprawidÅ‚owy! Czy czas serwera i urzÄ…dzenia jest poprawny? pagination: newer: Nowsze next: NastÄ™pna @@ -1040,6 +1116,7 @@ pl: relationships: activity: Aktywność konta dormant: UÅ›pione + follow_selected_followers: Zacznij Å›ledzić wybranych Å›ledzÄ…cych followers: ÅšledzÄ…cy following: Åšledzeni invited: Zaproszeni @@ -1136,10 +1213,16 @@ pl: profile: Profil relationships: Åšledzeni i Å›ledzÄ…cy two_factor_authentication: Uwierzytelnianie dwuetapowe + webauthn_authentication: Klucze bezpieczeÅ„stwa spam_check: spam_detected: To zgÅ‚oszenie jest automatyczne. ZostaÅ‚ wykryty spam. statuses: attached: + audio: + few: "%{count} pliki dźwiÄ™kowe" + many: "%{count} plików dźwiÄ™kowych" + one: "%{count} plik dźwiÄ™kowy" + other: pliki dźwiÄ™kowe (%{count}) description: 'Załączono: %{attached}' image: few: "%{count} obrazy" @@ -1181,6 +1264,8 @@ pl: other: "%{count} gÅ‚osy" vote: GÅ‚osuj show_more: Pokaż wiÄ™cej + show_newer: Pokaż nowsze + show_older: Pokaż starsze show_thread: Pokaż wÄ…tek sign_in_to_participate: Zaloguj siÄ™, aby udzielić siÄ™ w tej konwersacji title: '%{name}: "%{quote}"' @@ -1289,21 +1374,20 @@ pl: default: "%d. %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Aby kontynuować, wprowadź kod wyÅ›wietlany przez aplikacjÄ™ uwierzytelniajÄ…cÄ… - description_html: JeÅ›li włączysz <strong>uwierzytelnianie dwuetapowe</strong>, logowanie siÄ™ bÄ™dzie wymagaÅ‚o podania tokenu wyÅ›wietlonego na Twoim telefonie. + add: Dodaj disable: Wyłącz - enable: Włącz + disabled_success: PomyÅ›lnie wyłączono uwierzytelnianie dwuetapowe + edit: Edytuj enabled: Uwierzytelnianie dwuetapowe jest włączone enabled_success: PomyÅ›lnie aktywowano uwierzytelnianie dwuetapowe generate_recovery_codes: Generuj kody zapasowe - instructions_html: "<strong>Zeskanuj ten kod QR na swoim urzÄ…dzeniu za pomocÄ… Google Authenticator, FreeOTP lub podobnej aplikacji</strong>. Od teraz bÄ™dzie ona generowaÅ‚a kody wymagane przy logowaniu." lost_recovery_codes: Kody zapasowe pozwolÄ… uzyskać dostÄ™p do portalu, jeżeli utracisz dostÄ™p do telefonu. Jeżeli utracisz dostÄ™p do nich, możesz wygenerować je ponownie tutaj. Poprzednie zostanÄ… unieważnione. - manual_instructions: 'Jeżeli nie możesz zeskanować kodu QR, musisz wprowadzić ten kod rÄ™cznie:' + methods: Metody uwierzytelniania dwuetapowego + otp: Aplikacja uwierzytelniajÄ…ca recovery_codes: Przywróć kody zapasowe recovery_codes_regenerated: PomyÅ›lnie wygenerowano ponownie kody zapasowe recovery_instructions_html: Jeżeli kiedykolwiek utracisz dostÄ™p do telefonu, możesz wykorzystać jeden z kodów zapasowych, aby odzyskać dostÄ™p do konta. <strong>Trzymaj je w bezpiecznym miejscu</strong>. Na przykÅ‚ad, wydrukuj je i przechowuj z ważnymi dokumentami. - setup: Skonfiguruj - wrong_code: Wprowadzony kod jest niepoprawny! Czy czas serwera i urzÄ…dzenia jest poprawny? + webauthn: Klucze bezpieczeÅ„stwa user_mailer: backup_ready: explanation: ZażądaÅ‚eÅ› peÅ‚nej kopii zapasowej konta na Mastodonie. Jest ona dostÄ™pna do pobrania! @@ -1318,6 +1402,7 @@ pl: warning: explanation: disable: Kiedy Twoje konto jest wyłączone, Twoje dane pozostajÄ… na serwerze, ale nie możesz wykonywać żadnych dziaÅ‚aÅ„, zanim zostanie odblokowane. + sensitive: WysyÅ‚ane przez Ciebie pliki multimedialne i media z odnoÅ›ników bÄ™dÄ… traktowane jako wrażliwe. silence: Kiedy Twoje konto jest ograniczone, tylko osoby które je Å›ledzÄ… bÄ™dÄ… widzieć Twoje wpisy. Może ono też przestać być widoczne na publicznych listach. Inni wciąż mogÄ… zacząć CiÄ™ Å›ledzić. suspend: Twoje konto zostaÅ‚o zawieszone i wszystkie Twoje wpisy wraz z zawartoÅ›ciÄ… multimedialnÄ… zostaÅ‚y nieodwracalnie usuniÄ™te z tego serwera i serwerów, których użytkownicy Å›ledzili CiÄ™. get_in_touch: Możesz odpowiedzieć na ten e-mail aby pozostać w kontakcie z prowadzÄ…cymi %{instance}. @@ -1326,11 +1411,13 @@ pl: subject: disable: Twoje konto %{acct} zostaÅ‚o wyłączone none: Ostrzeżenie dla %{acct} + sensitive: Zawartość multimedialna publikowana przez Twoje konto %{acct} zostaÅ‚a oznaczona jako wrażliwa silence: Twoje konto %{acct} zostaÅ‚o ograniczone suspend: Twoje konto %{acct} zostaÅ‚o zawieszone title: disable: Konto wyłączone none: Ostrzeżenie + sensitive: Twoja zawartość multimedialna zostaÅ‚a oznaczona jako wrażliwa silence: Konto ograniczone suspend: Konto zawieszone welcome: @@ -1351,9 +1438,11 @@ pl: tips: Wskazówki title: Witaj na pokÅ‚adzie, %{name}! users: + blocked_email_provider: Ten dostawca e-mail jest niedozwolony follow_limit_reached: Nie możesz Å›ledzić wiÄ™cej niż %{limit} osób generic_access_help_html: Nie możesz uzyskać dostÄ™pu do konta? Skontaktuj siÄ™ z %{email} aby uzyskać pomoc invalid_email: Adres e-mail jest niepoprawny + invalid_email_mx: Ten adres e-mail wydaje siÄ™ nie istnieć invalid_otp_token: Kod uwierzytelniajÄ…cy jest niepoprawny invalid_sign_in_token: NieprawidÅ‚owy kod zabezpieczajÄ…cy otp_lost_help_html: Jeżeli utracisz dostÄ™p do obu, możesz skontaktować siÄ™ z %{email} @@ -1363,3 +1452,20 @@ pl: verification: explanation_html: 'Możesz <strong>zweryfikować siebie jako wÅ‚aÅ›ciciela stron, do których odnoÅ›niki znajdujÄ… siÄ™ w metadanych</strong>. Aby to zrobić, strona musi zawierać odnoÅ›nik do Twojego profilu na Mastodonie. OdnoÅ›nik <strong>musi</strong> zawierać atrybut <code>rel="me"</code>. Jego zawartość nie ma znaczenia. PrzykÅ‚ad:' verification: Weryfikacja + webauthn_credentials: + add: Dodaj nowy klucz bezpieczeÅ„stwa + create: + error: WystÄ…piÅ‚ problem z dodawaniem klucza bezpieczeÅ„stwa. Spróbuj ponownie. + success: PomyÅ›lnie dodano klucz bezpieczeÅ„stwa. + delete: UsuÅ„ + delete_confirmation: Czy jesteÅ› pewien, że chcesz usunąć ten klucz bezpieczeÅ„stwa? + description_html: JeÅ›li włączysz <strong>uwierzytelnianie kluczem bezpieczeÅ„stwa</strong>, logowanie bÄ™dzie wymagaÅ‚o użycia jednego z kluczy bezpieczeÅ„stwa. + destroy: + error: WystÄ…piÅ‚ problem z usuwaniem klucza bezpieczeÅ„stwa. Spróbuj ponownie. + success: PomyÅ›lnie usuniÄ™to klucz bezpieczeÅ„stwa. + invalid_credential: NieprawidÅ‚owy klucz bezpieczeÅ„stwa + nickname_hint: Wprowadź nazwÄ™ twojego nowego klucza bezpieczeÅ„stwa + not_enabled: Nie włączyÅ‚eÅ› WebAuthn + not_supported: Twoja przeglÄ…darka nie obsÅ‚uguje kluczy bezpieczeÅ„stwa + otp_required: Aby użyć kluczy bezpieczeÅ„stwa, najpierw włącz uwierzytelnianie dwuskÅ‚adnikowe. + registered_on: Zarejestrowano %{date} diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 2e2a8d4eb7d508ae9f3d9c09ad736eda917ab7e5..529548225a8c5484417064aebea3103d3bfa640e 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -60,6 +60,7 @@ pt-BR: one: Seguidor other: Seguidores following: Seguindo + instance_actor_flash: Esta conta é um ator virtual usado para representar o próprio servidor e não um usuário individual. É utilizada para fins de federação e não deve ser suspensa. joined: Entrou em %{date} last_active: última atividade link_verified_on: O link foi verificado em %{date} @@ -98,6 +99,7 @@ pt-BR: add_email_domain_block: Adicionar o domÃnio de e-mail à lista negra approve: Aprovar approve_all: Aprovar tudo + approved_msg: Aprovado com sucesso o pedido de registro de %{username} are_you_sure: Você tem certeza? avatar: Imagem de perfil by_domain: DomÃnio @@ -111,9 +113,11 @@ pt-BR: confirm: Confirmar confirmed: Confirmado confirming: Confirmando + delete: Excluir dados deleted: ExcluÃdo demote: Rebaixar - disable: Desativar + destroyed_msg: Os dados de %{username} estão na fila para serem excluÃdos em breve + disable: Congelar disable_two_factor_authentication: Desativar autenticação de dois fatores disabled: Desativada display_name: Nome de exibição @@ -121,12 +125,14 @@ pt-BR: edit: Editar email: E-mail email_status: Status do e-mail - enable: Ativar + enable: Descongelar enabled: Ativada + enabled_msg: Descongelada com sucesso a conta de %{username} followers: Seguidores follows: Seguindo header: Capa inbox_url: URL da caixa de entrada + invite_request_text: Motivos para entrar invited_by: Convidado por ip: IP joined: Entrou @@ -138,6 +144,8 @@ pt-BR: login_status: Situação da conta media_attachments: MÃdias anexadas memorialize: Converter em memorial + memorialized: Convertidas em memorial + memorialized_msg: Transformou com sucesso %{username} em uma conta memorial moderation: active: Ativo all: Todos @@ -158,10 +166,14 @@ pt-BR: public: Público push_subscription_expires: Inscrição PuSH expira redownload: Atualizar perfil + redownloaded_msg: Atualizado com sucesso o perfil de %{username} a partir da origem reject: Vetar reject_all: Vetar tudo + rejected_msg: Rejeitado com sucesso o pedido de registro de %{username} remove_avatar: Remover imagem de perfil remove_header: Remover capa + removed_avatar_msg: Removida com sucesso a imagem de avatar de %{username} + removed_header_msg: Removida com sucesso a imagem de capa de %{username} resend_confirmation: already_confirmed: Este usuário já está confirmado send: Reenviar o e-mail de confirmação @@ -178,6 +190,8 @@ pt-BR: search: Pesquisar search_same_email_domain: Outros usuários com o mesmo domÃnio de e-mail search_same_ip: Outros usuários com o mesmo IP + sensitive: SensÃveis + sensitized: marcadas como sensÃveis shared_inbox_url: Link da caixa de entrada compartilhada show: created_reports: Denúncias desta conta @@ -187,13 +201,19 @@ pt-BR: statuses: Toots subscribe: Inscrever-se suspended: Banido + suspension_irreversible: Os dados desta conta foram excluÃdos de forma irreversÃvel. Você pode remover a suspensão da conta para torná-la utilizável, mas ela não irá recuperar nenhum dado que ela possuÃa anteriormente. + suspension_reversible_hint_html: A conta foi suspensa e os dados serão totalmente removidos em %{date}. Até lá, a conta pode ser restaurada sem nenhum efeito negativo. Se você deseja remover todos os dados da conta imediatamente, você pode fazer isso abaixo. time_in_queue: Esperando na fila por %{time} title: Contas unconfirmed_email: E-mail não confirmado + undo_sensitized: Desfazer sensÃvel undo_silenced: Desfazer silêncio undo_suspension: Desbanir + unsilenced_msg: Removidas com sucesso as limitações da conta de %{username} unsubscribe: Cancelar inscrição + unsuspended_msg: Removida com sucesso a suspensão da conta de %{username} username: Nome de usuário + view_domain: Ver resumo para o domÃnio warn: Notificar web: Web whitelisted: Permitido @@ -208,31 +228,36 @@ pt-BR: create_domain_allow: Adicionar domÃnio permitido create_domain_block: Criar Bloqueio de DomÃnio create_email_domain_block: Criar Bloqueio de DomÃnio de E-mail + create_ip_block: Criar regra de IP demote_user: Rebaixar usuário destroy_announcement: Excluir anúncio destroy_custom_emoji: Excluir emoji personalizado destroy_domain_allow: Excluir domÃnio permitido destroy_domain_block: Excluir Bloqueio de DomÃnio destroy_email_domain_block: Excluir bloqueio de domÃnio de e-mail + destroy_ip_block: Excluir regra de IP destroy_status: Excluir Status disable_2fa_user: Desativar autenticação de dois fatores disable_custom_emoji: Desativar Emoji Personalizado disable_user: Desativar usuário enable_custom_emoji: Ativar Emoji Personalizado enable_user: Ativar usuário - memorialize_account: Memorizar Conta + memorialize_account: Converter conta em memorial promote_user: Promover usuário remove_avatar_user: Remover Avatar reopen_report: Reabrir Relatório reset_password_user: Redefinir a senha resolve_report: Resolver Relatório + sensitive_account: Marcar a mÃdia na sua conta como sensÃvel silence_account: Silenciar conta suspend_account: Suspender Conta unassigned_report: Remover relatório + unsensitive_account: Desmarcar a mÃdia na sua conta como sensÃvel unsilence_account: Desfazer silenciar conta unsuspend_account: Remover suspensão de conta update_announcement: Editar anúncio update_custom_emoji: Editar Emoji Personalizado + update_domain_block: Atualizar bloqueio de domÃnio update_status: Editar Status actions: assigned_to_self_report: "%{name} pegou a denúncia %{target}" @@ -244,31 +269,36 @@ pt-BR: create_domain_allow: "%{name} permitiu %{target}" create_domain_block: "%{name} bloqueou %{target}" create_email_domain_block: "%{name} adicionou o domÃnio de e-mail %{target} à lista negra" + create_ip_block: "%{name} criou regra para o IP %{target}" demote_user: "%{name} rebaixou o usuário %{target}" destroy_announcement: "%{name} excluiu o anúncio %{target}" destroy_custom_emoji: "%{name} excluiu emoji %{target}" destroy_domain_allow: "%{name} bloqueou %{target}" destroy_domain_block: "%{name} desbloqueou %{target}" destroy_email_domain_block: "%{name} adicionou domÃnio de e-mail %{target} à lista branca" + destroy_ip_block: "%{name} excluiu regra para o IP %{target}" destroy_status: "%{name} excluiu toot de %{target}" disable_2fa_user: "%{name} desativou a exigência de autenticação de dois fatores para o usuário %{target}" disable_custom_emoji: "%{name} desativou o emoji %{target}" disable_user: "%{name} desativou o acesso para o usuário %{target}" enable_custom_emoji: "%{name} ativou o emoji %{target}" enable_user: "%{name} ativou o acesso para o usuário %{target}" - memorialize_account: "%{name} transformou a conta de %{target} em um memorial" + memorialize_account: "%{name} transformou a conta de %{target} em um página de memorial" promote_user: "%{name} promoveu o usuário %{target}" remove_avatar_user: "%{name} removeu a imagem de perfil de %{target}" reopen_report: "%{name} reabriu a denúncia %{target}" reset_password_user: "%{name} redefiniu a senha do usuário %{target}" resolve_report: "%{name} resolveu a denúncia %{target}" + sensitive_account: "%{name} marcou a mÃdia de %{target} como sensÃvel" silence_account: "%{name} silenciou a conta de %{target}" suspend_account: "%{name} baniu a conta de %{target}" unassigned_report: "%{name} largou a denúncia %{target}" + unsensitive_account: "%{name} desmarcou a mÃdia de %{target} como sensÃvel" unsilence_account: "%{name} desativou o silêncio de %{target}" unsuspend_account: "%{name} removeu a suspensão da conta de %{target}" update_announcement: "%{name} atualizou o anúncio %{target}" update_custom_emoji: "%{name} atualizou o emoji %{target}" + update_domain_block: "%{name} atualizou o bloqueio de domÃnio para %{target}" update_status: "%{name} atualizou o status de %{target}" deleted_status: "(status excluÃdo)" empty: Nenhum registro encontrado. @@ -391,7 +421,7 @@ pt-BR: other: "%{count} contas no banco de dados foram afetadas" retroactive: silence: Dessilenciar contas existentes afetadas deste domÃnio - suspend: Dessuspender contas existentes afetadas deste domÃnio + suspend: Remover a suspensão das contas afetadas deste domÃnio title: Desfazer bloqueio de domÃnio para %{domain} undo: Desfazer undo: Desfazer bloqueio de domÃnio @@ -411,6 +441,7 @@ pt-BR: instances: by_domain: DomÃnio delivery_available: Envio disponÃvel + empty: Nenhum domÃnio encontrado. known_accounts: one: "%{count} conta conhecida" other: "%{count} contas conhecidas" @@ -434,6 +465,21 @@ pt-BR: expired: Expirado title: Filtro title: Convites + ip_blocks: + add_new: Criar regra + created_msg: Nova regra de IP adicionada com sucesso + delete: Excluir + expires_in: + '1209600': 2 semanas + '15778476': 6 meses + '2629746': 1 mês + '31556952': 1 ano + '86400': 1 dia + '94670856': 3 anos + new: + title: Criar nova regra de IP + no_ip_block_selected: Nenhuma regra de IP foi alterada pois nenhuma foi selecionada + title: Regras de IP pending_accounts: title: Contas pendentes (%{count}) relationships: @@ -473,6 +519,8 @@ pt-BR: comment: none: Nenhum created_at: Denunciado + forwarded: Encaminhados + forwarded_to: Encaminhado para %{domain} mark_as_resolved: Marcar como resolvido mark_as_unresolved: Marcar como não resolvido notes: @@ -542,6 +590,9 @@ pt-BR: min_invite_role: disabled: Ninguém title: Permitir convites de + require_invite_text: + desc_html: Quando o cadastro de novas contas exigir aprovação manual, tornar obrigatório, ao invés de opcional, o texto de solicitação de convite em "Por que você deseja criar uma conta aqui?" + title: Exigir que novos usuários preencham um texto de solicitação de convite registrations_mode: modes: approved: Aprovação necessária para criar conta @@ -681,8 +732,11 @@ pt-BR: prefix_sign_up: Crie uma conta no Mastodon hoje! suffix: Com uma conta, você poderá seguir pessoas, postar atualizações, trocar mensagens com usuários de qualquer instância Mastodon e muito mais! didnt_get_confirmation: Não recebeu instruções de confirmação? + dont_have_your_security_key: Não está com a sua chave de segurança? forgot_password: Esqueceu a sua senha? invalid_reset_password_token: Código de alteração de senha é inválido ou expirou. Por favor, solicite um novo. + link_to_otp: Digite um código de duas etapas do seu telefone ou um código de recuperação + link_to_webauth: Use seu dispositivo de chave de segurança login: Entrar logout: Sair migrate_account: Mudar-se para outra conta @@ -707,7 +761,9 @@ pt-BR: functional: Sua conta está totalmente operacional. pending: Sua solicitação está com revisão pendente por parte de nossa equipe. Você receberá um e-mail se ela for aprovada. redirecting_to: Sua conta está inativa porque atualmente está redirecionando para %{acct}. + too_fast: O formulário foi enviado muito rapidamente, tente novamente. trouble_logging_in: Problemas para entrar? + use_security_key: Usar chave de segurança authorize_follow: already_following: Você já segue already_requested: Você já enviou uma solicitação para seguir esta conta @@ -732,6 +788,7 @@ pt-BR: date: formats: default: "%d %b, %Y" + with_month_name: "%d de %b de %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -796,6 +853,7 @@ pt-BR: request: Solicitar o seu arquivo size: Tamanho blocks: Você bloqueou + bookmarks: Marcadores csv: CSV domain_blocks: Bloqueios de domÃnio lists: Listas @@ -872,6 +930,7 @@ pt-BR: success: Os seus dados foram enviados com sucesso e serão processados em instantes types: blocking: Lista de bloqueio + bookmarks: Marcadores domain_blocking: Lista de domÃnios bloqueados following: Pessoas que você segue muting: Lista de silenciados @@ -992,6 +1051,14 @@ pt-BR: quadrillion: QUA thousand: MIL trillion: TRI + otp_authentication: + code_hint: Digite o código gerado pelo seu aplicativo autenticador para confirmar + description_html: Se você habilitar a <strong>autenticação de dois fatores</strong> usando um aplicativo autenticador, o login exigirá que você esteja com o seu telefone, que gerará tokens para você entrar. + enable: Habilitar + instructions_html: "<strong>Escaneie este código QR no Google Authenticator ou em um aplicativo TOTP similar no seu telefone</strong>. A partir de agora, esse aplicativo irá gerar tokens que você terá que digitar ao fazer login." + manual_instructions: 'Se você não pode escanear o código QR e precisa digitá-lo manualmente, aqui está o segredo em texto:' + setup: Configurar + wrong_code: O código digitado é inválido! O horário do servidor e o horário do dispositivo estão corretos? pagination: newer: Mais novo next: Próximo @@ -1020,6 +1087,7 @@ pt-BR: relationships: activity: Atividade da conta dormant: Inativo + follow_selected_followers: Seguir os seguidores selecionados followers: Seguidores following: Seguindo invited: Convidado @@ -1116,6 +1184,7 @@ pt-BR: profile: Perfil relationships: Seguindo e seguidores two_factor_authentication: Autenticação de dois fatores + webauthn_authentication: Chaves de segurança spam_check: spam_detected: Esta é uma denúncia automática. Spam foi detectado. statuses: @@ -1154,6 +1223,8 @@ pt-BR: other: "%{count} votos" vote: Votar show_more: Mostrar mais + show_newer: Mostrar mais recentes + show_older: Mostrar mais antigos show_thread: Mostrar conversa sign_in_to_participate: Entre para participar dessa conversa title: '%{name}: "%{quote}"' @@ -1262,21 +1333,20 @@ pt-BR: default: "%H:%M em %d de %b de %Y" month: "%b de %Y" two_factor_authentication: - code_hint: Digite o código de dois fatores gerado pelo aplicativo no seu celular - description_html: Se você ativar a <strong>autenticação de dois fatores</strong>, o acesso à sua conta exigirá um celular, que gerará códigos para validação. + add: Adicionar disable: Desativar - enable: Ativar + disabled_success: Autenticação de dois fatores desabilitada com sucesso + edit: Editar enabled: Autenticação de dois fatores ativada enabled_success: Autenticação de dois fatores ativada com sucesso generate_recovery_codes: Gerar códigos de recuperação - instructions_html: "<strong>Escaneie este QR Code no Google Authenticator ou aplicativo TOTP similar no seu celular</strong>. De agora em diante, este aplicativo gerará códigos que você terá que inserir ao entrar na sua conta." lost_recovery_codes: Códigos de recuperação permitem que você recupere o acesso à sua conta caso perca o seu celular. Se você perdeu seus códigos de recuperação, você pode gerá-los novamente aqui. Seus códigos de recuperação anteriores serão invalidados. - manual_instructions: 'Se você não consegue escanear o QR code, aqui está o segredo em texto:' + methods: Métodos de dois fatores + otp: Aplicativo autenticador recovery_codes: Códigos de recuperação de reserva recovery_codes_regenerated: Códigos de recuperação gerados com sucesso recovery_instructions_html: Se você perder acesso ao seu celular, você pode usar um dos códigos de recuperação abaixo para acessar a sua conta. <strong>Mantenha os códigos de recuperação em um local seguro</strong>. Por exemplo, você pode imprimi-los e guardá-los junto com outros documentos importantes. - setup: Configurar - wrong_code: Código de dois fatores inválido. O horário da instância e o horário do seu celular estão corretos? + webauthn: Chaves de segurança user_mailer: backup_ready: explanation: Você pediu um backup completo da sua conta no Mastodon. E agora está pronto para ser baixado! @@ -1291,6 +1361,7 @@ pt-BR: warning: explanation: disable: Enquanto sua conta está congelada, seus dados de conta permanecem intactos, mas você não pode realizar nenhuma ação até que esteja destrancada. + sensitive: Seus arquivos de mÃdia carregados e mÃdias vinculadas serão tratados como sensÃveis. silence: Enquanto sua conta está silenciada, somente pessoas que já estão seguindo você poderão ver seus toots nessa instância, e você pode ser excluÃdo de várias listas públicas. No entanto, outros ainda podem te seguir manualmente. suspend: Sua conta foi banida e todos os seus toots e mÃdias foram irreversivelmente excluÃdos desta instância e das instâncias dos seus seguidores. get_in_touch: Você pode responder a este e-mail para entrar em contato com a equipe de %{instance}. @@ -1299,16 +1370,18 @@ pt-BR: subject: disable: Sua conta %{acct} foi bloqueada none: Aviso para %{acct} + sensitive: Sua conta %{acct} de postagem de mÃdia foi marcada como sensÃvel silence: Sua conta %{acct} foi silenciada suspend: Sua conta %{acct} foi banida title: disable: Conta bloqueada none: Aviso + sensitive: Sua mÃdia foi marcada como sensÃvel silence: Conta silenciada suspend: Conta banida welcome: edit_profile_action: Configurar perfil - edit_profile_step: Você pode customizar o seu perfil ao fazer upload de um avatar, header, alterar seu nome de exibição e mais. Se você preferir revisar novos seguidores antes de poderem te seguir, você pode trancar a sua conta. + edit_profile_step: Você pode personalizar o seu perfil enviando um avatar, uma capa, alterando seu nome de exibição e etc. Se você preferir aprovar seus novos seguidores antes de eles te seguirem, você pode trancar a sua conta. explanation: Aqui estão algumas dicas para você começar final_action: Comece a tootar final_step: 'Comece a tootar! Mesmo sem seguidores, suas mensagens públicas podem ser vistas pelos outros, por exemplo, na linha local e nas hashtags. Você pode querer fazer uma introdução usando a hashtag #introdução, ou em inglês usando a hashtag #introductions.' @@ -1324,9 +1397,11 @@ pt-BR: tips: Dicas title: Boas vindas, %{name}! users: + blocked_email_provider: Este provedor de e-mail não é permitido follow_limit_reached: Você não pode seguir mais de %{limit} pessoas generic_access_help_html: Problemas para acessar sua conta? Você pode entrar em contato com %{email} para obter ajuda invalid_email: Endereço de e-mail inválido + invalid_email_mx: O endereço de e-mail parece não existir invalid_otp_token: Código de dois fatores inválido invalid_sign_in_token: Cógido de segurança inválido otp_lost_help_html: Se você perder o acesso à ambos, você pode entrar em contato com %{email} @@ -1336,3 +1411,20 @@ pt-BR: verification: explanation_html: 'Você pode <strong>verificar os links nos metadados do seu perfil</strong>. Para isso, o site citado deve conter um link de volta para o seu perfil do Mastodon. O link de volta <strong>deve</strong> conter um atributo <code>rel="me"</code>. O conteúdo ou texto do link não importa. Aqui está um exemplo:' verification: Verificação + webauthn_credentials: + add: Adicionar nova chave de segurança + create: + error: Houve um problema ao adicionar sua chave de segurança. Tente novamente. + success: A sua chave de segurança foi adicionada com sucesso. + delete: Excluir + delete_confirmation: Você tem certeza de que deseja excluir esta chave de segurança? + description_html: Se você habilitar a <strong>autenticação por chave de segurança</strong>, o login exigirá que você use uma das suas chaves de segurança. + destroy: + error: Houve um problema ao excluir sua chave de segurança. Tente novamente. + success: Sua chave de segurança foi excluÃda com sucesso. + invalid_credential: Chave de segurança inválida + nickname_hint: Digite o apelido da sua nova chave de segurança + not_enabled: Você ainda não habilitou o WebAuthn + not_supported: Este navegador não tem suporte a chaves de segurança + otp_required: Para usar chaves de segurança, por favor habilite primeiro a autenticação de dois fatores. + registered_on: Registrado em %{date} diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 0d04bc358ebdf2a0a87904fa421f1efdbb2be4e9..f7b47fb10e5aacc880ff704de887ce3cc8bfe576 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -60,6 +60,7 @@ pt-PT: one: Seguidor other: Seguidores following: A seguir + instance_actor_flash: Esta conta é um actor virtual usado para representar a própria instância e não um utilizador individual. É usada para motivos de federação e não deve ser suspenso. joined: Aderiu %{date} last_active: última vez activo link_verified_on: A posse deste link foi verificada em %{date} @@ -79,7 +80,7 @@ pt-PT: posts_with_replies: Posts e Respostas reserved_username: Este nome de utilizadores é reservado roles: - admin: Administrador + admin: Administrador(a) bot: Robô group: Grupo moderator: Moderador @@ -90,14 +91,15 @@ pt-PT: action: Executar acção title: Executar acção de moderação em %{acct} account_moderation_notes: - create: Criar + create: Criar nota created_msg: Nota de moderação criada com sucesso! delete: Eliminar destroyed_msg: Nota de moderação excluÃda com sucesso! accounts: - add_email_domain_block: Adicione o domÃnio de email à lista negra + add_email_domain_block: Adicionar o domÃnio de email à lista negra approve: Aprovar approve_all: Aprovar todos + approved_msg: Inscrição de %{username} aprovada com sucesso are_you_sure: Tens a certeza? avatar: Imagem de Perfil by_domain: DomÃnio @@ -108,26 +110,30 @@ pt-PT: new_email: Novo e-mail submit: Alterar e-mail title: Alterar e-mail para %{username} - confirm: Confirme + confirm: Confirmar confirmed: Confirmado - confirming: Confirmer + confirming: A confirmar + delete: Eliminar dados deleted: Apagada demote: Rebaixar + destroyed_msg: Os dados de %{username} estão agora em fila de espera para serem eliminados de imediato disable: Desativar disable_two_factor_authentication: Desativar 2FA - disabled: Desativado + disabled: Congelada display_name: Nome a mostrar domain: DomÃnio edit: Editar email: E-mail - email_status: Estado do correio electrónico + email_status: Estado do e-mail enable: Ativar enabled: Ativado + enabled_msg: Descongelou com sucesso a conta %{username} followers: Seguidores - follows: Seguindo + follows: A seguir header: Cabeçalho inbox_url: URL da caixa de entrada - invited_by: Convidado por + invite_request_text: Razões para se juntar a nós + invited_by: Convidado(a) por ip: IP joined: Aderiu location: @@ -138,6 +144,8 @@ pt-PT: login_status: Estado de inÃcio de sessão media_attachments: Anexos de media memorialize: Converter em memorial + memorialized: Em memória + memorialized_msg: Conta %{username} transformada com sucesso em memorial moderation: active: Activo all: Todos @@ -158,10 +166,14 @@ pt-PT: public: Público push_subscription_expires: A Inscrição PuSH expira redownload: Atualizar perfil + redownloaded_msg: Atualizado com sucesso o perfil de %{username} da origem reject: Rejeitar reject_all: Rejeitar todas + rejected_msg: Inscrição de %{username} rejeitada com sucesso remove_avatar: Remover a imagem de perfil remove_header: Remover o cabeçalho + removed_avatar_msg: Imagem de perfil de %{username} removida com sucesso + removed_header_msg: Imagem de cabeçalho de %{username} removida com sucesso resend_confirmation: already_confirmed: Este utilizador já está confirmado send: Reenviar um email de confirmação @@ -171,13 +183,15 @@ pt-PT: resubscribe: Reinscrever role: Permissões roles: - admin: Administrador + admin: Administrador(a) moderator: Moderador staff: Equipa user: Utilizador search: Pesquisar search_same_email_domain: Outros utilizadores com o mesmo domÃnio de email search_same_ip: Outros utilizadores com o mesmo IP + sensitive: Marcar como sensÃvel + sensitized: marcada como sensÃvel shared_inbox_url: URL da caixa de entrada compartilhada show: created_reports: Relatórios gerados por esta conta @@ -187,13 +201,19 @@ pt-PT: statuses: Status subscribe: Inscrever-se suspended: Suspensa + suspension_irreversible: Os dados desta conta foram eliminados irreversivelmente. Você pode cancelar a suspensão da conta para torná-la utilizável, mas ela não irá recuperar os dados que possuÃa anteriormente. + suspension_reversible_hint_html: A conta foi suspensa e os dados serão totalmente eliminados em %{date}. Até lá, a conta poderá ser recuperada sem quaisquer efeitos negativos. Se deseja eliminar todos os dados desta conta imediatamente, pode fazê-lo em baixo. time_in_queue: Aguardando na fila %{time} title: Contas unconfirmed_email: E-mail não confirmado + undo_sensitized: Desmarcar como sensÃvel undo_silenced: Desfazer silenciar undo_suspension: Desfazer supensão + unsilenced_msg: Removeu com sucesso as limitações da conta %{username} unsubscribe: Cancelar inscrição + unsuspended_msg: Removeu com sucesso a suspensão da conta %{username} username: Utilizador + view_domain: Ver resumo do domÃnio warn: Aviso web: Web whitelisted: Está na lista branca @@ -208,12 +228,14 @@ pt-PT: create_domain_allow: Criar Permissão de DomÃnio create_domain_block: Criar Bloqueio de DomÃnio create_email_domain_block: Criar Bloqueio de DomÃnio de E-mail + create_ip_block: Criar regra de IP demote_user: Despromover Utilizador destroy_announcement: Remover Anúncio destroy_custom_emoji: Remover Emoji Personalizado destroy_domain_allow: Remover Permissão de DomÃnio destroy_domain_block: Remover Bloqueio de DomÃnio destroy_email_domain_block: Remover Bloqueio de DomÃnio de E-mail + destroy_ip_block: Eliminar regra de IP destroy_status: Remover Estado disable_2fa_user: Desativar 2FA disable_custom_emoji: Desativar Emoji Personalizado @@ -226,13 +248,16 @@ pt-PT: reopen_report: Reabrir Relatório reset_password_user: Repor Password resolve_report: Resolver Relatório + sensitive_account: Marcar a media na sua conta como sensÃvel silence_account: Silenciar Conta suspend_account: Suspender Conta unassigned_report: Desatribuir Relatório + unsensitive_account: Desmarcar a media na sua conta como sensÃvel unsilence_account: Deixar de Silenciar Conta unsuspend_account: Retirar Suspensão à Conta update_announcement: Atualizar Anúncio update_custom_emoji: Atualizar Emoji Personalizado + update_domain_block: Atualizar Bloqueio de DomÃnio update_status: Atualizar Estado actions: assigned_to_self_report: "%{name} atribuiu o relatório %{target} a si próprios" @@ -244,12 +269,14 @@ pt-PT: create_domain_allow: "%{name} colocou o domÃnio %{target} na lista branca" create_domain_block: "%{name} bloqueou o domÃnio %{target}" create_email_domain_block: "%{name} adicionou na lista negra o domÃnio de correio electrónico %{target}" + create_ip_block: "%{name} criou regra para o IP %{target}" demote_user: "%{name} rebaixou o utilizador %{target}" destroy_announcement: "%{name} excluiu o anúncio %{target}" destroy_custom_emoji: "%{name} destruiu o emoji %{target}" destroy_domain_allow: "%{name} removeu o domÃnio %{target} da lista branca" destroy_domain_block: "%{name} desbloqueou o domÃnio %{target}" destroy_email_domain_block: "%{name} retirou o domÃnio de e-mail %{target} da lista negra" + destroy_ip_block: "%{name} eliminou regra para o IP %{target}" destroy_status: "%{name} removeu o publicação feita por %{target}" disable_2fa_user: "%{name} desactivou o requerimento de autenticação em dois passos para o utilizador %{target}" disable_custom_emoji: "%{name} desabilitou o emoji %{target}" @@ -262,13 +289,16 @@ pt-PT: reopen_report: "%{name} reabriu o relatório %{target}" reset_password_user: "%{name} restabeleceu a palavra-passe do utilizador %{target}" resolve_report: "%{name} recusou o relatório %{target}" + sensitive_account: "%{name} marcou a media de %{target} como sensÃvel" silence_account: "%{name} silenciou a conta de %{target}" suspend_account: "%{name} suspendeu a conta de %{target}" unassigned_report: "%{name} não atribuiu o relatório %{target}" + unsensitive_account: "%{name} desmarcou a media de %{target} como sensÃvel" unsilence_account: "%{name} desativou o silêncio de %{target}" unsuspend_account: "%{name} desativou a suspensão de %{target}" update_announcement: "%{name} atualizou o anúncio %{target}" update_custom_emoji: "%{name} atualizou o emoji %{target}" + update_domain_block: "%{name} atualizou o bloqueio de domÃnio para %{target}" update_status: "%{name} atualizou o estado de %{target}" deleted_status: "(apagou a publicação)" empty: Não foram encontrados registos. @@ -372,6 +402,8 @@ pt-PT: silence: Silenciar suspend: Suspender title: Novo bloqueio de domÃnio + obfuscate: Ofuscar nome de domÃnio + obfuscate_hint: Ofuscar parcialmente o nome de domÃnio na lista, se estiverem habilitadas as limitações na publicação da lista de domÃnios private_comment: Comentário privado private_comment_hint: Comentário sobre essa limitação de domÃnio para uso interno pelos moderadores. public_comment: Comentário público @@ -411,6 +443,7 @@ pt-PT: instances: by_domain: DomÃnio delivery_available: Entrega disponÃvel + empty: Não foram encontrados domÃnios. known_accounts: one: "%{count} conta conhecida" other: "%{count} contas conhecidas" @@ -434,6 +467,21 @@ pt-PT: expired: Expirados title: Filtro title: Convites + ip_blocks: + add_new: Criar regra + created_msg: Nova regra de IP adicionada com sucesso + delete: Eliminar + expires_in: + '1209600': 2 semanas + '15778476': 6 meses + '2629746': 1 mês + '31556952': 1 ano + '86400': 1 dia + '94670856': 3 anos + new: + title: Criar nova regra de IP + no_ip_block_selected: Nenhuma regra de IP foi alterada pois nenhuma foi selecionada + title: Regras de IP pending_accounts: title: Contas pendentes (%{count}) relationships: @@ -473,6 +521,8 @@ pt-PT: comment: none: Nenhum created_at: Relatado + forwarded: Encaminhado + forwarded_to: Encaminhado para %{domain} mark_as_resolved: Marcar como resolvido mark_as_unresolved: Marcar como não resolvido notes: @@ -516,6 +566,7 @@ pt-PT: domain_blocks_rationale: title: Mostrar motivo enable_bootstrap_timeline_accounts: + desc_html: Faça com que novos utilizadores sigam automaticamente contas configuradas, para que a cronologia destes não se apresente inicialmente vazia title: Habilitar seguidores predefinidos para novos utilizadores hero: desc_html: Apresentado na primeira página. Pelo menos 600x100px recomendados. Quando não é definido, é apresentada a miniatura da instância @@ -542,6 +593,9 @@ pt-PT: min_invite_role: disabled: Ninguém title: Permitir convites de + require_invite_text: + desc_html: Quando os registos exigirem aprovação manual, faça o texto "Porque se quer juntar a nós?" da solicitação de convite obrigatório, em vez de opcional + title: Exigir que novos utilizadores preencham um texto de solicitação de convite registrations_mode: modes: approved: Registo sujeito a aprovação @@ -681,8 +735,11 @@ pt-PT: prefix_sign_up: Inscreva-se hoje no Mastodon! suffix: Com uma conta, poderá seguir pessoas, publicar atualizações e trocar mensagens com utilizadores de qualquer instância Mastodon e muito mais! didnt_get_confirmation: Não recebeu o email de confirmação? + dont_have_your_security_key: Não tem a sua chave de segurança? forgot_password: Esqueceste a palavra-passe? invalid_reset_password_token: Token de modificação da palavra-passe é inválido ou expirou. Por favor, solicita um novo. + link_to_otp: Insere um código de duas etapas do teu telemóvel ou um código de recuperação + link_to_webauth: Usa o teu dispositivo de chave de segurança login: Entrar logout: Sair migrate_account: Mudar para uma conta diferente @@ -707,7 +764,9 @@ pt-PT: functional: A sua conta está totalmente operacional. pending: A sua inscrição está pendente de revisão pela nossa equipa. Isso pode demorar algum tempo. Receberá um e-mail se a sua conta for aprovada. redirecting_to: A sua conta está inativa porque está atualmente a ser redirecionada para %{acct}. + too_fast: Formulário enviado muito rapidamente, tente novamente. trouble_logging_in: Problemas em iniciar sessão? + use_security_key: Usar chave de segurança authorize_follow: already_following: Tu já estás a seguir esta conta already_requested: Já enviou anteriormente um pedido para seguir esta conta @@ -732,6 +791,7 @@ pt-PT: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -796,6 +856,7 @@ pt-PT: request: Pede o teu arquivo size: Tamanho blocks: Bloqueaste + bookmarks: Itens Salvos csv: CSV domain_blocks: Bloqueios de domÃnio lists: Listas @@ -863,6 +924,8 @@ pt-PT: status: Estado da verificação view_proof: Ver prova imports: + errors: + over_rows_processing_limit: contém mais de %{count} linhas modes: merge: Juntar merge_long: Manter os registos existentes e adicionar novos registos @@ -872,6 +935,7 @@ pt-PT: success: Os teus dados foram enviados com sucesso e serão processados em breve types: blocking: Lista de bloqueio + bookmarks: Itens salvos domain_blocking: Lista de domÃnios bloqueados following: Lista de pessoas que estás a seguir muting: Lista de utilizadores silenciados @@ -992,6 +1056,14 @@ pt-PT: quadrillion: Q thousand: mil trillion: T + otp_authentication: + code_hint: Introduz o código gerado pela tua aplicação de autenticação para confirmar + description_html: Se ativar a <strong>autenticação em duas etapas</strong>, para entrar na sua conta terá de ter consigo o seu telefone, que vai gerar os tokens necessários à validação do seu acesso. + enable: Ativar + instructions_html: "<strong>Digitalize este código QR no Google Authenticator ou num aplicativo TOTP similar no seu telefone</strong>. A partir de agora, esse aplicativo irá gerar tokens que você terá que introduzir para aceder à sua conta." + manual_instructions: 'Se você não consegue digitalizar o código QR e precisa introduzi-lo manualmente, aqui está o código em texto:' + setup: Configurar + wrong_code: O código introduzido é inválido! A hora do servidor e a hora do dispositivo estão corretos? pagination: newer: Mais nova next: Seguinte @@ -1020,6 +1092,7 @@ pt-PT: relationships: activity: Atividade da conta dormant: Inativo + follow_selected_followers: Seguir seguidores selecionados followers: Seguidores following: A seguir invited: Convidado @@ -1116,6 +1189,7 @@ pt-PT: profile: Perfil relationships: Seguindo e seguidores two_factor_authentication: Autenticação em dois passos + webauthn_authentication: Chaves de segurança spam_check: spam_detected: Este é um relatório automatizado. Foi detectado spam. statuses: @@ -1154,6 +1228,8 @@ pt-PT: other: "%{count} votos" vote: Votar show_more: Mostrar mais + show_newer: Mostrar mais recentes + show_older: Mostrar mais antigos show_thread: Mostrar conversa sign_in_to_participate: Inicie a sessão para participar na conversa title: '%{name}: "%{quote}"' @@ -1256,27 +1332,26 @@ pt-PT: themes: contrast: Mastodon (Elevado contraste) default: Mastodon - mastodon-light: Mastodon (Leve) + mastodon-light: Mastodon (Claro) time: formats: default: "%H:%M em %d de %b de %Y" month: "%b de %Y" two_factor_authentication: - code_hint: Entre o código gerado pelo seu aplicativo para confirmar - description_html: Se ativar a <strong>autenticação em dois passos</strong>, quando logar será necessário o seu telefone que vai gerar os tokens para validação. + add: Adicionar disable: Desativar - enable: Ativar + disabled_success: Autenticação em duas etapas desativada com sucesso + edit: Editar enabled: A autenticação em dois passos está ativada enabled_success: Autenticação em dois passos ativada com sucesso generate_recovery_codes: Gerar códigos para recuperar conta - instructions_html: "<strong>Scaneie este código QR no seu Google Authenticator ou aplicativo similar no seu telefone</strong>. A partir de agora seu aplicativo irá gerar tokens que deverão ser digitados para você logar." lost_recovery_codes: Códigos de recuperação permite que você recupere o acesso a sua conta se você perder seu telefone. Se você perder os códigos de recuperação, você pode regera-los aqui. Seus códigos antigos serão invalidados. - manual_instructions: 'Se você não puder scanear o código QR e precisa digita-los manualmente, aqui está o segredo em texto.:' + methods: Métodos de duas etapas + otp: Aplicação de autenticação recovery_codes: Cópia de segurança dos códigos de recuperação recovery_codes_regenerated: Códigos de recuperação foram gerados com sucesso recovery_instructions_html: Se tu alguma vez perderes o teu smartphone, to poderás usar um dos códigos de recuperação para voltares a ter acesso à tua conta. <strong>Mantém os códigos de recuperação seguros</strong>. Por exemplo, tu podes imprimi-los e guardá-los junto a outros documentos importantes. - setup: Configurar - wrong_code: O código inserido é invalido! O horário do servidor e o horário do seu aparelho estão corretos? + webauthn: Chaves de segurança user_mailer: backup_ready: explanation: Pediste uma cópia completa da tua conta Mastodon. Ela já está pronta para descarregares! @@ -1291,6 +1366,7 @@ pt-PT: warning: explanation: disable: Enquanto a tua conta está congelada, os seus dados permanecem intactos, mas tu não podes executar quaisquer acções até que ela seja desbloqueada. + sensitive: Os seus ficheiros de media carregados e os media ligados serão tratados como sensÃveis. silence: Enquanto a sua conta estiver limitada, só pessoas que já estiver a seguir irão ver as suas publicações nesta instância e poderá ser excluÃdo de várias listagens públicas. No entanto, outros ainda o poderão seguir de forma manual. suspend: A sua conta foi suspensa e todas as suas publicações e os seus ficheiros de media foram irreversivelmente removidos desta instância e das instâncias onde tinhas seguidores. get_in_touch: Pode responder a este e-mail para entrar em contacto com a equipa de %{instance}. @@ -1299,11 +1375,13 @@ pt-PT: subject: disable: A tua conta %{acct} foi congelada none: Aviso para %{acct} + sensitive: As publicações de media da sua conta %{acct} foram marcadas como sensÃveis silence: A tua conta %{acct} foi limitada suspend: A tua conta %{acct} foi suspensa title: disable: Conta congelada none: Aviso + sensitive: A sua media foi marcada como sensÃvel silence: Conta limitada suspend: Conta suspensa welcome: @@ -1318,15 +1396,17 @@ pt-PT: review_preferences_step: Certifica-te de configurar as tuas preferências, tais como os e-mails que gostarias de receber ou o nÃvel de privacidade que desejas que as tuas publicações tenham por defeito. Se não sofres de enjoo, podes ativar a opção de auto-iniciar GIFs. subject: Bem-vindo ao Mastodon tip_federated_timeline: A cronologia federativa é uma visão global da rede Mastodon. Mas só inclui pessoas que os teus vizinhos subscrevem, por isso não é uma visão completa. - tip_following: Você segue o(s) administrador(es) da sua instância por defeito. Para encontrar mais pessoas interessantes, procure nas cronologias local e federada. + tip_following: Segues o(s) administrador(es) do teu servidor por defeito. Para encontrar mais pessoas interessantes, procura nas cronologias local e federada. tip_local_timeline: A cronologia local é uma visão global das pessoas em %{instance}. Estes são os seus vizinhos mais próximos! tip_mobile_webapp: Se o teu navegador móvel te oferecer a possibilidade de adicionar o Mastodon ao teu homescreen, tu podes receber notificações push. Ele age como uma aplicação nativa de vários modos! tips: Dicas title: Bem-vindo a bordo, %{name}! users: + blocked_email_provider: Este provedor de e-mail não é permitido follow_limit_reached: Não podes seguir mais do que %{limit} pessoas generic_access_help_html: Problemas para aceder à sua conta? Pode entrar em contacto com %{email} para obter ajuda invalid_email: O endereço de e-mail é inválido + invalid_email_mx: O endereço de e-mail não parece existir invalid_otp_token: Código de autenticação inválido invalid_sign_in_token: Cógido de segurança inválido otp_lost_help_html: Se tu perdeste acesso a ambos, tu podes entrar em contacto com %{email} @@ -1336,3 +1416,20 @@ pt-PT: verification: explanation_html: 'Tu podes <strong>comprovar que és o dono dos links nos metadados do teu perfil</strong>. Para isso, o website para o qual o link aponta tem de conter um link para o teu perfil do Mastodon. Este link <strong>tem</strong> de ter um <code>rel="me"</code> atributo. O conteúdo do texto não é relevante. Aqui está um exemplo:' verification: Verificação + webauthn_credentials: + add: Adicionar nova chave de segurança + create: + error: Ocorreu um problema ao adicionar sua chave de segurança. Tente novamente. + success: A sua chave de segurança foi adicionada com sucesso. + delete: Remover + delete_confirmation: Tem a certeza de que pretende remover esta chave de segurança? + description_html: Se você ativar a <strong>autenticação com chave de segurança</strong>, para aceder à sua conta será necessário que utilize uma das suas chaves de segurança. + destroy: + error: Ocorreu um problema ao remover a sua chave de segurança. Tente novamente. + success: A sua chave de segurança foi removida com sucesso. + invalid_credential: Chave de segurança inválida + nickname_hint: Introduza o apelido da sua nova chave de segurança + not_enabled: Ainda não ativou o WebAuthn + not_supported: Este navegador não suporta chaves de segurança + otp_required: Para usar chaves de segurança, por favor ative primeiro a autenticação de duas etapas. + registered_on: Registado em %{date} diff --git a/config/locales/ro.yml b/config/locales/ro.yml index c1aec2d151782fa3afa9050bc06b6e420a766501..630bd91d6443e4f397cf1348edc27705eb0f57e1 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -680,21 +680,14 @@ ro: default: "%d %m, %Y, %H:%M" month: "%m %Y" two_factor_authentication: - code_hint: IntroduceÈ›i codul generat de aplicaÈ›ia dvs de autentificare pentru a confirma - description_html: Dacă activaÈ›i <strong>autentificarea în doi paÈ™i</strong>, autentificarea va necesita ca tu să fii în posesia telefonului tău, ceea ce va genera token-uri pentru ca tu să intri. disable: Dezactivează - enable: Activează enabled: Autentificare în doi paÈ™i este activată enabled_success: Autentificarea în doi paÈ™i activată cu succes generate_recovery_codes: Generează coduri de recuperare - instructions_html: "<strong>ScanaÈ›i acest cod QR în Google Authenticator sau o aplicaÈ›ie TOTP similiară de pe telefonul dvs.</strong>. De acum înainte, acea aplicaÈ›ie va genera token-uri pe care va trebui să îi introduceÈ›i atunci când vă conectaÈ›i." lost_recovery_codes: Codurile de recuperare vă permit să redobândiÈ›i accesul la contul dvs. dacă vă pierdeÈ›i telefonul. Dacă È›i-ai pierdut codurile de recuperare, le poÈ›i regenera aici. Codurile tale vechi de recuperare vor fi invalidate. - manual_instructions: 'Dacă nu puteÈ›i scana codul QR È™i trebuie să-l introduceÈ›i manual, aici este textul simplu pentru cheia secretă:' recovery_codes: Copie a codurilor de recuperare recovery_codes_regenerated: Coduri de recuperare regenerate cu succes recovery_instructions_html: Dacă îți pierzi vreodată accesul la telefon, poÈ›i folosi unul dintre codurile de recuperare de mai jos pentru a recâștiga accesul la contul tău. <strong>PăstraÈ›i codurile de recuperare în condiÈ›ii de siguranță</strong>. De exemplu, le puteÈ›i tipări È™i stoca cu alte documente importante. - setup: Configurare - wrong_code: Codul introdus nu a fost valid! Orele serverului È™i timpul dispozitivului sunt corecte? user_mailer: backup_ready: explanation: Ai solicitat o copie de rezervă completă a contului tău. Acum este gata pentru descărcare! diff --git a/config/locales/ru.yml b/config/locales/ru.yml index f316c5cdfca7f91800a600d32d4a870cc0f95300..9895f9a55d451d228326652ed8b746da847e3a5c 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -66,6 +66,7 @@ ru: one: подпиÑчик other: подпиÑчиков following: подпиÑки + instance_actor_flash: Ðта ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ - виртуальный пользователь, иÑпользуемый Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñамого Ñервера, а не отдельного пользователÑ. Она иÑпользуетÑÑ Ð´Ð»Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¾Ð½Ð½Ñ‹Ñ… целей и не может быть заморожена. joined: 'Дата региÑтрации: %{date}' last_active: поÑледнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ñть link_verified_on: Владение Ñтой ÑÑылкой было проверено %{date} @@ -106,6 +107,7 @@ ru: add_email_domain_block: Заблокировать e-mail домен approve: Подтвердить approve_all: Подтвердить вÑе + approved_msg: УÑпешно одобрена заÑвка на региÑтрацию %{username} are_you_sure: Ð’Ñ‹ уверены? avatar: Ðватар by_domain: Домен @@ -119,8 +121,10 @@ ru: confirm: Подтвердить confirmed: Подтверждено confirming: Подтверждение + delete: Удалить данные deleted: Удалён demote: Разжаловать + destroyed_msg: Данные %{username} поÑтавлены в очередь на удаление disable: Заморозка disable_two_factor_authentication: Отключить 2FA disabled: Отключено @@ -131,10 +135,12 @@ ru: email_status: Ð¡Ñ‚Ð°Ñ‚ÑƒÑ e-mail enable: Включить enabled: Включен + enabled_msg: Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{username} уÑпешно разморожена followers: ПодпиÑчики follows: ПодпиÑки header: Шапка inbox_url: URL входÑщих + invite_request_text: Причины Ð´Ð»Ñ Ð¿Ñ€Ð¸ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ invited_by: Приглашение выдал(а) ip: IP joined: Дата региÑтрации @@ -146,6 +152,8 @@ ru: login_status: Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð¾Ð¹ запиÑи media_attachments: Файлы мультимедиа memorialize: Сделать мемориалом + memorialized: Превращён в памÑтник + memorialized_msg: "%{username} уÑпешно превращён в памÑтник" moderation: active: ДейÑтвующие all: Ð’Ñе @@ -166,10 +174,14 @@ ru: public: Публичный push_subscription_expires: ПодпиÑка PuSH иÑтекает redownload: Обновить аватар + redownloaded_msg: Профиль %{username} уÑпешно обновлен из оригинала reject: Отклонить reject_all: Отклонить вÑе + rejected_msg: УÑпешно отклонено приложение Ð´Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации %{username} remove_avatar: Удалить аватар remove_header: Убрать шапку + removed_avatar_msg: Ðватар %{username} уÑпешно удален + removed_header_msg: УÑпешно удалено изображение заголовка %{username} resend_confirmation: already_confirmed: Ðтот пользователь уже подтвержден send: Повторно отправить подтверждение по Ñлектронной почте @@ -186,6 +198,8 @@ ru: search: ПоиÑк search_same_email_domain: Другие пользователи Ñ Ñ‚ÐµÐ¼ же доменом Ñлектронной почты search_same_ip: Другие пользователи Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же IP + sensitive: Деликатный + sensitized: отмечено как деликатный контент shared_inbox_url: URL общих входÑщих show: created_reports: Жалобы, отправленные Ñ Ñтой учётной запиÑи @@ -195,13 +209,19 @@ ru: statuses: ПоÑты subscribe: ПодпиÑатьÑÑ suspended: Заморожен + suspension_irreversible: Данные Ñтой учётной запиÑи были необратимо удалены. Ð’Ñ‹ можете разблокировать учетную запиÑÑŒ, чтобы Ñделать её доÑтупной, но Ñто не воÑÑтановит ранее имевшиеÑÑ Ð² ней данные. + suspension_reversible_hint_html: Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была заблокирована, и данные будут полноÑтью удалены %{date}. До Ñтого момента её можно воÑÑтановить без каких-либо неприÑтных поÑледÑтвий. ЕÑли вы хотите немедленно удалить вÑе данные учётной запиÑи, вы можете Ñделать Ñто ниже. time_in_queue: Ожидание в очереди %{time} title: Учётные запиÑи unconfirmed_email: Ðеподтверждённый e-mail + undo_sensitized: СнÑть отметку "деликатный" undo_silenced: Отменить Ñкрытие undo_suspension: СнÑть блокировку + unsilenced_msg: ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð¾Ð¹ запиÑи %{username} ÑнÑты уÑпешно unsubscribe: ОтпиÑатьÑÑ + unsuspended_msg: Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{username} уÑпешно разморожена username: Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + view_domain: ПроÑмотр Ñводки по домену warn: Предупреждение web: Веб whitelisted: Ð’ белом ÑпиÑке @@ -216,12 +236,14 @@ ru: create_domain_allow: Создать разрешение Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ð° create_domain_block: Блокировка доменов create_email_domain_block: Блокировка e-mail доменов + create_ip_block: Создать IP правило demote_user: Разжалование пользователей destroy_announcement: Удаление объÑвлений destroy_custom_emoji: Удаление Ñмодзи destroy_domain_allow: Удалить разрешение Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ð° destroy_domain_block: Разблокировка доменов destroy_email_domain_block: Разблокировка e-mail доменов + destroy_ip_block: Удалить IP правило destroy_status: Удаление поÑтов disable_2fa_user: Отключение 2FA disable_custom_emoji: Отключение Ñмодзи @@ -234,13 +256,16 @@ ru: reopen_report: Возобновление жалоб reset_password_user: Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ resolve_report: Отметка жалоб «решёнными» + sensitive_account: Отметить вÑе медиафайлы в вашей учётной запиÑи как деликатные silence_account: Скрытие пользователей suspend_account: Блокировка пользователей unassigned_report: СнÑтие жалоб + unsensitive_account: СнÑть отметку "деликатный" Ñ Ð¼ÐµÐ´Ð¸Ð°Ñ„Ð°Ð¹Ð»Ð¾Ð² вашей учётной запиÑи unsilence_account: Отмена ÑÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ unsuspend_account: Разблокировка пользователей update_announcement: Обновление объÑвлений update_custom_emoji: Обновление Ñмодзи + update_domain_block: Изменить блокировку домена update_status: Изменение поÑтов actions: assigned_to_self_report: "%{name} назначил(а) ÑÐµÐ±Ñ Ð´Ð»Ñ Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð¶Ð°Ð»Ð¾Ð±Ñ‹ %{target}" @@ -252,12 +277,14 @@ ru: create_domain_allow: "%{name} внеÑ(ла) домен %{target} в белый ÑпиÑок" create_domain_block: "%{name} заблокировал(а) домен %{target}" create_email_domain_block: "%{name} добавил(а) e-mail домен %{target} в чёрный ÑпиÑок" + create_ip_block: "%{name} Ñоздал правило Ð´Ð»Ñ IP %{target}" demote_user: "%{name} разжаловал(а) Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" destroy_announcement: "%{name} удалил объÑвление %{target}" destroy_custom_emoji: "%{name} измельчил(а) Ñмодзи %{target} в пыль" destroy_domain_allow: "%{name} убрал домен %{target} из белого ÑпиÑка" destroy_domain_block: "%{name} разблокировал(а) домен %{target}" destroy_email_domain_block: "%{name} добавил(а) e-mail домен %{target} в белый ÑпиÑок" + destroy_ip_block: "%{name} удалил правило Ð´Ð»Ñ IP %{target}" destroy_status: "%{name} удалил(а) поÑÑ‚ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" disable_2fa_user: "%{name} отключил(а) требование двухÑтапной авторизации Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" disable_custom_emoji: "%{name} отключил(а) Ñмодзи %{target}" @@ -270,13 +297,16 @@ ru: reopen_report: "%{name} переоткрыл(а) жалобу %{target}" reset_password_user: "%{name} ÑброÑил(а) пароль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" resolve_report: "%{name} решил(а) жалобу %{target}" + sensitive_account: "%{name} пометил медиа %{target} как деликатное" silence_account: "%{name} наложил(а) Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° видимоÑть поÑтов учётной запиÑи %{target}" suspend_account: "%{name} заблокировал(а) учётную запиÑÑŒ %{target}" unassigned_report: "%{name} ÑнÑла назначение жалобы %{target}" + unsensitive_account: '%{name} ÑнÑл отметку "деликатное" Ñ Ð¼ÐµÐ´Ð¸Ð° %{target}' unsilence_account: "%{name} ÑнÑл Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾Ñти поÑтов Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" unsuspend_account: "%{name} ÑнÑл(а) блокировку Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" update_announcement: "%{name} обновил объÑвление %{target}" update_custom_emoji: "%{name} обновил(а) Ñмодзи %{target}" + update_domain_block: "%{name} обновил блокировку домена Ð´Ð»Ñ %{target}" update_status: "%{name} изменил(а) поÑÑ‚ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{target}" deleted_status: "(удалённый поÑÑ‚)" empty: Журнал пуÑÑ‚. @@ -426,6 +456,7 @@ ru: instances: by_domain: Домен delivery_available: ДоÑтавка возможна + empty: Домены не найдены. known_accounts: few: "%{count} извеÑтные учётные запиÑи" many: "%{count} извеÑтных учётных запиÑей" @@ -451,6 +482,21 @@ ru: expired: ИÑтёкшие title: Фильтр title: ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ + ip_blocks: + add_new: Создать правило + created_msg: УÑпешно добавлено новое IP правило + delete: Удалить + expires_in: + '1209600': 2 недели + '15778476': 6 меÑÑцев + '2629746': 1 меÑÑц + '31556952': 1 год + '86400': 1 день + '94670856': 3 года + new: + title: Создать новое IP правило + no_ip_block_selected: Ðе было изменено ни одного IP правила, так как не было выбрано ни одного + title: IP правила pending_accounts: title: Ожидающие учетные запиÑи (%{count}) relationships: @@ -494,6 +540,8 @@ ru: comment: none: Ðет created_at: Создана + forwarded: ПереÑлано + forwarded_to: ПереÑлано на %{domain} mark_as_resolved: Отметить как решённую mark_as_unresolved: Отметить как нерешённую notes: @@ -563,6 +611,9 @@ ru: min_invite_role: disabled: Ðикого title: Разрешать Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾Ñ‚ + require_invite_text: + desc_html: Когда региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ ручного подтверждениÑ, Ñделать ответ на Ð²Ð¾Ð¿Ñ€Ð¾Ñ "Почему вы хотите приÑоединитьÑÑ?" обÑзательным, а не опциональным + title: ОбÑзать новых пользователей заполнÑть текÑÑ‚ запроÑа на приглашение registrations_mode: modes: approved: Ð”Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации требуетÑÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ðµ @@ -702,8 +753,11 @@ ru: prefix_sign_up: ЗарегиÑтрируйтеÑÑŒ в Mastodon уже ÑегоднÑ! suffix: Ð˜Ð¼ÐµÑ ÑƒÑ‡Ñ‘Ñ‚Ð½ÑƒÑŽ запиÑÑŒ, вы можете подпиÑыватьÑÑ Ð½Ð° людей, поÑтить обновлениÑ, обмениватьÑÑ ÑообщениÑми Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñми любых узлов Mastodon и не только! didnt_get_confirmation: Ðе получили инÑтрукцию Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ? + dont_have_your_security_key: У Ð²Ð°Ñ Ð½ÐµÑ‚ ключа безопаÑноÑти? forgot_password: Забыли пароль? invalid_reset_password_token: Токен ÑброÑа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½ÐµÐ²ÐµÑ€ÐµÐ½ или уÑтарел. ПожалуйÑта, запроÑите новый. + link_to_otp: Введите двухфакторный код Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð° или код воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ + link_to_webauth: ИÑпользуйте уÑтройÑтво Ñ ÐºÐ»ÑŽÑ‡Ð¾Ð¼ безопаÑноÑти login: Войти logout: Выйти migrate_account: ÐŸÐµÑ€ÐµÐ½Ð¾Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð¾Ð¹ запиÑи @@ -728,7 +782,9 @@ ru: functional: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в полном порÑдке. pending: Ваша заÑвка ожидает Ð¾Ð´Ð¾Ð±Ñ€ÐµÐ½Ð¸Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтраторами, Ñто может занÑть немного времени. Ð’Ñ‹ получите пиÑьмо, как только заÑвку одобрÑÑ‚. redirecting_to: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ деактивированна, потому что вы наÑтроили перенаправление на %{acct}. + too_fast: Форма отправлена Ñлишком быÑтро, попробуйте еще раз. trouble_logging_in: Ðе удаётÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸? + use_security_key: ИÑпользовать ключ безопаÑноÑти authorize_follow: already_following: Ð’Ñ‹ уже подпиÑаны на Ñту учётную запиÑÑŒ already_requested: Ð’Ñ‹ уже отправили Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑку на Ñту учётную запиÑÑŒ @@ -753,6 +809,7 @@ ru: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}ч" @@ -817,6 +874,7 @@ ru: request: ЗапроÑить ваш архив size: Размер blocks: СпиÑок блокировки + bookmarks: Закладки csv: CSV domain_blocks: Доменные блокировки lists: СпиÑки @@ -895,6 +953,7 @@ ru: success: Ваши данные были уÑпешно загружены и будут обработаны Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾Ð¹ ÑкороÑтью types: blocking: СпиÑок блокировки + bookmarks: Закладки domain_blocking: СпиÑок доменных блокировок following: ПодпиÑки muting: СпиÑок Ð³Ð»ÑƒÑˆÐµÐ½Ð¸Ñ @@ -1021,6 +1080,14 @@ ru: quadrillion: квадрлн thousand: Ñ‚Ñ‹Ñ trillion: трлн + otp_authentication: + code_hint: Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð²ÐµÐ´Ð¸Ñ‚Ðµ код, Ñгенерированный приложением-аутентификатором + description_html: ЕÑли вы включите <strong>двухфакторную аутентификацию</strong> Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ приложениÑ-аутентификатора, Вход в ÑиÑтему потребует от Ð²Ð°Ñ Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ телефона, который будет генерировать токены Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему. + enable: Включить + instructions_html: "<strong>ОтÑканируйте Ñтот QR-код в Google Authenticator или аналогичном приложении TOTP на вашем телефоне</strong>. С Ñтого момента приложение будет генерировать токены, которые вам придетÑÑ Ð²Ð²Ð¾Ð´Ð¸Ñ‚ÑŒ при входе." + manual_instructions: 'ЕÑли вы не можете отÑканировать QR-код и ввеÑти его вручную, то вот Ñекретный текÑÑ‚:' + setup: Создан + wrong_code: Введенный код недейÑтвителен! Ð’Ñ€ÐµÐ¼Ñ Ñервера и Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтройÑтва правильно? pagination: newer: Ðовее next: След @@ -1049,6 +1116,7 @@ ru: relationships: activity: ÐктивноÑть учётной запиÑи dormant: Ð—Ð°Ð±Ñ€Ð¾ÑˆÐµÐ½Ð½Ð°Ñ + follow_selected_followers: ПодпиÑатьÑÑ Ð½Ð° выбранных подпиÑчиков followers: ПодпиÑчики following: ПодпиÑки invited: Приглашённые @@ -1145,6 +1213,7 @@ ru: profile: Профиль relationships: ПодпиÑки и подпиÑчики two_factor_authentication: Подтверждение входа + webauthn_authentication: Ключи безопаÑноÑти spam_check: spam_detected: Ðто автоматичеÑкий отчет. Обнаружен Ñпам. statuses: @@ -1195,6 +1264,8 @@ ru: other: "%{count} голоÑов" vote: ГолоÑовать show_more: Развернуть + show_newer: Показать более новое + show_older: Показать Ñтарые show_thread: Открыть обÑуждение sign_in_to_participate: Войдите, чтобы принÑть учаÑтие в диÑкуÑÑии title: '%{name}: "%{quote}"' @@ -1299,21 +1370,20 @@ ru: default: "%d %b %Y, %H:%M" month: "%m.%Y" two_factor_authentication: - code_hint: Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð²ÐµÐ´Ð¸Ñ‚Ðµ код, Ñгенерированный приложением-аутентификатором. - description_html: 'Ðа Ñтой Ñтранице можно включить <strong>двухфакторную авторизацию</strong>: Ñ Ð½ÐµÐ¹, чтобы войти в Ñвою учётную запиÑÑŒ, потребуетÑÑ Ð²Ð²ÐµÑти небольшой временный код, генерируемый через приложение на Ñвоём Ñмартфоне.' + add: Добавить disable: Отключить - enable: Включить + disabled_success: Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑƒÑпешно отключена + edit: Изменить enabled: Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð½Ð°Ñтроена enabled_success: Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ ÑƒÑпешно наÑтроена generate_recovery_codes: Сгенерировать коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ - instructions_html: "<strong>ОтÑканируйте Ñтот QR-код Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Google Authenticator, ЯндекÑ.Ключа или любого другого подобного приложениÑ</strong>. ПоÑле ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ добавлениÑ, приложение начнёт генерировать коды, которые потребуетÑÑ Ð²Ð²Ð¾Ð´Ð¸Ñ‚ÑŒ Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð° в учётную запиÑÑŒ." lost_recovery_codes: Коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÑŽÑ‚ÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ в учётную запиÑÑŒ в Ñлучае утери Ñмартфона. ЕÑли вы потерÑли Ñвои коды воÑÑтановлениÑ, вы можете Ñоздать новые здеÑÑŒ. Прошлые коды работать переÑтанут. - manual_instructions: 'ЕÑли отÑканировать QR-код не получаетÑÑ Ð¸Ð»Ð¸ не предÑтавлÑетÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ð¼, вы можете ввеÑти его вручную:' + methods: Методы двухфакторной аутентификации + otp: Приложение Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ подлинноÑти recovery_codes: Коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ recovery_codes_regenerated: Коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑпешно Ñгенерированы recovery_instructions_html: 'ПожалуйÑта, Ñохраните коды ниже в надёжном меÑте: они понадобÑÑ‚ÑÑ, чтобы войти в учётную запиÑÑŒ, еÑли вы потерÑете доÑтуп к Ñвоему Ñмартфону. Ð’Ñ‹ можете вручную перепиÑать их, раÑпечатать и ÑпрÑтать Ñреди важных документов или, например, в любимой книжке. <strong>Каждый код дейÑтвителен один раз</strong>.' - setup: ÐаÑтроить - wrong_code: Введенный код неверен! Правильно ли уÑтановлены Ñерверное Ð²Ñ€ÐµÐ¼Ñ Ð¸ Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтройÑтва? + webauthn: Ключи безопаÑноÑти user_mailer: backup_ready: explanation: Ð’Ñ‹ запроÑили архив вÑех данных вашей учётной запиÑи Mastodon. Что ж, он готов к Ñкачиванию. @@ -1328,6 +1398,7 @@ ru: warning: explanation: disable: Пока ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ заморожена, ваши данные оÑтаютÑÑ Ð½ÐµÑ‚Ñ€Ð¾Ð½ÑƒÑ‚Ñ‹Ð¼Ð¸, но вы не можете производить никаких дейÑтвий до разблокировки. + sensitive: Ваши загруженные медиа-файлы и ÑвÑзанные Ñ Ð½Ð¸Ð¼Ð¸ медиа будут раÑÑматриватьÑÑ ÐºÐ°Ðº деликатные. silence: Пока дейÑтвуют данные ограничениÑ, публикуемые вами поÑты будут видеть иÑключительно люди, которые на Ð²Ð°Ñ ÑƒÐ¶Ðµ подпиÑаны на Ñтом узле, вы также можете быть иÑключены из различных публичных лент. ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° Ñто, оÑтальные пользователи по-прежнему могут подпиÑатьÑÑ Ð½Ð° ваÑ, чтобы читать новые поÑты. suspend: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ заблокирована и вÑе ваши поÑты и загруженные медиафайлы безвозвратно удалены Ñ Ñтого Ñервера и других Ñерверов, где у Ð²Ð°Ñ Ð±Ñ‹Ð»Ð¸ подпиÑчики. get_in_touch: Ð’Ñ‹ можете ответить на Ñто пиÑьмо, чтобы ÑвÑзатьÑÑ Ñ Ñотрудниками %{instance}. @@ -1336,11 +1407,13 @@ ru: subject: disable: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{acct} заморожена none: "%{acct} вынеÑено предупреждение" + sensitive: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{acct} помечена как Ð´ÐµÐ»Ð¸ÐºÐ°Ñ‚Ð½Ð°Ñ silence: Ðа учётную запиÑÑŒ %{acct} наложены Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ suspend: Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ %{acct} была заблокирована title: disable: Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ заморожена none: Предупреждение + sensitive: Ваш медиафайл был отмечен как деликатный silence: Ðа учётную запиÑÑŒ наложены Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ suspend: Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ заблокирована welcome: @@ -1361,9 +1434,11 @@ ru: tips: Советы title: Добро пожаловать на борт, %{name}! users: + blocked_email_provider: Ðтот почтовый провайдер не разрешен follow_limit_reached: Ð’Ñ‹ не можете подпиÑатьÑÑ Ð±Ð¾Ð»ÑŒÑˆÐµ, чем на %{limit} человек generic_access_help_html: Ðе можете войти в Ñвою учётную запиÑÑŒ? СвÑжитеÑÑŒ Ñ %{email} Ð´Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ð¸ invalid_email: Введенный e-mail неверен + invalid_email_mx: ÐÐ´Ñ€ÐµÑ Ñлектронной почты не ÑущеÑтвует invalid_otp_token: Введен неверный код двухфакторной аутентификации invalid_sign_in_token: Ðеверный код безопаÑноÑти otp_lost_help_html: ЕÑли Ð’Ñ‹ потерÑли доÑтуп к обоим, ÑвÑжитеÑÑŒ Ñ %{email} @@ -1373,3 +1448,20 @@ ru: verification: explanation_html: 'Владение ÑÑылками в профиле <strong>можно подтвердить</strong>. Ð”Ð»Ñ Ñтого на указанном Ñайте должна ÑодержатьÑÑ ÑÑылка на ваш профиль Mastodon, а у Ñамой ÑÑылки <strong>должен</strong> быть атрибут <code>rel="me"</code>. Что внутри ÑÑылки — Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½Ðµ имеет. Вот вам пример ÑÑылки:' verification: Подтверждение + webauthn_credentials: + add: Добавить новый ключ безопаÑноÑти + create: + error: Возникла проблема Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ ключа безопаÑноÑти. ПожалуйÑта, попробуйте еще раз. + success: Ваш ключ безопаÑноÑти был уÑпешно добавлен. + delete: Удалить + delete_confirmation: Ð’Ñ‹ дейÑтвительно хотите удалить Ñтот ключ безопаÑноÑти? + description_html: ЕÑли вы включите <strong>аутентификацию по Ñекретным ключам</strong>, вход потребует иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ из ваших ключей. + destroy: + error: Произошла ошибка при удалении ключа безопаÑноÑти. ПожалуйÑта, попробуйте еще раз. + success: Ваш ключ безопаÑноÑти был уÑпешно удален. + invalid_credential: Ðеверный ключ безопаÑноÑти + nickname_hint: Введите Ð¸Ð¼Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ нового ключа безопаÑноÑти + not_enabled: Ð’Ñ‹ еще не включили WebAuthn + not_supported: Ðтот браузер не поддерживает ключи безопаÑноÑти + otp_required: Чтобы иÑпользовать ключи безопаÑноÑти, Ñначала включите двухфакторную аутентификацию. + registered_on: ЗарегиÑтрирован %{date} diff --git a/config/locales/sa.yml b/config/locales/sa.yml new file mode 100644 index 0000000000000000000000000000000000000000..229e4568c5e2cdbaa023092cce71e8a104ffa001 --- /dev/null +++ b/config/locales/sa.yml @@ -0,0 +1,12 @@ +--- +sa: + errors: + '400': The request you submitted was invalid or malformed. + '403': You don't have permission to view this page. + '404': The page you are looking for isn't here. + '406': This page is not available in the requested format. + '410': The page you were looking for doesn't exist here anymore. + '422': + '429': Too many requests + '500': + '503': The page could not be served due to a temporary server failure. diff --git a/config/locales/sc.yml b/config/locales/sc.yml index d1b8b43b4408763bfe2cdf41a80cb8bb62dc546f..626c7671c0ca7b85c2368c3ac25ae7a81e7e004a 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -1,20 +1,1420 @@ --- sc: + about: + about_hashtag_html: Custos sunt tuts pùblicos etichetados cun <strong>#%{hashtag}</strong>. Bi podes intrare in cuntatu si tenes unu contu in cale si siat logu de su fediversu. + about_mastodon_html: 'Sa rete sotziale de su benidore: sena publitzidade, sena vigilà ntzia corporativa, disignu èticu e detzentralizatzione! Sias mere de is datos tuos cun Mastodon!' + about_this: Informatziones + active_count_after: ativu + active_footnote: Utentes Ativos Mensiles (UAM) + administered_by: 'Amministradu dae:' + api: "*API" + apps: Aplicatziones mòbiles + apps_platforms: Imprea Mastodon dae iOS, Android e à teras prataformas + browse_directory: Nà viga su diretòriu de profilos e filtra segundu interessos + browse_local_posts: Nà viga unu flussu in direta de messà gios pùblicos de custu serbidore + browse_public_posts: Nà viga unu flussu in direta de messà gios pùblicos in Mastodon + contact: Cuntatu + contact_missing: No impostadu + contact_unavailable: No a disponimentu + discover_users: Iscoberi utentes + documentation: Documentatzione + federation_hint_html: Cun unu contu in %{instance} as a pòdere sighire persones in cale si siat serbidore de Mastodon o de su fediversu. + get_apps: Proa un'aplicatzione mòbile + hosted_on: Mastodon acasagiadu in %{domain} + instance_actor_flash: 'Custu contu est un''atore virtuale impreadu pro rapresentare su serbidore matessi, no est un''utente individuale. Benit impreadu pro punnas de federatzione e non lu dias dèpere blocare si non cheres blocare su domìniu intreu, e in cussu casu dias dèpere impreare unu blocu de domìniu. + +' + learn_more: Àteras informatziones + privacy_policy: Polìtica de riservadesa + see_whats_happening: Cà stia su chi est acontessende + server_stats: 'Istatìsticas de su serbidore:' + source_code: Còdighe mitza + status_count_after: + one: istadu + other: istados + status_count_before: Autores de + tagline: Sighi is amigos tuos e iscoberi·nde de noos + terms: Cunditziones de su servìtziu + unavailable_content: Serbidores moderados + unavailable_content_description: + domain: Serbidore + reason: Resone + rejecting_media: 'Is documentos multimediales de custos serbidores no at a èssere protzessadu o sarvadu e peruna miniadura at a èssere ammustradas, ca tenent bisòngiu de un''incarcu manuale in su documentu originale:' + rejecting_media_title: Mèdios filtrados + silenced: 'Is messà gios dae custos serbidores ant a èssere cuados in is lìnias de tempus e is arresonadas pùblicas, e no at a èssere generada peruna notìfica dae is interatziones de is utentes, francu chi nde sias sighende:' + silenced_title: Serbidores a sa muda + suspended: 'Perunu datu de custos serbidores at a èssere protzessadu, immagasinadu o cuncambiadu; est impossìbile duncas cale si siat interatzione o comunicatzione cun is utentes de custos serbidores:' + suspended_title: Serbidores suspèndidos + unavailable_content_html: Mastodon ti permitit de bìdere su cuntenutu de utentes de cale si siat à teru serbidore de su fediversu. Custas sunt etzetziones chi fatas in custu serbidore particulare. + user_count_after: + one: utente + other: utentes + user_count_before: Allogiadu dae + what_is_mastodon: Ite est Mastodon? + accounts: + choices_html: 'Sèberos de %{name}:' + endorsements_hint: Podes cussigiare gente chi sighis dae s'interfache web, e at a aparèssere inoghe. + featured_tags_hint: Podes evidentziare etichetas ispetzìficas chi ant a èssere ammustradas inoghe. + follow: Sighi + followers: + one: Sighidura + other: Sighiduras + following: Sighende + joined: At aderidu su %{date} + last_active: ùrtima atividade + link_verified_on: Sa propiedade de custu ligà mene est istada controllada su %{date} + media: Elementos multimediales + moved_html: "%{name} est istadu trasferidu a %{new_profile_link}:" + network_hidden: Custa informatzione no a disponimentu + never_active: Mai + nothing_here: Nudda inoghe. + people_followed_by: Gente sighida dae %{name} + people_who_follow: Gente chi sighit a %{name} + pin_errors: + following: Depes sighire sa persone chi boles promòvere + posts: + one: Tut + other: Tuts + posts_tab_heading: Tuts + posts_with_replies: Tuts e rispostas + reserved_username: Custu nòmine de utente est giai impreadu + roles: + admin: Admin + bot: Bot + group: Grupu + moderator: Moderadore + unavailable: Su profilu no est a disponimentu + unfollow: Non sigas prus + admin: + account_actions: + action: Faghe un'atzione + title: Faghe un'atzione de moderatzione in %{acct} + account_moderation_notes: + create: Lassa una nota + created_msg: As creadu una nota de moderatzione. + delete: Cantzella + destroyed_msg: As cantzelladu una nota de moderatzione. + accounts: + add_email_domain_block: Bloca domìniu de posta eletrònica + approve: Aprova + approve_all: Aprova totus + approved_msg: Sa dimanda de registru de %{username} est istada aprovada + are_you_sure: Seguru? + avatar: Immà gine de profilu + by_domain: Domìniu + change_email: + changed_msg: As cambiadu s'indiritzu eletrònicu. + current_email: Indiritzu eletrònicu atuale + label: Muda s'indiritzu eletrònicu + new_email: Indiritzu de eletrònicu nou + submit: Muda s'indiritzu eletrònicu + title: Muda s'indiritzu eletrònicu de %{username} + confirm: Cunfirma + confirmed: Cunfirmadu + confirming: Cunfirmende + delete: Cantzella datos + deleted: Cantzelladu + demote: Degrada + destroyed_msg: Is datos de %{username} sunt a sa coa pro èssere cantzellados luego + disable: Disativa + disable_two_factor_authentication: Disativa 2FA + disabled: Disativadu + display_name: Nòmine visìbile + domain: Domìniu + edit: Modìfica + email: Posta eletrònica + email_status: Istadu de s'indiritzu eletrònicu + enable: Ativa + enabled: Ativadu + enabled_msg: Su contu de %{username} est istadu ativadu + followers: Sighiduras + follows: Sighende + header: Intestatzione + inbox_url: URL de intrada + invited_by: Invitu dae + ip: IP + joined: At aderidu + location: + all: Totus + local: Locale + remote: Remotu + title: Positzione + login_status: Istadu de atzessu + media_attachments: Allegados multimediales + memorialize: Cunverte in memoriam + memorialized: Memorializadu + memorialized_msg: As trasformadu %{username} in unu contu de ammentu + moderation: + active: Ativu + all: Totus + pending: De imbiare + silenced: A sa muda + suspended: Suspèndidu + title: Moderatzione + moderation_notes: Notas de moderatzione + most_recent_activity: Atividade prus reghente + most_recent_ip: IP prus reghente + no_account_selected: Perunu contu est istadu mudadu, dae chi non nd'as seletzionadu + no_limits_imposed: Sena lìmites + not_subscribed: Sena sutiscritzione + pending: De revisionare + perform_full_suspension: Suspèndidu + promote: Promove + protocol: Protocollu + public: Pùblicu + push_subscription_expires: Sa sutiscritzione PuSH iscadit + redownload: Atualiza su profilu + redownloaded_msg: Su profilu de %{username} est istadu agiornadu dae s'orìgine + reject: Refuda + reject_all: Refuda totu + rejected_msg: Sa dimanda de registru de %{username} est istada refudada + remove_avatar: Boga immà gine de profilu + remove_header: Boga s'intestatzione + removed_avatar_msg: S'immà gine de d'à vatar de %{username} est istada bogada + removed_header_msg: S'immà gine de intestatzione de %{username} est istada bogada + resend_confirmation: + already_confirmed: Custa persone est giai cunfirmada + send: Torra a imbiare messà giu eletrònicu de cunfirmatzione + success: Messà giu eletrònicu de cunfirmatzione imbiadu. + reset: Reseta + reset_password: Reseta sa crae + resubscribe: Torra a sutascrìere + role: Permissos + roles: + admin: Admin + moderator: Mod + staff: Personale + user: Utente + search: Chirca + search_same_email_domain: Àteras persones cun su pròpiu domìniu de posta + search_same_ip: Àteras persones cun sa pròpiu IP + sensitive: Sensìbile + sensitized: marcadu comente a sensìbile + shared_inbox_url: URL de intrada cumpartzida + show: + created_reports: Informes creados + targeted_reports: Informes de à tere + silence: Lìmita + silenced: Limitadas + statuses: Tuts + subscribe: Sutascrie·ti + suspended: Suspèndidu + suspension_irreversible: Is datos de custu contu sunt istados cantzellados in manera irreversìbile. Podes bogare sa suspensione a su contu pro chi si potzat impreare, ma no at a recuperare datu perunu de is chi teniat in antis. + suspension_reversible_hint_html: Su contu est istadu suspèndidu, e is datos ant a èssere cantzelladu de su totu su %{date}. Finas a tando, su contu si podet ripristinare sena efetu malu perunu. Si boles cantzellare totu is datos de su contu immediatamente ddu podes fà ghere inoghe in bassu. + time_in_queue: Isetende in coa %{time} + title: Contos + unconfirmed_email: Posta eletrònica sena cunfirmare + undo_sensitized: Boga sa marcadura comente "sensìbile" + undo_silenced: Non pòngias a sa muda + undo_suspension: Iscontza sa suspensione + unsilenced_msg: As bogadu is lìmites a su contu de %{username} + unsubscribe: Annulla sa sutiscritzione + unsuspended_msg: As bogadu sa suspensione a su contu de %{username} + username: Nòmine utente + view_domain: Cà stia unu resumu pro su domìniu + warn: Avisu + web: Web + whitelisted: Federatzione permìtida + action_logs: + action_types: + assigned_to_self_report: Assigna s'informe + change_email_user: Muda s'indiritzu eletrònicu pro s'utente + confirm_user: Cunfirma s'utente + create_account_warning: Crea un'avisu + create_announcement: Crea un'annùntziu + create_custom_emoji: Crea un'emoji personalizadu + create_domain_allow: Crea unu domìniu permìtidu + create_domain_block: Crea unu blocu de domìniu + create_email_domain_block: Crea unu blocu de domìniu de indiritzu de posta + create_ip_block: Crea una règula IP + demote_user: Degrada s'utente + destroy_announcement: Cantzella s'annùntziu + destroy_custom_emoji: Cantzella s'emoji personalizadu + destroy_domain_allow: Cantzella su domìniu permìtidu + destroy_domain_block: Cantzella su blocu de domìniu + destroy_email_domain_block: Cantzella su blocu de domìniu de s'indiritzu de posta + destroy_ip_block: Cantzella sa règula IP + destroy_status: Cantzella s'istadu + disable_2fa_user: Disativa 2FA + disable_custom_emoji: Disativa s'emoji personalizadu + disable_user: Disativa utente + enable_custom_emoji: Ativa s'emoji personalizadu + enable_user: Ativa utente + memorialize_account: Regorda su contu + promote_user: Promove utente + remove_avatar_user: Cantzella immà gine de profilu + reopen_report: Torra a abèrrere s'informe + reset_password_user: Reseta sa crae + resolve_report: Isorve s'informe + sensitive_account: Marca sos cuntenutos multimediales in su contu tuo comente sensìbile + silence_account: Pone custu contu a sa muda + suspend_account: Suspende custu contu + unassigned_report: Boga s'assignatzione de custu informe + unsensitive_account: Boga sa marcadura "sensìbiles" a is elementos multimediales in su contu tuo + unsilence_account: Boga custu contu de is contos a sa muda + unsuspend_account: Boga custu contu de is contos suspèndidos + update_announcement: Atualiza s'annùntziu + update_custom_emoji: Atualiza s'emoji personalizadu + update_status: Atualiza s'istadu + actions: + assigned_to_self_report: "%{name} s'est auto-assignadu s'informe %{target}" + change_email_user: "%{name} at mudadu s'indiritzu de posta eletrònica de s'utente %{target}" + confirm_user: "%{name} at cunfirmadu s'indiritzu de posta eletrònica de s'utente %{target}" + create_account_warning: "%{name} at imbiadu un'avisu a %{target}" + create_announcement: "%{name} at creadu un'annùntziu nou %{target}" + create_custom_emoji: "%{name} at carrigadu un'emoji nou%{target}" + create_domain_allow: "%{name} at permìtidu sa federatzione cun su domìniu %{target}" + create_domain_block: "%{name} at blocadu su domìniu %{target}" + create_email_domain_block: "%{name} at blocadu su domìniu de posta eletrònica %{target}" + create_ip_block: "%{name} at creadu una règula pro s'IP %{target}" + demote_user: "%{name} at degradadu s'utente %{target}" + destroy_announcement: "%{name} at cantzelladu s'annùntziu %{target}" + destroy_custom_emoji: "%{name} at cantzelladu s'emoji %{target}" + destroy_domain_allow: "%{name} no at permìtidu sa federatzione cun su domìniu %{target}" + destroy_domain_block: "%{name} at isblocadu su domìniu %{target}" + destroy_email_domain_block: "%{name} at isblocadu su domìniu de posta eletrònica %{target}" + destroy_ip_block: "%{name} at cantzelladu sa règula pro s'IP %{target}" + destroy_status: "%{name} at eliminadu s'istadu de %{target}" + disable_2fa_user: "%{name} at disativadu su rechisitu de duos fatores pro s'utente %{target}" + disable_custom_emoji: "%{name} at disativadu s'emoji %{target}" + disable_user: "%{name} at disativadu s'atzessu pro s'utente %{target}" + enable_custom_emoji: "%{name} at ativadu s'emoji %{target}" + enable_user: "%{name} at ativadu s'atzessu pro s'utente %{target}" + memorialize_account: "%{name} at cunvertidu su contu %{target} in una pà gina in memoriam" + promote_user: "%{name} at promòvidu s'utente %{target}" + remove_avatar_user: "%{name} at cantzelladu s'immà gine de profilu de %{target}" + reopen_report: "%{name} at torradu a abèrrere s'informe %{target}" + reset_password_user: "%{name} at restadu sa crae de s'utente %{target}" + resolve_report: "%{name} at isòrvidu s'informe %{target}" + sensitive_account: "%{name} at marcadu s'elementu multimediale de %{target} comente sensìbile" + silence_account: "%{name} at postu su contu de %{target} a sa muda" + suspend_account: "%{name} at suspèndidu su contu de %{target}" + unassigned_report: "%{name} at bogadu s'assignatzione de s'informe %{target}" + unsensitive_account: '%{name} at bogadu sa marcadura "sensìbile" a s''elementu multimediale de %{target}' + unsilence_account: "%{name} at postu su contu de %{target} a sa muda" + unsuspend_account: "%{name} at bogadu sa suspensione de su contu de %{target}" + update_announcement: "%{name} at atualizadu s'annùntziu %{target}" + update_custom_emoji: "%{name} at atualizadu s'emoji %{target}" + update_status: "%{name} at atualizadu s'istadu de %{target}" + deleted_status: "(istadu cantzelladu)" + empty: Perunu registru agatadu. + filter_by_action: Filtra pro atzione + filter_by_user: Filtra pro utente + title: Registru de controllu + announcements: + destroyed_msg: As cantzelladu s'annùntziu. + edit: + title: Modìfica s'annùntziu + empty: Perunu annùntziu agatadu. + live: In direta + new: + create: Crea un'annùntziu + title: Annùntziu nou + published_msg: As publicadu s'annùntziu. + scheduled_for: Programmadu pro %{time} + scheduled_msg: As programmadu s'annùntziu pro èssere publicadu! + title: Annùntzios + unpublished_msg: As ritiradu s'annùntziu! + updated_msg: As atualizadu s'annùntziu. + custom_emojis: + assign_category: Assigna a una categoria + by_domain: Domìniu + copied_msg: As creadu sa còpia locale de s'emoji + copy: Còpia + copy_failed_msg: Impossìbile fà ghere una còpia locale de custu emoji + create_new_category: Crea una categoria noa + created_msg: As creadu s'emoji. + delete: Cantzella + destroyed_msg: As cantzelladu s'emoji. + disable: Disativa + disabled: Disativu + disabled_msg: As disativadu s'emoji + emoji: Emoji + enable: Ativa + enabled: Ativadu + enabled_msg: As ativadu s'emoji + image_hint: PNG de finas a 50 KB + list: Lista + listed: Listadu + new: + title: Agiunghe emoji personalizadu nou + not_permitted: Non tenes su permissu de fà ghere custa atzione + overwrite: Subraiscrie + shortcode: Incurtzadura + shortcode_hint: Mìnimu 2 carà teres, isceti carà teres alfanumèricos e tratigheddos bà scios + title: Emojis personalizados + uncategorized: Sena categoria + unlist: Esclude de sa lista + unlisted: Esclùidu de sa lista + update_failed_msg: Impossìbile atualizare custu emoji + updated_msg: Emoji atualizadu + upload: Cà rriga + dashboard: + authorized_fetch_mode: Modalidade segura + backlog: tareas arretradas + config: Cunfiguratzione + feature_deletions: Eliminatzione de contos + feature_invites: Ligà menes de invitu + feature_profile_directory: Diretòriu de profilos + feature_registrations: Registradas + feature_relay: Ripetidore de federatzione + feature_spam_check: Anti-à liga + feature_timeline_preview: Pre-visualizatzione de sa lìnia de tempus + features: Caraterìsticas + hidden_service: Federatzione cun servìtzios cuados + open_reports: informes abertos + pending_tags: etichetas de revisionare + pending_users: persones de revisionare + recent_users: Persones reghentes + search: Chirca de testu cumpletu + single_user_mode: Modalidade de utente ùnicu + software: Programmas + space: Impreu de ispà tziu + title: Pannellu + total_users: persones in totale + trends: Tendèntzias + week_interactions: interatziones de custa chida + week_users_active: persones ativas custa chida + week_users_new: persones noas de custa chida + whitelist_mode: Modalidade de federatzione limitada + domain_allows: + add_new: Permite sa federatzione cun domìniu + created_msg: Sa federatzione cun su domìniu est istada permìtida + destroyed_msg: Sa federatzione cun su domìniu no est istada permìtida + undo: Non permitas sa federatzione cun su domìniu + domain_blocks: + add_new: Agiunghe blocu de domìniu nou + created_msg: Protzessende su blocu de domìniu + destroyed_msg: Su blocu de domìniu est istadu iscontzadu + domain: Domìniu + edit: Modìfica su blocu de su domìniu + existing_domain_block_html: As giai impostu lìmites prus astrintos a %{name}, ddu dias dèpere <a href="%{unblock_url}">isblocare</a> prima. + new: + create: Crea unu blocu + hint: Su blocu de domìniu no at a impedire sa creatzione de contos noos in sa base de datos, ma ant a èssere aplicados in manera retroativa mètodos de moderatzione ispetzìficos subra custos contos. + severity: + desc_html: "<strong>A sa muda</strong> at a pònnere is messà gios de custos contos comente invisìbiles a sa gente chi no ddi siat sighende. <strong>Sa suspensione</strong> at a cantzellare totu su cuntenutu de su contu, elementos multimediales e datos de profilu. Imprea <strong>Perunu</strong> si boles isceti refudare is archìvios multimediales." + noop: Perunu + silence: A sa muda + suspend: Suspèndidu + title: Blocu de domìniu nou + private_comment: Cummentu privadu + private_comment_hint: Lassa unu cummentu a subra de custa limitatzione de domìniu pro impreu internu de s'iscuadra de moderatzione. + public_comment: Cummentu pùblicu + public_comment_hint: Lassa unu cummentu pro su pùblicu generale a subra de custa limitatzione de su domìniu, si sa publicatzione de sa lista de limitatziones de domìniu est abilitada. + reject_media: Refuda documentos multimediales + reject_media_hint: Cantzellat documentos multimediales sarvados in locale e refudat iscarrigamentos in su benidore. Non rilevante pro is suspensiones + reject_reports: Refuda informes + reject_reports_hint: Iscarta informes chi benint de custu domìniu. Non rilevante pro is suspensiones + rejecting_media: refudende documentos multimediales + rejecting_reports: refudende informes + severity: + silence: a sa muda + suspend: suspèndidu + show: + affected_accounts: + one: Unu contu de sa base de datos implicadu + other: "%{count} contos de sa base de datos implicados" + retroactive: + silence: Boga de is contos a sa muda is contos de custu domìniu implicados + suspend: Boga sa suspensione de is contos de custu domìniu implicados + title: Iscontza su blocu de domìniu de %{domain} + undo: Iscontza + undo: Iscontza su blocu de domìniu + view: Bide su blocu de domìniu + email_domain_blocks: + add_new: Agiunghe noa + created_msg: Domìniu de posta eletrònica blocadu + delete: Cantzella + destroyed_msg: Domìniu de posta eletrònica isblocadu + domain: Domìniu + empty: Perunu domìniu de posta eletrònica blocadu. + from_html: dae %{domain} + new: + create: Agiunghe unu domìniu + title: Bloca su domìniu de posta eletrònica nou + title: Domìnios de posta eletrònica blocados + instances: + by_domain: Domìniu + delivery_available: Sa cunsigna est a disponimentu + known_accounts: + one: "%{count} contu connòschidu" + other: "%{count} contos connòschidos" + moderation: + all: Totus + limited: Limitadas + title: Moderatzione + private_comment: Cummentu privadu + public_comment: Cummentu pùblicu + title: Federatzione + total_blocked_by_us: Blocados dae nois + total_followed_by_them: Sighidos dae à tere + total_followed_by_us: Sighidos dae nois + total_reported: Informes a subra de à tere + total_storage: Allegados multimediales + invites: + deactivate_all: Disativa totu + filter: + all: Totus + available: A disponimentu + expired: Iscadidu + title: Filtru + title: Invitos + ip_blocks: + add_new: Crea una règula + created_msg: As agiuntu una règula IP noa + delete: Cantzella + expires_in: + '1209600': 2 chidas + '15778476': 6 meses + '2629746': 1 mese + '31556952': 1 annu + '86400': 1 die + '94670856': 3 annos + new: + title: Crea una règula IP noa + no_ip_block_selected: Peruna règula IP est istada mudada dae chi non nd'as seletzionadu + title: Règulas IP + pending_accounts: + title: Contos in ispera (%{count}) + relationships: + title: relatziones de %{acct} + relays: + add_new: Agiunghe unu ripetidore nou + delete: Cantzella + description_html: Unu <strong>ripetidore de federatzione</strong> est unu serbidore intermedià riu chi cuncà mbiat volùmenes mannos de tuts pùblicos intre serbidores chi si connetent e bi pùblicant. <strong>Podet agiudare a serbidores minores e medianos a iscobèrrere cuntenutu de su fediversu</strong>, in manera chi is utentes locales non tèngiant bisòngiu de sighire a manu à tera gente de serbidores remotos. + disable: Disativa + disabled: Disativu + enable: Ativa + enable_hint: Si abilitadu, su serbidore tuo at a èssere sutascritu a totu is tuts pùblicos de custu ripetidore e bi at a cumintzare a imbiare totu is tuts pùblicos de custu serbidore. + enabled: Ativadu + inbox_url: URL de su ripetidore + pending: Isetende s'aprovatzione de su ripetidore + save_and_enable: Sarva e ativa + setup: Cunfigura una connessione cun unu ripetidore + signatures_not_enabled: Is ripetidores no ant a funtzionare comente si tocat si sa modalidade segura o sa modalidade a federatzione limitada sunt abilitadas + status: Istadu + title: Ripetidores + report_notes: + created_msg: As creadu sa nota de s'informe + destroyed_msg: As cantzelladu sa nota de s'informe + reports: + account: + notes: + one: "%{count} nota" + other: "%{count} notas" + reports: + one: "%{count} informe" + other: "%{count} informes" + action_taken_by: Mesuras adotadas dae + are_you_sure: Seguru? + assign_to_self: Assigna a mie + assigned: Moderatzione assignada + by_target_domain: Domìniu de su contu signaladu + comment: + none: Perunu + created_at: Signaladu + mark_as_resolved: Marca comente a isòrvidu + mark_as_unresolved: Marcare comente a non isòrvidu + notes: + create: Agiunghe una nota + create_and_resolve: Isorve cun una nota + create_and_unresolve: Torra a abèrrere cun una nota + delete: Cantzella + placeholder: Descrie is atziones chi as pigadu o cale si siat à tera atualizatzione de importu... + reopen: Torra a abèrrere s'informe + report: 'Informe #%{id}' + reported_account: Contu signaladu + reported_by: Signaladu dae + resolved: Isòrvidu + resolved_msg: Informe isòrvidu. + status: Istadu + title: Informes + unassign: Boga s'assignatzione + unresolved: No isòrvidu + updated_at: Atualizadu + settings: + activity_api_enabled: + desc_html: Nùmeru de tuts publicados in locale, utentes ativos e registros noos in perìodos chidajolos + title: Pùblica istatìsticas agregadas subra s'atividade de s'utente + bootstrap_timeline_accounts: + desc_html: Imprea vìrgulas intre is nòmines de utente. Isceti is contos locales e isblocados ant a funtzionare. Su valore predefinidu cando est bòidu est totu is admins locales. + title: Sighidura predefinida pro persones noas + contact_information: + email: Indiritzu eletrònicu de impresa + username: Nòmine de utente de su cuntatu + custom_css: + desc_html: Modìfica s'aspetu cun CSS carrigadu in cada pà gina + title: CSS personalizadu + default_noindex: + desc_html: ÃŒmplicat a totu is utentes chi no apant modificadu custa cunfiguratzione + title: Esclude in manera predefinida is utentes dae s'inditzamentu de is motores de chirca + domain_blocks: + all: Pro totus + disabled: Pro nemos + title: Ammustra blocos de domìniu + users: Pro utentes locales in lìnia + domain_blocks_rationale: + title: Ammustra sa resone + enable_bootstrap_timeline_accounts: + title: Ativa s sighiduras predefinidas pro is persones noas + hero: + desc_html: Ammustradu in sa pà gina printzipale. Cussigiadu a su mancu 600x100px. Si no est cunfiguradu, at a èssere ammustradu cussu de su serbidore + title: Immà gine de eroe + mascot: + desc_html: Ammustrada in và rias pà ginas. Cussigiadu a su mancu 293x205px. Si no est cunfiguradu, torra a su personà giu predefinidu + title: Immà gine de su personà giu + peers_api_enabled: + desc_html: Is nòmines de domìniu chi custu serbidore at agatadu in su fediversu + title: Pùblica sa lista de serbidores iscobertos + preview_sensitive_media: + desc_html: Is antiprimas de ligòngios de à teros sitos web ant a ammustrare una miniadura mancari is mèdios de comunicatzione siant marcados comente a sensìbiles + title: Ammustra mèdios sensìbiles in sas previsualizatziones de OpenGraph + profile_directory: + desc_html: Permite a is persone de èssere iscobertas + title: Ativa diretòriu de profilos + registrations: + closed_message: + desc_html: Ammustradu in sa prima pà gina cando is registratziones sunt serradas. Podes impreare etichetas HTML + title: Messà giu de registru serradu + deletion: + desc_html: Permite a chie si siat de cantzellare su contu suo + title: Aberi s'eliminatzione de su contu + min_invite_role: + disabled: Perunu + title: Permite invitos de + registrations_mode: + modes: + approved: Aprovatzione rechesta pro si registrare + none: Nemos si podet registrare + open: Chie si siat si podet registrare + title: Modu de registratzione + show_known_fediverse_at_about_page: + desc_html: Cando ativu, ammustrat in sa previsualizatzione is tuts de totu is istà ntzias connòschidas. Si nono, ammustrat isceti is cuntenutos locales + title: Include su cuntenutu federadu in sa pà gina no autenticada de sa lìnia de tempus pùblica + show_staff_badge: + desc_html: Ammustra un'insigna de personale in sa pà gina de utente + title: Ammustra insigna de personale + site_description: + desc_html: Parà grafu de introdutzione a s'API. Descrie ite rendet ispatziale custu serbidore de Mastodon e cale si siat à tera cosa de importu. Podes impreare etichetas HTML, mescamente <code><a></code> e <code><em></code>. + title: Descritzione de su serbidore + site_description_extended: + desc_html: Unu logu adatu pro publicare su còdighe de cumportamentu, règulas, diretivas e à teras caraterìsticas ispetzìficas de su serbidore tuo. Podes impreare etichetas HTML + title: Descritzione estèndida de su logu + site_short_description: + desc_html: Ammustradu in sa barra laterale e in is meta-etichetas. Descrie ite est Mastodon e pro ite custu serbidore est ispetziale in unu parà grafu. + title: Descritzione curtza de su serbidore + site_terms: + desc_html: Podes iscriere sa tua normativa de riservadesa pròpia, cunditziones de servìtziu e à teras normas legales. Podes impreare etichetas HTML + title: Termes de su servìtziu personalizados + site_title: Nòmine de su serbidore + spam_check_enabled: + desc_html: Mastodon podet signalare in automà ticu contos chi imbiant messà gios non rechestos in manera repetitiva. Bi podent èssere falsos positivos. + title: Automatzione anti-spam + thumbnail: + desc_html: Impreadu pro otènnere pre-visualizatziones pro mèdiu de OpenGraph e API. Cussigiadu 1200x630px + title: Miniadura de su serbidore + timeline_preview: + desc_html: Ammustra su ligà mene a sa lìnia de tempus pùblica in sa pà gina initziale e permite s'atzessu pro mèdiu de s'API a sa lìnia de tempus pùblica sena autenticatzione + title: Permite s'atzessu no autenticadu a sa lìnia de tempus pùblica + title: Cunfiguratzione de su logu + trendable_by_default: + desc_html: Tocat a is etichetas chi non siant istadas refudadas prima + title: Permite chi is etichetas divenant tendèntzia sena revisione pretzedente + trends: + desc_html: Ammustra in pùblicu is etichetas chi siant istadas revisionadas in passadu e chi oe siant in tendèntzia + title: Etichetas de tendèntzia + site_uploads: + delete: Cantzella s'archìviu carrigadu + destroyed_msg: Cà rriga de su situ cantzellada. + statuses: + back_to_account: Torra a sa pà gina de su contu + batch: + delete: Cantzella + nsfw_off: Signala comente a non sensìbile + nsfw_on: Signala comente a sensìbile + deleted: Cantzelladu + failed_to_execute: Faddina in s'esecutzione + media: + title: Elementos multimediales + no_media: Perunu elementu multimediale + no_status_selected: Perunu istadu est istadu mudadu dae chi non nd'as seletzionadu + title: Istados de su contu + with_media: Cun elementos multimediales + tags: + accounts_today: Impreos ùnicos atuales + accounts_week: Impreos ùnicos de custa chida + breakdown: Detà llios de s'impreu atuale pro orìgine + context: Cuntestu + directory: In su diretòriu + in_directory: "%{count} in su diretòriu" + last_active: Ùrtima atividade + most_popular: Prus populares + most_recent: Prus reghentes + name: Eticheta + review: Revisiona s'istadu + reviewed: Revisionadas + title: Etichetas + trending_right_now: In tendèntzia immoe + unique_uses_today: "%{count} publicatziones de oe" + unreviewed: Sena revisionare + updated_msg: Cunfiguratzione de etichetas atualizada + title: Amministratzione + warning_presets: + add_new: Agiunghe noa + delete: Cantzella + edit_preset: Modìfica s'avisu predefinidu + title: Gesti is cunfiguratziones predefinidas de is avisos + admin_mailer: + new_pending_account: + body: Is detà llios de su contu nou sunt a suta. Podes aprovare o refudare custa rechesta. + subject: Contu nou de revisionare in %{instance} (%{username}) + new_report: + body: "%{reporter} at signaladu %{target}" + body_remote: Calicunu de su domìniu %{domain} at signaladu %{target} + subject: Informe nou pro %{instance} (#%{id}) + new_trending_tag: + body: 'S''eticheta #%{name} est in tendèntzia oe, ma non est istada revisionada in passadu. No at a èssere ammustrada in pùblicu francu chi ddu permitas; si sarvas formulà riu sena ddu modificare no ddu as a bìdere mai prus.' + subject: Eticheta noa de revisionare in %{instance} (#%{name}) + aliases: + add_new: Crea unu nomìngiu + created_msg: Nomìngiu creadu. Immoe podes cumintzare a tramudare dae su contu betzu. + deleted_msg: Nomìngiu bogadu. Sa trà muda dae cussu contu a custu no at a èssere prus possìbile. + empty: No tenes perunu nomìngiu. + hint_html: Si boles mudare dae un'à teru contu a custu, inoghe as a pòdere creare unu nomìngiu, chi est rechestu in antis de sighire cun sa trà muda de is persones chi ti sighint dae su contu betzu a custu. Custa atzione est <strong>innòcua e reversìbile</strong>. <strong>Trà muda de su contu betzu cumintzada</strong>. + remove: Disconnete su nomìngiu + appearance: + advanced_web_interface: Interfache web avantzada + advanced_web_interface_hint: 'Si impreare totu sa largà ria de s''ischermu, s''interfache web avantzada ti permitit de cunfigurare diversas colunnas pro bìdere meda prus informatzione in contemporà nea: printzipale, notìficas, lìnia de tempus federada e cale si siat nùmeru de listas e etichetas.' + animations_and_accessibility: Animatziones e atzessibilidade + confirmation_dialogs: Dià logos de cunfirmatzione + discovery: Iscoberta + localization: + body: Mastodon est bortadu in manera voluntà ria. + guide_link: https://crowdin.com/project/mastodon + guide_link_text: Chie si siat podet contribuire. + sensitive_content: Cuntenutu sensìbile + toot_layout: Dispositzione de is tuts + application_mailer: + notification_preferences: Muda is preferèntzias de posta + salutation: "%{name}," + settings: 'Muda is preferèntzias de posta: %{link}' + view: 'Visualizatzione:' + view_profile: Visualiza profilu + view_status: Ammustra s'istadu + applications: + created: Aplicatzione creada + destroyed: Aplicatzione cantzellada + invalid_url: S'URL frunidu no est curretu + regenerate_token: Torra a generare s'identificadore de atzessu + token_regenerated: Identificadore de atzessu generadu + warning: Dae cara a custos datos. Non ddos cumpartzas mai cun nemos! + your_token: S'identificadore tuo de atzessu + auth: + apply_for_account: Pedi un'invitu + change_password: Crae + checkbox_agreement_html: So de acòrdiu cun is <a href="%{rules_path}" target="_blank">règulas de su serbidore</a> e is <a href="%{terms_path}" target="_blank">cunditziones de su servìtziu</a> + checkbox_agreement_without_rules_html: So de acòrdiu cun is <a href="%{terms_path}" target="_blank">cunditziones de su servìtziu</a> + delete_account: Cantzella su contu + delete_account_html: Si boles cantzellare su contu, ddu podes <a href="%{path}">fà ghere inoghe</a>. T'amus a dimandare una cunfirmatzione. + description: + prefix_invited_by_user: "@%{name} t'at invitadu a custu serbidore de Mastodon!" + prefix_sign_up: Registra·ti oe a Mastodon! + suffix: Cun unu contu as a pòdere sighire gente, publicare e cuncambiare messà gios cun persones de cale si siat serbidore de Mastodon e à teru! + didnt_get_confirmation: No as retzidu su messà giu de cunfirmatzione? + dont_have_your_security_key: Non tenes sa crae de seguresa tua? + forgot_password: Ti ses iscarèssidu de sa crae? + invalid_reset_password_token: Su còdighe de autorizatzione pro resetare sa crae no est và lidu o est iscadidu. Dimanda·nde un'à teru. + link_to_otp: Inserta unu còdighe a duas fases dae su telèfono tuo o unu còdighe de recùperu + link_to_webauth: Imprea su dispositivu tuo de crae de seguresa + login: Intra + logout: Essi + migrate_account: Moe a unu contu diferente + migrate_account_html: Si boles torrare a indiritzare custu contu a un'à teru, ddu as a pòdere <a href="%{path}">fà ghere inoghe</a>. + or_log_in_with: O intra cun + providers: + cas: CAS + saml: SAML + register: Registru + registration_closed: "%{instance} no atzetat à teras persones" + resend_confirmation: Torra a imbiare is istrutziones de cunfirmatzione + reset_password: Reseta sa crae + security: Seguresa + set_new_password: Cunfigura una crae noa + setup: + email_below_hint_html: Si s'indiritzu de posta eletrònica imbeniente no est curreta, dda podes mudare inoghe e as a retzire unu messà giu de cunfirmatzione nou. + email_settings_hint_html: Messà giu de cunfirmatzione imbiadu a %{email}. Si custu indiritzu de posta eletrònica no est curretu, ddu podes mudare dae is cunfiguratziones de su contu. + title: Cunfiguratzione + status: + account_status: Istadu de su contu + confirming: Isetende chi sa posta eletrònica siat cumpletada. + functional: Su contu tuo est operativu. + pending: Sa dimanda tua est in protzessu de revisione dae su personale nostru. Podet serbire unu pagu de tempus. As a retzire unu messà giu eletrònicu si sa dimanda est aprovada. + redirecting_to: Su contu tuo est inativu ca in die de oe est torrende a indiritzare a %{acct}. + too_fast: Mòdulu imbiadu tropu a lestru, torra a proare. + trouble_logging_in: Tenes problemas de atzessu? + use_security_key: Imprea una crae de seguresa + authorize_follow: + already_following: Ses giai sighende custu contu + already_requested: As giai imbiadu una dimanda de sighidura a custa persone + error: Faddina in sa chirca de su contu remotu + follow: Sighi + follow_request: 'As imbiadu una dimanda de sighidura a:' + following: 'Fatu! Immoe ses sighende:' + post_follow: + close: O, podes serrare custa ventana. + return: Ammustra su profilu de custa persone + web: Bae a su situ web + title: Sighi %{acct} + challenge: + confirm: Sighi + hint_html: "<strong>Cussìgiu:</strong> No t'amus a torrare a dimandare sa crae in s'ora imbeniente." + invalid_password: Sa crae no est và lida + prompt: Cunfirma sa crae pro sighire + crypto: + errors: + invalid_key: no est una crae Ed25519 o Curve25519 và lida + invalid_signature: no est una firma Ed25519 và lida + date: + formats: + default: "%d %b %Y" + with_month_name: "%d %B %Y" + datetime: + distance_in_words: + about_x_hours: "%{count} o" + about_x_months: "%{count} me" + about_x_years: "%{count} an" + almost_x_years: "%{count} an" + half_a_minute: Immoe etotu + less_than_x_minutes: "%{count} m" + less_than_x_seconds: Immoe etotu + over_x_years: "%{count} an" + x_days: "%{count} d" + x_minutes: "%{count} m" + x_months: "%{count} me" + x_seconds: "%{count} s" + deletes: + challenge_not_passed: S'informatzione insertada no est curreta + confirm_password: Inserta·nche sa crae atuale pro verificare s'identidade + confirm_username: Iscrie su nòmine de utente tuo cunfirmare su protzedimentu + proceed: Cantzella su contu + success_msg: Contu cantzelladu + warning: + before: 'In antis de sighire, leghe custu cun atentzione:' + caches: Su cuntenutu chi siat istadu sarvadu in sa memòria temporà nea de à teros serbidores podet sighire a esìstere + data_removal: Is publicatziones tuas e à teros datos ant a èssere cantzellados in manera permanente + email_change_html: Podes <a href="%{path}">mudare s'indiritzu tuo de posta eletrònica</a> sena cantzellare su contu + email_contact_html: Si no est ancora arribada, podes imbiare unu messà giu a <a href="mailto:%{email}">%{email}</a> e dimandare agiudu + email_reconfirmation_html: Si no ses retzende su messà giu de cunfirmatzione, ddu podes <a href="%{path}">torrare a dimandare</a> + irreversible: No as a pòdere ripristinare o torrare a ativare su contu tuo + more_details_html: Pro à teros detà llios, bide sa <a href="%{terms_path}">normativa de riservadesa</a>. + username_available: Su nòmine de utente tuo at a torrare a èssere a disponimentu + username_unavailable: Su nòmine de utente tuo no at a abarrare a disponimentu + directories: + directory: Diretòriu de profilos + explanation: Iscoberi gente segundu is interessos suos + explore_mastodon: Esplora %{title} + domain_validator: + invalid_domain: no est unu nòmine de domìniu và lidu errors: - '400': The request you submitted was invalid or malformed. - '403': You don't have permission to view this page. - '404': The page you are looking for isn't here. - '406': This page is not available in the requested format. - '410': The page you were looking for doesn't exist here anymore. - '422': - '429': Too many requests - '500': - '503': The page could not be served due to a temporary server failure. + '400': Sa dimanda chi as imbiadu non fiat và lida o non fiat curreta. + '403': Non tenes permissu pro bìdere custa pà gina. + '404': Sa pà gina chi ses chirchende no est inoghe. + '406': Custa pà gina no est a disponimentu in su formadu chi as pregontadu. + '410': Sa pà gina chi ses chirchende no esistet prus. + '422': + content: Faddina in sa verìfica de seguresa. Ses blochende is boboettos? + title: Faddina in sa verìfica de seguresa + '429': Tropu rechestas + '500': + content: Faddina dae s'ala nostra. + title: Custa pà gina no est curreta + '503': Faddina in sa trasmissione de sa pà gina pro more de una faddina temporà nea de su serbidore. + noscript_html: Pro impreare s'aplicatzione web de Mastodon, ativa JavaScript. In alternativa, proa una de is <a href="%{apps_path}">aplicatziones nativas</a> pro Mastodon in sa prataforma tua. + existing_username_validator: + not_found: impossìbile agatare utentes locales cun cussu nòmine + not_found_multiple: impossìbile agatare %{usernames} + exports: + archive_takeout: + date: Data + download: Iscà rriga s'archìviu + hint_html: Podes dimandare un'archìviu cun is <strong>tuts tuos e is mèdias chi as carrigadu</strong>. Is datos sunt in formadu ActivityPub, leghìbile dae is programmas cumpatìbiles. Podes pregontare un'archìviu cada 7 dies. + in_progress: Compilende s'archìviu tuo... + request: Pregonta s'archìviu tuo + size: Mannà ria + blocks: Ses blochende + bookmarks: Sinnalibros + csv: CSV + domain_blocks: Blocos de domìnios + lists: Listas + mutes: Ses ponende a sa muda + storage: Immagasinamentu + featured_tags: + add_new: Agiunghe noa + errors: + limit: As giai evidentziadu sa cantidade mà ssima de etichetas + hint_html: "<strong>Ite sunt is etichetas in evidèntzia?</strong> Sunt ammustradas in evidèntzia in su profilu pùblicu tuo e permitint a sa gente de navigare is messà gios pùblicos tuos in cussas etichetas ispetzìficas. Sunt un'aina perfeta pro tènnere unu registru de òperas creativas o progetos longos." + filters: + contexts: + account: Profilos + home: Pà gina printzipale e listas + notifications: Notìficas + public: Lìnias de tempos pùblicas + thread: Arresonadas + edit: + title: Modìfica filtru + errors: + invalid_context: Cuntestu mancante o non và lidu + invalid_irreversible: Su filtrà giu non reversìbile funtzionat isceti in is cuntestos printzipale o de notìficas + index: + delete: Cantzella + empty: Non tenes perunu filtru. + title: Filtros + new: + title: Agiunghe unu filtru nou + footer: + developers: Iscuadra de isvilupu + more: Àteru… + resources: Resursas + trending_now: Est tendèntzia immoe + generic: + all: Totus + changes_saved_msg: Modìficas sarvadas. + copy: Còpia + delete: Cantzella + no_batch_actions_available: Peruna atzione in blocu a disponimentu dae custa pà gina + order_by: Ã’rdina pro + save_changes: Sarva is modìficas + validation_errors: + one: Calicuna cosa ancora no est andende. Bide sa faddina in bà sciu + other: Calicuna cosa ancora no est andende. Bide is %{count} faddinas in bà sciu + html_validator: + invalid_markup: 'cuntenet etichetas HTML non và lidas: %{error}' + identity_proofs: + active: Ativu + authorize: Eja, autoriza + authorize_connection_prompt: Boles autorizare custa connessione critografada? + errors: + failed: Faddina in sa connessione critografada. Torra·bi a proare dae %{provider}. + keybase: + invalid_token: Is còdighes de autorizatzione de Keybase sunt hash de firmas e depent tènnere 66 carà teres esadetzimales + verification_failed: Keybase non reconnoschet custu còdighe de autorizatzione che a firma de s'utente de Keybase %{kb_username}. Torra·bi a proare dae Keybase. + wrong_user: Impossìbile creare una proa pro %{proving} cando as fatu s'atzessu che a %{current}. Intra che a %{proving} e torra·bi a proare. + explanation_html: Inoghe podes collegare critograficamente is à teras identidades tuas dae à teras prataformas, che a Keybase. Custu permitit a à teras persones de t'imbiare messà gios tzifrados in cussas prataformas e de tènnere sa seguresa chi sos cuntenutos chi lis mandas benit dae tene. + i_am_html: So %{username} in %{service}. + identity: Identidade + inactive: Inativu + publicize_checkbox: 'E imbiat custu tut:' + publicize_toot: 'Verificadu! So %{username} in %{service}: %{url}' + remove: Boga sa proa dae su contu + removed: Proa bogada dae su contu + status: Istadu de verìfica + view_proof: Bìdere sa proa + imports: + modes: + merge: Uni + merge_long: Mantene is registros chi esistint e agiunghe·nde à teros + overwrite: Subraiscrie + overwrite_long: Sostitui is registros atuales cun cussos noos + preface: Podes importare datos chi as esportadu dae unu à teru serbidore, che a sa lista de sa gente chi ses sighende o blochende. + success: Datos carrigados; ant a èssere protzessados luego + types: + blocking: Lista de blocados + bookmarks: Sinnalibros + domain_blocking: Lista domìnios blocados + following: Lista de sighiduras + muting: Lista gente a sa muda + upload: Cà rriga + in_memoriam_html: In memoriam. invites: + delete: Disativa + expired: Iscadidu expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day + '1800': 30 minutos + '21600': 6 oras + '3600': 1 ora + '43200': 12 oras + '604800': 1 chida + '86400': 1 die + expires_in_prompt: Mai + generate: Gènera ligà mene de invitu + invited_by: 'As retzidu unu messà giu de invitu dae:' + max_uses: + one: 1 impreu + other: "%{count} impreos" + max_uses_prompt: Sena lìmite + prompt: Gènera e cumpartzi ligà menes cun à teras persones pro dare atzessu a custu serbidore + table: + expires_at: Iscadit + uses: Impreos + title: Invita gente + lists: + errors: + limit: Cantidade mà ssima de listas cròmpida + media_attachments: + validations: + images_and_video: Non si podet allegare unu vìdeu in una publicatzione chi cuntenet giai immà gines + not_ready: Impossìbile allegare archìvios chi no siant istados protzessados in manera totale. Torra·bi a proare a pustis + too_many: Impossìbile allegare prus de 4 archìvios + migrations: + acct: Mòidu a + cancel: Annulla s'indiritzamentu + cancel_explanation: Si annullas s'indiritzamentu, su contu tuo at a èssere torradu a ativare, però is sighiduras chi apas tramudadu a cussu contu no ant a pòdere èssere recuperadas. + cancelled_msg: Indiritzamentu annulladu. + errors: + already_moved: est su pròpiu contu a su chi as giai tramudadu + missing_also_known_as: no est unu nomìngiu de custu countu + move_to_self: non podet èssere su contu atuale + not_found: no agatadu + on_cooldown: Ses in perìodu de pà usa intre una trà muda e s'à tera + followers_count: Gente chi ti sighiat in su momentu de sa trà muda + incoming_migrations: Tramudada dae unu contu diferente + incoming_migrations_html: Pro tramudare cuntenutos dae un'à teru contu a custu, prima depes <a href="%{path}">creare unu nomìngiu</a>. + moved_msg: Su contu tuo immoe est torrende a indiritzare a %{acct} e sa gente chi ti sighit at a èssere tramudada. + not_redirecting: Su contu tuo no est torrende a indiritzare a perunu à teru contu immoe. + on_cooldown: As tramudadu su contu tuo de reghente. Custa funtzionalidade at a torrare a èssere a disponimentu de immoe a %{count} dies. + past_migrations: Trà mudas pretzedentes + proceed_with_move: Trà muda sa gente chi ti sighit + redirected_msg: Su contu tuo immoe est torrende a indiritzare a %{acct}. + redirecting_to: Su contu tuo est torrende a indiritzare a %{acct}. + set_redirect: Cunfigura s'indiritzamentu + warning: + backreference_required: Su contu nou depet èssere prima cunfiguradu pro pòdere fà ghere riferimentu a custu + before: 'In antis de sighire, leghe custu cun atentzione:' + cooldown: A pustis de tramudare, ddoe at a èssere unu perìodu de pà usa in su chi no as a pòdere torrare a tramudare + disabled_account: A pustis, su contu atuale tuo no at a èssere prus operativu in manera cumpleta. Sende gasi, as a tènnere atzessu a s'esportatzione de datos e a sa re-ativatzione. + followers: Custa atzione at a tramudare totu sa gente chi ti sighit dae su contu atuale a su contu nou + only_redirect_html: In alternativa, podes isceti <a href="%{path}">cunfigurare un'indiritzamentu in su profilu tuo</a>. + other_data: Perunu à teru datu at a èssere tramudadu in automà ticu + redirect: Su profilu de su contu atuale tuo at a èssere atualizadu cun un'avisu de indiritzamentu e at a èssere esclùidu dae is chircas + moderation: + title: Moderatzione + move_handler: + carry_blocks_over_text: Custu utente s'est tramudadu dae %{acct}, chi as blocadu. + carry_mutes_over_text: Custu utente s'est tramudadu dae %{acct}, chi as impostadu a sa muda. + copy_account_note_text: 'Custu utente s''est tramudadu dae %{acct}, custas sunt sas notas antepostas tuas chi li pertocant:' + notification_mailer: + digest: + action: Ammustra totu is notìficas + body: Custu est unu resumu de su chi ti est sutzèdidu dae sa visita ùrtima tua su %{since} + mention: "%{name} t'at mentovadu in:" + new_followers_summary: + one: In prus, %{count} persone noa ti sighit dae cando fias assente. Incredìbile! + other: In prus, %{count} persones noas ti sighint dae cando fias assente. Incredìbile! + subject: + one: "1 notìfica noa dae s'ùrtima visita tua \U0001F418" + other: "%{count} notìficas noas dae s'ùrtima visita tua \U0001F418" + title: Durante s'ausèntzia tua... + favourite: + body: "%{name} at marcadu comente a preferidu s'istadu tuo:" + subject: "%{name} at marcadu comente a preferidu s'istadu tuo" + title: Preferidu nou + follow: + body: "%{name} t'est sighende!" + subject: "%{name} t'est sighende" + title: Una sighidura noa + follow_request: + action: Gesti is rechestas de sighidura + body: "%{name} at rechestu de ti sighire" + subject: 'Sighidura in ispera: %{name}' + title: Rechesta de sighidura noa + mention: + action: Risponde + body: "%{name} t'at mentovadu in:" + subject: "%{name} t'at mentovadu" + title: Mentovu nou + reblog: + body: "%{name} at cumpartzidu s'istadu tuo:" + subject: "%{name} at cumpartzidu s'istadu tuo" + title: Cumpartzidura noa + notifications: + email_events: Eventos pro notìficas cun posta eletrònica + email_events_hint: 'Seletziona eventos pro is chi boles retzire notìficas:' + other_settings: Àteras configuratziones de notìficas + number: + human: + decimal_units: + format: "%n%u" + units: + billion: Mrd + million: M + quadrillion: Blr + thousand: m + trillion: Bln + otp_authentication: + code_hint: Inserta·nche su còdighe generadu dae s'aplicatzione di autenticatzione pro cunfirmare + description_html: Si as a abilitare <strong>s'autenticatzione in duas fases</strong> impreende un'aplicatzione de autenticatzione, pro s'intrada as a dèpere tènnere in fatu su telèfonu tuo, chi at a ingendrare getones pro ti fà ghere intrare. + enable: Ativa + instructions_html: "<strong>Iscansi custu còdighe QR in s'autenticadore de Google o in un'aplicatzione TOTP simigiante in su telèfonu tuo</strong>. Dae como a in antis, cuss'aplicatzione at a ingendrare getones chi as a dèpere insertare pro pòdere fà ghere s'atzessu." + manual_instructions: 'Si non podet iscansire su còdighe QR e tenes bisòngiu de dd''insertare manualmente, inoghe ddoe est su còdighe segretu in testu craru:' + setup: Cunfigura + wrong_code: Su còdighe insertadu no est và lidu! S'ora de su serbidore e de su dispositivu sunt curretas? + pagination: + newer: Prus reghente + next: Sighi + older: Prus betzu + prev: A coa + truncate: "…" + polls: + errors: + already_voted: As giai votadu in custu sondà giu + duplicate_options: cuntenet elementos duplicados + duration_too_long: est tropu a tesu in su benidore + duration_too_short: est tropu chitzi + expired: Su sondà giu est giai concruidu + invalid_choice: Su sèberu de votu chi as seberadu no esistet + over_character_limit: non podet èssere superiore a %{max} carà teres cadaunu + too_few_options: depet tènnere prus de un'elementu + too_many_options: non podet cuntènnere prus de %{max} elementos + preferences: + other: Àteru + posting_defaults: Valores predefinidos de publicatzione + public_timelines: Lìnias de tempos pùblicas + reactions: + errors: + limit_reached: Lìmite de reatziones diferentes cròmpidu + unrecognized_emoji: no est un'emoji reconnotu + relationships: + activity: Atividade de su contu + dormant: Firmu + follow_selected_followers: Sighi is persones seletzionadas + followers: Sighiduras + following: Sighende + invited: Invitos + last_active: Ùrtima atividade + most_recent: Prus reghentes + moved: Tramudadu + mutual: Pari-pari + primary: Primà riu + relationship: Relatzione + remove_selected_domains: Boga totu is sighiduras de is domìnios seletzionados + remove_selected_followers: Boga is sighiduras seletzionadas + remove_selected_follows: Non sigas prus is persones seletzionadas + status: Istadu de su contu + remote_follow: + acct: Inserta·nche s'utente@domìniu tuo dae su chi boles sighire custa persone + missing_resource: Impossìbile agatare sa rechesta de indiritzamentu URL pro su contu tuo + no_account_html: Non tenes ancora unu contu? Ti podes <a href='%{sign_up_path}' target='_blank'>registrare inoghe</a> + proceed: Cumintza a sighire + prompt: 'As a sighire a:' + reason_html: "<strong>Pro ite serbit custu?</strong> Podet èssere chi <code>%{instance}</code> non siat su serbidore aunde ses registradu, pro custu tenimus bisòngiu de ti torrare a indiritzare prima a su serbidore tuo." + remote_interaction: + favourite: + proceed: Sighi pro marcare che a preferidu + prompt: 'Boles marcare comente a preferidu custu tut:' + reblog: + proceed: Sighi pro cumpartzire + prompt: 'Boles cumpartzire custu tut:' + reply: + proceed: Sighi pro rispòndere + prompt: 'Boles rispòndere a custu tut:' + scheduled_statuses: + over_daily_limit: As superadu su lìmite de %{limit} tuts programmados pro cudda die + over_total_limit: As superadu su lìmite de %{limit} tuts programmados + too_soon: Sa data programmada depet èssere benidora + sessions: + activity: Ùrtima atividade + browser: Navigadore + browsers: + alipay: Alipay + blackberry: Blackberry + chrome: Chrome + edge: Microsoft Edge + electron: Electron + firefox: Firefox + generic: Navigadore disconnotu + ie: Internet Explorer + micro_messenger: MicroMessenger + nokia: Navigadore Nokia S40 Ovi + opera: Opera + otter: Otter + phantom_js: PhantomJS + qq: QQ Browser + safari: Safari + uc_browser: UCBrowser + weibo: Weibo + current_session: Sessione atuale + description: "%{browser} de %{platform}" + explanation: Custos sunt is navigadores web de is chi ses intradu in su contu tuo de Mastodon. + ip: IP + platforms: + adobe_air: Adobe Air + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS + ios: iOS + linux: Linux + mac: macOS + other: prataforma disconnota + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone + revoke: Rèvoca + revoke_success: Sessione revocada + title: Sessiones + settings: + account: Contu + account_settings: Cunfiguratziones de su contu + aliases: Nomìngios de su contu + appearance: Aspetu + authorized_apps: Aplicatziones autorizadas + back: Torra a Mastodon + delete: Eliminatzione de su contu + development: Isvilupu + edit_profile: Modìfica profilu + export: Esportatzione de datos + featured_tags: Etichetas in evidèntzia + identity_proofs: Proas de identidade + import: Importatzione + import_and_export: Importatzione e esportatzione + migrate: Trà muda de contu + notifications: Notìficas + preferences: Preferèntzias + profile: Profilu + relationships: Persones chi sighis e chi ti sighint + two_factor_authentication: Autenticatzione de duos fatores + webauthn_authentication: Craes de seguresa + spam_check: + spam_detected: Custu est un'informe automà ticu. Àliga rilevada. + statuses: + attached: + audio: + one: "%{count} à udio" + other: "%{count} à udios" + description: 'Allegadu: %{attached}' + image: + one: "%{count} immà gine" + other: "%{count} immà gines" + video: + one: "%{count} vìdeu" + other: "%{count} vìdeos" + boosted_from_html: Cumpartzidu dae %{acct_link} + content_warning: 'Avisu de cuntenutu: %{warning}' + disallowed_hashtags: + one: 'cuntenet un''eticheta non permìtida: %{tags}' + other: 'cuntenet is etichetas non permìtidas: %{tags}' + errors: + in_reply_not_found: Ses chirchende de rispòndere a unu tut chi no esistit prus. + language_detection: Rileva sa limba in automà ticu + open_in_web: Aberi in sa web + over_character_limit: lìmite de carà teres de %{max} superadu + pin_errors: + limit: As giai apicadu su nùmeru mà ssimu de tuts + ownership: Is tuts de à tere non podent èssere apicados + private: Is tuts non pùblicos non podent èssere apicados + reblog: Is cumpartziduras non podent èssere apicadas + poll: + total_people: + one: "%{count} persone" + other: "%{count} persones" + total_votes: + one: "%{count} votu" + other: "%{count} votos" + vote: Vota + show_more: Ammustra·nde prus + show_newer: Ammustra is prus noos + show_older: Ammustra is prus betzos + show_thread: Ammustra su tema + sign_in_to_participate: Cumintzat sa sessione pro partetzipare in s'arresonada + title: '%{name}: "%{quote}"' + visibilities: + private: Isceti pro chie ti sighit + private_long: Ammustra isceti a chie ti sighit + public: Pùblicu + public_long: Podet èssere bidu dae chie si siat + unlisted: Esclùidu de sa lista + unlisted_long: Podet èssere bidu dae chie si siat, però non podet èssere ammustradu in lìnias de tempus pùblicas + stream_entries: + pinned: Tut apicadu + reblogged: cumpartzidu + sensitive_content: Cuntenutu sensìbile + tags: + does_not_match_previous_name: non cointzidet cun su nòmine anteriore + terms: + body_html: | + <h2>Polìtica de riservadesa</h2> + <h3 id="collect">Ite informatziones collimus?</h3> + + <ul> + <li><em>Informatziones de base de su contu</em>: Si t'as a registrare in custu serbidore, ti diant pòdere pedire de insertare unu nòmine utente, un'indiritzu de posta eletrònica e una crae de intrada. Dias pòdere insertare fintzas à teras informatziones de profilu, che a unu nòmine de ammustrare e una biografia, e carrigare un'immà gine de profilu e una de cobertedda. Su nòmine utente, cussu ammustradu, sa biografia, s'immà gine de profilu e de cobertedda sunt semper allistados in pùblicu.</li> + <li><em>Publicatziones, sighidores e à teras informatziones pùblicas</em>: Sa lista de is persones chi sighis est allistada in pùblicu, e sa matessi cosa balet pro is chi ti sighint. Cando imbias unu messà giu sa data e s'ora benint sarbadas, gasi comente s'aplicatzione dae sa cale as imbiadu su messà giu. Is messà gios diant pòdere cuntènnere cuntenutos multimediales allongiados, che a immà gines e vìdeos. Is publicatziones pùblicas e no allistadas sunt a disponimentu in abertu. Cando ammustras una publicatzione in su profilu tuo, fintzas cussa est un'informatzione a disponimentu pùblicu. Is publicatziones tuas benint imbiadas a is sighidores tuos, cosa chi a bortas bolet nà rrere chi benint intregadas a serbidores diferentes chi nde sarbant còpias in cue. Cando cantzellas publicatziones, custu acontessimentu benit imbiadu fintzas issu a is sighidores tuos. S'atzione de torrare a cumpartzire o de pònnere in is preferidos un'à tera publicatzione est semper pùblica.</li> + <li><em>Publicatziones diretas e pro is sighidores ebbia</em>: Totu is publicatziones benint archiviadas e protzessadas in su serbidore. Is publicatziones pro is sighidores ebbia benint intregadas a is sighidores tuos e a is utentes chi ddoe sunt mentovados in intro, e is publicatziones diretas benint intregadas isceti a is sighidores chi ddoe sunt mentovados in intro. In unos cantos casos bolet nà rrere chi benint intregados a serbidores diferentes e chi còpias issoro benint sarvadas in cue. Nois chircamus de limitare s'atzessu a custas publicatziones a is persones autorizadas ebbia, ma à teros serbidores bi diant pòdere non resessere. Pro custa resone est de importu mannu su de revisionare is serbidores a is cales faghent parte is sighidores tuos. Podes impreare un'optzione pro aprovare o refudare in manera automà tica sighidores noos in is cunfiguratziones. <em>Ammenta·ti chi is operadores de su serbidore e cale si siat serbidore chi ddos retzit podent castiare custos messà gios</em>, e chi is retzidores ddos diant pòdere sarvare faghende caturas, copiende·los o torrende·los a cumpartzire in à teras maneras. <em>Non cumpartzas peruna informatzione perigulosa impreende Mastodon.</em></li> + <li><em>IP e à teros metadatos</em>: Cando intras in su contu tuo sarvamus s'indiritzu IP dae su cale lu ses faghende, e fintzas su nòmine de s'aplicatzione chi impreas comente navigadore. Totu is sessiones de atzessu abertas sunt a disponimentu pro sa revisione e sa rèvoca in is cunfiguratziones tuas. S'ùrtimu indiritzu IP impreadu benit sarvadu finas a 12 meses. Diamus pòdere archiviare fintzas raportos chi includent is indiritzos IP de totu is rechestas a su serbidore nostru.</li> + </ul> + + <hr class="spacer" /> + + <h3 id="use">Pro ite cosas impreamus is informatziones tuas?</h3> + + <p>Totu is informatziones chi collimus dae tene diat pòdere èssere impreadas in is maneras chi sighint:</p> + + <ul> + <li>Pro frunire sa funtzionalidade de base de Mastodon. Podes interagire cun is cuntenutos de is à teras persones, e cumpartzire is tuos, isceti cando ses intradu in su contu tuo. A esèmpiu, podes sighire à teras persones pro castiare is publicatziones cumbinadas issoro in sa lìnia de tempus personalizada printzipale tua.</li> + <li>Pro agiudare sa moderatzione de sa comunidade, a esèmpiu cunfrontende s'indiritzu IP tuo cun à teros giai connotos pro verificare evasiones de blocos o à teras violatziones.</li> + <li>S'indiritzu de posta eletrònica chi as a frunire diat pòdere èssere impreadu pro t'imbiare informatziones, notìficas a pitzu de à teras persones chi ant a interagire cun is cuntenutos tuos o chi t'ant a imbiare messà gios, e pro rispòndere a interrogativos e/o à teras rechestas o preguntas.</li> + </ul> + + <hr class="spacer" /> + + <h3 id="protect">Comente amparamus is informatziones tuas?</h3> + + <p>Impreamus medidas de seguresa và rias pro amparare sa seguresa de is informatziones personales tuas cando insertas o imbias is informatziones personales tuas, o cando b'atzedes. In paris a à teras cosas, sa sessione de su navigadore tuo, e fintzas su trà ficu intre s'aplicatzione tua e s'API, benint amparados cun SSL, e sa crae tua benit tzifrada impreende un'algoritmu forte a una diretzione. Pro afortiare sa seguresa de s'atzessu a su contu tuo galu de prus podes abilitare s'autenticatzione in duos fatores.</p> + + <hr class="spacer" /> + + <h3 id="data-retention">Cale est sa polìtica nostra de archiviatzione de is datos?</h3> + + <p>Amus a fà ghere un'isfortzu in fide bona pro chircare de:</p> + + <ul> + <li>Mantènnere in archìviu is raportos chi cuntenent is indiritzos IP de totu is rechestas a custu serbidore, cando cussas rechestas benint registradas, pro non prus de 90 dies.</li> + <li>Mantènnere in archìviu is indiritzos IP assotziados a is utentes registrados pro non prus de 12 meses.</li> + </ul> + + <p>Podes pedire e iscarrigare un'archìviu de is cuntenutos tuos chi includet is publicatziones tuas, is elementos multimediales allongiados, s'immà gine de profilu e cussa de cobertedda.</p> + + <p>Podes cantzellare su contu tuo in manera irreversìbile in cale si siat momentu.</p> + + <hr class="spacer"/> + + <h3 id="cookies">Impreamus is testimòngios?</h3> + + <p>Eja. Is testimòngios ("cookies") sunt documentos minores chi unu situ o su frunidore de servìtzios suos tramudant a su discu tèteru de s'elaboradore tuo pro mèdiu de su navigadore web tuo (si bi lu permitis). Custos testimòngios permitint a su situ de reconnòschere su navigadore tuo e, si tenes unu contu registradu, de dd'assotziare cun su contu tuo.</p> + + <p>Impreamus is testimòngios pro cumprèndere e sarvare is preferèntzias tuas pro is bìsitas imbenientes.</p> + + <hr class="spacer" /> + + <h3 id="disclose">Rivelamus carchi informatzione a tertzas partes?</h3> + + <p>Non bendimus, cuncambiamus, o tramudamus in à teras maneras is informatziones tuas chi ti diant pòdere individuare in manera personale. Custu no incluit sugetos de tertzas partes fidados chi nos agiudant a amministrare su situ, fà ghere is fainas nostras, o a t'agiudare, finas a cando cussos sugetos atzetant de mantènnere cunfidentziales cussas informatziones. Diamus fintzas pòdere frunire is informatziones tuas si amus a èssere cumbintos chi siat apropriadu pro sighire is leges, aplicare is polìticas de su situ nostru, e amparare is deretos, propiedades o seguresas nostros o de à teros.</p> + + <p>Is cuntenutos pùblicos tuos diant pòdere èssere iscarrigados dae à teros serbidores in sa retza. Is publicatziones pùblicas e pro is sighidores ebbia benint intregadas a is serbidores in ue istant is retzidores, si istant in unu serbidore chi no est custu.</p> + + <p>Cando autorizas un'aplicatzione a impreare su contu tuo, a segunda de sa mannà ria de is permissos chi frunis, cussa diat pòdere atzèdere a is informatziones pùblicas de profilu tuas, a sa lista de is persones chi sighis e chi ti sighint, a is listas tuas, a totu is publicatziones tuas e a is referidos tuos. Is aplicatziones non podent mai tènnere atzessu a s'indiritzu de posta eletrònica tuo e a sa crae de intrada tua.</p> + + <hr class="spacer" /> + + <h3 id="children">Impreu de custu situ dae arte de pitzinnos</h3> + + <p>Si custu serbidore est in s'UE o in s'ÀEE: Su situ nostru, is produtos nostros e is servìtzios nostros sunt totu cantos pensados pro persones chi tenent a su mancu 16 annos de edade. Si tenes de mancu de 16 annos, in aplicatzione de is rechisitos de su GDPR (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">General Data Protection Regulation</a>) no imprees custu situ.</p> + + <p>Si custu serbidore est in sos IUA: Su situ nostru, is produtos e is servìtzios suos sunt totu cantos pensados pro persones chi tenent a su mancu 13 annos de edade. Si tenes de mancu de 13 annos, in aplicatzione de su COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Children's Online Privacy Protection Act</a>) no imprees custu situ.</p> + + <p>Is rechisidos de sa lege diant pòdere èssere diferentes si custu serbidore est in suta de un'à tera giurisditzione.</p> + + <hr class="spacer" /> + + <h3 id="changes">Modìficas a sa polìtica de riservadesa nostra</h3> + + <p>Si amus a isseberare de cambiare sa polìtica de riservadesa nostra amus a publicare is modìficas in custa pà gina.</p> + + <p>Custu documentu tenet una litzèntzia CC-BY-SA. Est istadu agiornadu s'ùrtima borta su 7 de martzu de su 2018.</p> + + <p>Adatadu, in orìgine, dae sa <a href="https://github.com/discourse/discourse">Polìtica de riservadesa de Discourse</a>.</p> + title: "%{instance} Cunditziones de su servìtziu e polìtica de riservadesa" + themes: + contrast: Mastodon (cuntrastu artu) + default: Mastodon (iscuru) + mastodon-light: Mastodon (craru) + time: + formats: + default: "%d %b %Y, %H:%M" + month: "%b %Y" + two_factor_authentication: + add: Agiunghe + disable: Disativa 2FA + disabled_success: Autenticatzione de duos fatores disativada + edit: Modìfica + enabled: Autenticatzione de duos fatores ativada + enabled_success: Autenticatzione de duos fatores ativada + generate_recovery_codes: Gènera còdighes de recùperu + lost_recovery_codes: Is còdighes de recùperu ti permitint de recuperare s'atzessu a su contu tuo si as a pèrdere su telèfonu tuo. Si perdes is còdighes de recùperu tuos, ddos podes torrare a ingendrare inoghe. Is còdighes betzos tuos s'ant a invalidare. + methods: Mètodos in duos fatores + otp: Aplicatzione de autenticatzione + recovery_codes: Còdighes de recùperu de còpia de seguridade + recovery_codes_regenerated: Còdighes de recùperu torrados a generare + recovery_instructions_html: Si una die as a pèrdere s'atzessu a su telèfonu tuo, as a pòdere impreare unu de is còdighes de recùperu inoghe in suta pro recuperare s'atzessu a su contu tuo. <strong>Cunserva is còdighes in manera segura</strong>. A esèmpiu, ddos dias pòdere imprentare e archiviare in paris a à teros documentos de importu. + webauthn: Craes de seguresa + user_mailer: + backup_ready: + explanation: As pedidu una còpia de seguresa totale de su contu de Mastodon tuo. Como est pronta pro s'iscarrigamentu! + subject: S'archìviu tuo est prontu pro èssere iscarrigadu + title: Collida dae s'archìviu + sign_in_token: + details: 'Custos sunt is detà llios de su tentativu:' + explanation: 'Amus rilevadu unu tentativu de identificatzione in su contu tuo dae un''indiritzu IP non reconnotu. Si fias tue, inserta su còdighe de seguresa in bà sciu in sa pà gina disafiu de identificatzione:' + further_actions: 'Si no fias tue, cà mbia sa crae tua e ativa s''autenticatzione in duos passos in su contu tuo. Ddu podes fà ghere inoghe:' + subject: Cunfirma su tentativu de identificatzione + title: Tentativu de identificatzione + warning: + explanation: + disable: Non podes prus intrare in su contu tuo o dd'impreare in cale si siat à tera manera, ma su profilu e is à teros datos tuos abarrant intatos. + sensitive: Is elementos e documentos multimediales carrigados e ligados tuos ant a èssere tratados che a sensìbiles. + silence: Podes ancora impreare so contu tuo, ma isceti is persones chi ti sunt giai sighende ant a bìdere is tuts tuos in custu serbidore, e dias pòdere èssere esclùdidu dae unas cantas listas pùblicas. Nointames custu, is à teros ti diant pòdere galu sighire in manera manuale. + suspend: Non podes prus impreare su contu tuo, e su profilu e à teros datos non sunt prus atzessìbiles. Bi podes galu intrare pro pedire una còpia de seguresa de is datos tuos finas a cando no ant a èssere cantzellados de su totu, ma nd'amus a mantènnere unos cantos pro non ti permìtere de evà dere sa suspensione. + get_in_touch: Podes rispòndere a custu indiritzu de posta eletrònica pro cuntatare cun su personale de %{instance}. + review_server_policies: Revisionat sas polìticas de su serbidore + statuses: 'In manera cuncreta, pro:' + subject: + disable: Su contu tuo %{acct} est istadu cungeladu + none: Avisu pro %{acct} + sensitive: Is elementos multimediales de publicatzione de su contu tuo %{acct} sunt istados marcados comente sensìbiles + silence: Su contu tuo %{acct} est istadu limitadu + suspend: Su contu tuo %{acct} est istadu suspèndidu + title: + disable: Contu congeladu + none: Atentzione + sensitive: S'elementu multimediale tuo est istadu marcadu comente sensìbile + silence: Contu limitadu + suspend: Contu suspèndidu + welcome: + edit_profile_action: Cunfigura su profilu + edit_profile_step: Podes personalizare su profilu tuo carrighende un'à vatar o un'intestatzione, cambiende su nòmine visìbile tuo e faghende fintzas à teru. Si boles revisionare is sighidores noos in antis chi tèngiant su permissu de ti sighire podes blocare su contu tuo. + explanation: Inoghe b'ant una paja de impòsitos pro cumintzare + final_action: Cumintza a publicare + final_step: 'Cumintza a publicare! Fintzas si no ti sighit nemos is à teros podent bìdere is messà gios pùblicos tuos, pro esèmpiu in sa lìnia de tempus locale e in is etichetas ("hashtags"). Ti dias pòdere bòlere introduire a sa comunidade cun s''eticheta #introductions.' + full_handle: Su nòmine utente intreu tuo + full_handle_hint: Custu est su chi dias nà rrere a is amigos tuos pro chi ti potzant imbiare messà gios o sighire dae un'à teru serbidore. + review_preferences_action: Muda is preferèntzias + review_preferences_step: Ammenta·ti de impostare is preferèntzias tuas, che a is lìteras de posta eletrònicas chi boles retzire, o ite livellu de riservadesa dias bòlere chi siat predefinidu pro is messà gios tuos. Si is immà gines in movimentu non ti infadant podes isseberare de abilitare sa riprodutzione automà tica de is GIF. + subject: Ti donamus su benebènnidu a Mastodon + tip_federated_timeline: Sa lìnia de tempus federada est una vista globale de sa retza de Mastodon. Ma incluit isceti is persones sighidas dae is bighinos tuos, duncas no est totale. + tip_following: Pro more de is cunfiguratziones predefinidas sighis s'amministratzione de su serbidore tuo. Pro agatare à teras persones de interessu, cà stia is lìnias de su tempus locale e federada. + tip_local_timeline: Sa lìnia de tempus locale est una vista globale de is persones in %{instance}. Custos sunt is bighinos tuos! + tip_mobile_webapp: Si su navigadore mòbile tuo t'oferit de agiùnghere Mastodon a s'ischermada printzipale tua podes retzire notìficas push. Funtzionat che a un'aplicatzione nativa in maneras medas! + tips: Impòsitos + title: Bene bènnidu a bordu, %{name}! + users: + blocked_email_provider: Custu frunidore de posta eletrònica no est permìtidu + follow_limit_reached: Non podes sighire prus de %{limit} persones + generic_access_help_html: Tenes problemas a intrare in su contu tuo? Podes cuntatare a %{email} pro retzire agiudu + invalid_email: Custu indiritzu de posta eletrònica no est và lidu + invalid_email_mx: Custu indiritzu de posta eletrònica paret chi no esistat + invalid_otp_token: Còdighe a duas fases non và lidu + invalid_sign_in_token: Còdighe de seguresa non và lidu + otp_lost_help_html: Si as pèrdidu s'atzessu a ambos, podes cuntatare a %{email} + seamless_external_login: Ses intradu pro mèdiu de unu servìtziu esternu, e pro custa resone is impostatziones de sa crae de intrada e de posta eletrònica non sunt a disponimentu. + signed_in_as: 'Sessione aberta comente:' + suspicious_sign_in_confirmation: Paret chi tue non sias giai intradu dae custu dispositivu e non ses intradu dae unu pagu de tempus, duncas ti semus mandende unu còdighe de seguresa a s'indiritzu de posta eletrònica tuo pro cunfirmare chi ses tue. + verification: + explanation_html: 'Ti podes <strong>verificare a sa sola comente mere de is ligòngios in is metadatos de su profilu tuo</strong>. Pro ddu fà ghere su situ ligadu depet cuntènnere unu ligòngiu chi torret a su profilu de Mastodon tuo. Su ligòngiu in su situ <strong>depet</strong> tènnere un''atributu <code>rel="me"</code>. Su testu cuntenutu in su ligòngiu no est de importu. Custu est un''esèmpiu:' + verification: Verìfica + webauthn_credentials: + add: Agiunghe una crae de seguresa noa + create: + error: Ddoe est istadu unu problema cun s'agiunta de sa crae de seguresa tua. Torra a proare. + success: Sa crae de seguresa tua est istada agiunta. + delete: Cantzella + delete_confirmation: Seguru chi boles cantzellare custa crae de seguresa? + description_html: Si permites s'<strong>autenticatzione cun crae de seguresa</strong>, as a tènnere bisòngiu de impreare una de is craes de seguresa tuas pro ti identificare. + destroy: + error: Ddoe est istadu unu problema cun sa cantzelladura de sa crae de seguresa tua. Torra a proare. + success: Sa crae de seguresa tua est istada cantzellada. + invalid_credential: Crae de seguresa non và lida + nickname_hint: Inserta su nomìngiu de sa crae de seguresa tua noa + not_enabled: No as ativadu ancora WebAuthn + not_supported: Custu navigadore no est cumpatìbile cun is craes de seguresa + otp_required: Pro impreare is craes de seguresa depes ativare prima s'autenticatzione in duos passos. + registered_on: 'Registratzione: %{date}' diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml index 8d149d11fa22d52c47c051bbe67f1e5dd67ca8bf..63f122b78f8e763eac2232f04848e5498356b4fb 100644 --- a/config/locales/simple_form.ar.yml +++ b/config/locales/simple_form.ar.yml @@ -88,7 +88,7 @@ ar: disable: تعطيل none: لا ØªÙØ¹Ù„ شيئا silence: كتم - suspend: تعليق Ùˆ ØØ°Ù ÙƒØ§ÙØ© بيانات Ø§Ù„ØØ³Ø§Ø¨ + suspend: علÙÙ‚ warning_preset_id: استخدم نموذج تنبيه announcement: all_day: ØØ¯Ø« اليوم كله @@ -162,6 +162,8 @@ ar: comment: التعليق invite_request: text: لماذا ترغب ÙÙŠ الانضمام؟ + ip_block: + ip: عنوان IP notification_emails: digest: إرسال ملخصات عبر البريد الإلكتروني favourite: ابعث بريداً إلكترونيًا عندما ÙŠÙØ¹Ø¬ÙŽØ¨ Ø£ØØ¯Ù‡Ù… بمنشورك diff --git a/config/locales/simple_form.br.yml b/config/locales/simple_form.br.yml index b67db471f8bad5026480e5b6840770dc518d6772..4cbc173bd310be508e9d4955c1bd65dd576edc47 100644 --- a/config/locales/simple_form.br.yml +++ b/config/locales/simple_form.br.yml @@ -4,10 +4,16 @@ br: labels: account_warning_preset: title: Titl + admin_account_action: + types: + suspend: Astalañ announcement: text: Kemenn defaults: + current_password: Ger-tremen a vremañ + data: Roadennoù display_name: Anv diskouezet + email: Chomlec'h postel header: Talbenn locale: Yezh ar c'hetal new_password: Ger-tremen nevez @@ -15,6 +21,11 @@ br: setting_display_media_default: Dre ziouer setting_display_media_hide_all: Kuzhat pep tra setting_display_media_show_all: Diskouez pep tra + username: Anv + featured_tag: + name: Ger-klik + invite: + comment: Evezhiadenn tag: name: Ger-klik 'no': Ket diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 00ca1ed5d666e11735a4ec13ba7d99db1f2bac08..b3692f5bae59bcdd42d3aba3d5bfce5242482ae8 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -65,8 +65,17 @@ ca: data: Fitxer CSV exportat des d'un altre servidor de Mastodon invite_request: text: Això ens ajudarà a revisar la teva petició + ip_block: + comment: Opcional. Recordatori de perquè l’has afegit. + expires_in: Les adreces IP son un recurs finit, de vegades son compartides i sovint canvien de mans. Per aquest motiu no es recomanen els bloquejos d’IP indefinits. + ip: Introdueix una adreça IPv4 o IPv6. Pots bloquejar rangs complets amb la sintaxi CIDR. Ves a compte no et bloquegis a tu mateix! + severities: + no_access: Bloqueja l’accés a tots els recursos + sign_up_requires_approval: Els nous registres requeriran la teva aprovació + severity: Tria què passarà amb les sol·licituds des d’aquesta IP sessions: otp: 'Introdueix el codi de dos factors generat per el teu telèfon o utilitza un dels teus codis de recuperació:' + webauthn: Si és una clau USB assegurat de que està inserida i, si és necessari, toca-ho. tag: name: Només pots canviar la caixa de les lletres, per exemple, per fer-la més llegible user: @@ -91,6 +100,7 @@ ca: types: disable: Inhabilita none: No fer res + sensitive: Sensible silence: Silenci suspend: Suspèn i elimina irreversiblement les dades del compte warning_preset_id: Utilitza una configuració predefinida d'avÃs @@ -116,6 +126,7 @@ ca: expires_in: Expira després fields: Metadades del perfil header: Capçalera + honeypot: "%{label} (no omplir)" inbox_url: URL de la safata d'entrada del relay irreversible: Cau en lloc d'ocultar locale: Llengua de la interfÃcie @@ -135,6 +146,7 @@ ca: setting_default_privacy: Privacitat de les publicacions setting_default_sensitive: Marca sempre els elements multimèdia com a sensibles setting_delete_modal: Mostra la finestra de confirmació abans d'esborrar un tut + setting_disable_swiping: Desactivar les animacions setting_display_media: Visualització multimèdia setting_display_media_default: Per defecte setting_display_media_hide_all: Amaga-ho tot @@ -168,6 +180,13 @@ ca: comment: Comenta invite_request: text: Per què vols unir-te? + ip_block: + comment: Comentari + ip: IP + severities: + no_access: Bloquejar l’accés + sign_up_requires_approval: Limitar els registres + severity: Regla notification_emails: digest: Envia un resum per correu electrònic favourite: Envia un correu electrònic si algú marca com a preferit el teu estat @@ -188,4 +207,7 @@ ca: required: mark: "*" text: necessari + title: + sessions: + webauthn: Usa una de les teves claus de seguretat per a iniciar sessió 'yes': Sà diff --git a/config/locales/simple_form.co.yml b/config/locales/simple_form.co.yml index f3edefdf315f3350abfeb651aa7274c67cc0d330..1d41066d1b3c8c6cacf31737a2b2572e96ea600c 100644 --- a/config/locales/simple_form.co.yml +++ b/config/locales/simple_form.co.yml @@ -65,8 +65,17 @@ co: data: Un fugliale CSV da un’altru servore di Mastodon invite_request: text: Quessu ci aiutarà à valutà a vostra dumanda + ip_block: + comment: In uzzione. Rammintatevi di perchè avete aghjuntu sta regula. + expires_in: L'indirizzi IP sò una risorsa finita, ponu esse spartute è spessu cambianu di mani. Ghjè perchè i blucchimi d'IP permanenti ùn sò micca ricumandati. + ip: Entrate un'indirizzu IPv4 o IPv6. Pudete bluccà tutt'un'intervallu cù a sintassa CIDR. Fate attenzione, ùn vi bluccate micca! + severities: + no_access: Bluccà l'accessu à tutte e risorse + sign_up_requires_approval: E nove dumande d'arregistramente necessitaranu a vostr'appruvazione + severity: Sceglie ciò chì si passerà cù e richieste di quest'IP sessions: otp: 'Entrate u codice d’identificazione à dui fattori nant’à u vostru telefuninu, o unu di i vostri codici di ricuperazione:' + webauthn: S'ella hè una chjave USB assicuratevi di brancalla è, s'ellu c'hè unu, appughjà nant'à u buttone. tag: name: Pudete solu cambià a cassa di i caratteri, per esempiu per u rende più lighjevule user: @@ -91,6 +100,7 @@ co: types: disable: Disattivà none: Ùn fà nunda + sensitive: Sensibile silence: Silenzà suspend: Suspende è sguassà i dati di u contu di manera irreversibile warning_preset_id: Utilizà un'avertimentu preselezziunatu @@ -116,6 +126,7 @@ co: expires_in: Spira dopu à fields: Metadata di u prufile header: Ritrattu di cuprendula + honeypot: "%{label} (ùn empie micca)" inbox_url: URL di l'inbox di u ripetitore irreversible: Sguassà invece di piattà locale: Lingua di l'interfaccia @@ -135,6 +146,7 @@ co: setting_default_privacy: Cunfidenzialità di i statuti setting_default_sensitive: Sempre cunsiderà media cum’è sensibili setting_delete_modal: Mustrà une cunfirmazione per toglie un statutu + setting_disable_swiping: Disattivà e sculiscere setting_display_media: Affissera di i media setting_display_media_default: Predefinitu setting_display_media_hide_all: Piattà tuttu @@ -168,6 +180,13 @@ co: comment: Cummentariu invite_request: text: Perchè vulete ghjunghje? + ip_block: + comment: Cummentariu + ip: IP + severities: + no_access: Bluccà l'accessu + sign_up_requires_approval: Limità l'arregistramenti + severity: Regula notification_emails: digest: Mandà e-mail di ricapitulazione favourite: Mandà un’e-mail quandu qualch’unu aghjunghje i mo statuti à i so favuriti @@ -188,4 +207,7 @@ co: required: mark: "*" text: riquisiti + title: + sessions: + webauthn: Utilizà una chjave di sicurità per cunnettassi 'yes': Ié diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index d6681e664be01347e6961209e0184e6811b94328..cb3f75c1aa6a0234c7a83c7d1b84693d7a7cbcaa 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -151,6 +151,7 @@ cy: setting_use_blurhash: Dangoswch raddiannau lliwgar ar gyfer cyfryngau cudd setting_use_pending_items: Modd araf severity: Difrifoldeb + sign_in_token_attempt: Cod dioelwch type: Modd mewnforio username: Enw defnyddiwr username_or_email: Enw defnyddiwr neu e-bost diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index d7a10a4a9501aee8a90a0027b8b33587c3283032..1c16c8e372f29a4d07a7a0ff091f32f74d0a0a97 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -2,6 +2,8 @@ da: simple_form: hints: + account_warning_preset: + title: Valgfri. Ikke synlig for modtageren admin_account_action: type_html: Vælg hvad du vil gøre med <strong>%{acct}</strong> defaults: @@ -9,6 +11,7 @@ da: avatar: PNG, GIF eller JPG. Højest %{size}. Vil blive skaleret ned til %{dimensions}px bot: Denne konto udfører hovedsageligt automatiserede handlinger og bliver muligvis ikke overvÃ¥get context: En eller flere sammenhænge hvor filteret skal være gældende + current_username: For at bekræfte, angiv venligst brugernavnet pÃ¥ den aktuelle konto digest: Sendes kun efter en lang periode med inaktivitet og kun hvis du har modtaget nogle personlige beskeder i dit fravær email: Du vil fÃ¥ tilsendt en bekræftelses e-mail fields: Du kan have op til 4 ting vist som en tabel pÃ¥ din profil @@ -22,14 +25,24 @@ da: scopes: Hvilke APIs applikationen vil fÃ¥ adgang til. Hvis du vælger et højtlevel omfang, behøver du ikke vælge enkeltstÃ¥ende. setting_display_media_default: Skjul medier markeret som følsomt setting_display_media_hide_all: Skjul altid alle medier + setting_display_media_show_all: Vis altid medier setting_hide_network: Hvem du følger og hvem der følger dig vil ikke blive vist pÃ¥ din profil setting_noindex: PÃ¥virker din offentlige profil og status sider username: Dit brugernavn vil være unikt pÃ¥ %{domain} whole_word: NÃ¥r nøgle ordet eller udtrykket kun er alfanumerisk, vil det kun blive brugt hvis det passer hele ordet featured_tag: name: 'Du kunne mÃ¥ske tænke dig at bruge en af følgende:' + form_challenge: + current_password: Du indtræder et sikkert omrÃ¥de imports: data: CSV fil eksporteret fra en anden Mastodon server + invite_request: + text: Dette vil hjælpe os med at gennemgÃ¥ din ansøgning + ip_block: + comment: Valgfri. Husk hvorfor du har tilføjet denne regel. + severities: + no_access: Bloker for adgangen til alle ressourcer + sign_up_requires_approval: Nye tilmeldinger kræver din godkendelse sessions: otp: 'Indtast to-faktor koden der generes af appen af appen pÃ¥ din telefon eller brug en af din genoprettelses koder:' user: @@ -52,6 +65,10 @@ da: silence: Silence suspend: Suspendér og slet kontodata uopretteligt warning_preset_id: Brug en forudindstillet advarsel + announcement: + all_day: Heldags begivenhed + scheduled_at: Planlæg offentliggørelse + text: Bekendtgørelse defaults: autofollow: Inviter til at følge din konto avatar: Profilbillede @@ -99,10 +116,13 @@ da: setting_unfollow_modal: Vis bekræftelses dialog før du stopper med at følge nogen setting_use_pending_items: Langsom tilstand severity: Omfang + sign_in_token_attempt: Sikkerhedskode type: Importtype username: Brugernavn username_or_email: Brugernavn eller Email whole_word: Helt ord + email_domain_block: + with_dns_records: Inkluder MX-optegnelser og IP'er for domænet featured_tag: name: Hashtag interactions: @@ -113,6 +133,13 @@ da: comment: Kommentar invite_request: text: Hvorfor ønsker du at tilmelde dig? + ip_block: + comment: Kommentar + ip: IP + severities: + no_access: Bloker adgang + sign_up_requires_approval: Begræns tilmeldinger + severity: Regel notification_emails: digest: Send sammendrag via emails favourite: Send email nÃ¥r nogen favoriserer din status @@ -133,4 +160,7 @@ da: required: mark: "*" text: pÃ¥krævet + title: + sessions: + webauthn: Log pÃ¥ ved brug af en af dine sikkerhedskoder 'yes': Ja diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index 999c4432de0791ee7cfee1dc6d1241b374641f80..711dbf5c68c73cae897249866bcd668fbf3d379f 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -41,8 +41,8 @@ de: phrase: Wird schreibungsunabhängig mit dem Text und Inhaltswarnung eines Beitrags verglichen scopes: Welche Schnittstellen der Applikation erlaubt sind. Wenn du einen Top-Level-Scope auswählst, dann musst du nicht jeden einzelnen darunter auswählen. setting_aggregate_reblogs: Zeige denselben Beitrag nicht nochmal an, wenn er erneut geteilt wurde (dies betrifft nur neulich erhaltene erneut geteilte Beiträge) - setting_default_sensitive: Heikle Medien werden erst nach einem Klick sichtbar - setting_display_media_default: Verstecke Medien, die als sensibel markiert sind + setting_default_sensitive: NSFW-Medien werden erst nach einem Klick sichtbar + setting_display_media_default: Verstecke Medien, die als NSFW markiert sind setting_display_media_hide_all: Alle Medien immer verstecken setting_display_media_show_all: Alle Medien immer anzeigen setting_hide_network: Wem du folgst und wer dir folgt, wird in deinem Profil nicht angezeigt @@ -56,7 +56,7 @@ de: domain: Diese Domain kann Daten von diesem Server abrufen und eingehende Daten werden verarbeitet und gespeichert email_domain_block: domain: Dies kann der Domainname sein, der in der E-Mail-Adresse angezeigt wird, den MX-Datensatz, der aufgelöst wird oder die IP des Servers, auf dem der MX-Eintrag aufgelöst wird. Diese werden bei der Registrierung überprüft und die Registrierung wird abgelehnt. - with_dns_records: Ein Versuch die DNS-Einträge der Domain aufzulösen wurde unternommen und diese Ergebnisse werden unter anderem auch geblacklistet + with_dns_records: Ein Versuch die DNS-Einträge der Domain aufzulösen wurde unternommen und diese Ergebnisse werden unter anderem auch geblockt featured_tag: name: 'Du möchtest vielleicht einen von diesen benutzen:' form_challenge: @@ -65,8 +65,17 @@ de: data: CSV-Datei, die aus einem anderen Mastodon-Server exportiert wurde invite_request: text: Dies wird uns helfen deine Anmeldungsanfrage besser zu verarbeiten + ip_block: + comment: Optional. Denke daran, warum du diese Regel hinzugefügt hast. + expires_in: IP-Adressen sind eine endliche Ressource, sie werden manchmal geteilt und werden ab und zu ausgetauscht. Aus diesem Grund werden unbestimmte IP-Blöcke nicht empfohlen. + ip: Gebe eine IPv4- oder IPv6-Adresse an. Du kannst ganze Bereiche mit der CIDR-Syntax blockieren. Achte darauf, dass du dich nicht aussperrst! + severities: + no_access: Zugriff auf alle Ressourcen blockieren + sign_up_requires_approval: Neue Anmeldungen erfordern deine Zustimmung + severity: Wähle aus, was mit Anfragen aus dieser IP passiert sessions: otp: 'Gib die Zwei-Faktor-Authentifizierung von deinem Telefon ein oder benutze einen deiner Wiederherstellungscodes:' + webauthn: Wenn es sich um einen USB-Schlüssel handelt, stelle sicher, dass du ihn einsteckst und ihn antippst. tag: name: Du kannst zum Beispiel nur die Groß- und Kleinschreibung der Buchstaben ändern, um es lesbarer zu machen user: @@ -91,6 +100,7 @@ de: types: disable: Deaktivieren none: Nichts tun + sensitive: NSFW silence: Stummschalten suspend: Deaktivieren und Benutzerdaten unwiderruflich löschen warning_preset_id: Benutze eine Warnungsvorlage @@ -116,6 +126,7 @@ de: expires_in: Läuft ab fields: Tabellenfelder header: Titelbild + honeypot: "%{label} (nicht ausfüllen)" inbox_url: Inbox-URL des Relais irreversible: Verwerfen statt verstecken locale: Sprache der Benutzeroberfläche @@ -133,10 +144,11 @@ de: setting_crop_images: Bilder in nicht ausgeklappten Beiträgen auf 16:9 zuschneiden setting_default_language: Beitragssprache setting_default_privacy: Beitragssichtbarkeit - setting_default_sensitive: Medien immer als heikel markieren + setting_default_sensitive: Medien immer als NSFW markieren setting_delete_modal: Bestätigungsdialog anzeigen, bevor ein Beitrag gelöscht wird + setting_disable_swiping: Deaktiviere Wischgesten setting_display_media: Medien-Anzeige - setting_display_media_default: Heikle Inhalte verstecken + setting_display_media_default: NSFW-Inhalte verstecken setting_display_media_hide_all: Alle Medien verstecken setting_display_media_show_all: Alle Medien anzeigen setting_expand_spoilers: Beiträge mit Inhaltswarnungen immer ausklappen @@ -168,6 +180,13 @@ de: comment: Kommentar invite_request: text: Warum möchtest du beitreten? + ip_block: + comment: Kommentar + ip: IP-Adresse + severities: + no_access: Zugriff sperren + sign_up_requires_approval: Anmeldungen begrenzen + severity: Regel notification_emails: digest: Kurzfassungen über E-Mail senden favourite: E-Mail senden, wenn jemand meinen Beitrag favorisiert @@ -188,4 +207,7 @@ de: required: mark: "*" text: Pflichtfeld + title: + sessions: + webauthn: Verwende einer deiner Sicherheitsschlüssel zum Anmelden 'yes': Ja diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 86ba0d3033e3b561a36102ce64bc6d350c94bc16..d4c8a2da6852e90cc52ac3bb901005837cd4c7a4 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -65,8 +65,15 @@ el: data: ΑÏχείο CSV που Îχει εξαχθεί από διαφοÏετικό κόμβο Mastodon invite_request: text: Αυτό θα μας βοηθήσει να επιθεωÏήσουμε την αίτησή σου + ip_block: + comment: Î ÏοαιÏετικό. Θυμηθείτε γιατί Ï€ÏοσθÎσατε αυτόν τον κανόνα. + severities: + no_access: Αποκλεισμός Ï€Ïόσβασης σε όλους τους πόÏους + sign_up_requires_approval: ÎÎες εγγÏαφÎÏ‚ θα απαιτοÏν την ÎγκÏιση σας + severity: ΕπιλÎξτε τι θα γίνεται με αιτήσεις από αυτήν την διεÏθυνση IP sessions: otp: 'Βάλε τον κωδικό δυο παÏαγόντων (2FA) από την εφαÏμογή του τηλεφώνου σου ή χÏησιμοποίησε κάποιον από τους κωδικοÏÏ‚ ανάκτησης σου:' + webauthn: Αν Ï€Ïόκειται για Îνα κλειδί USB βεβαιωθείτε ότι είναι συνδεδεμÎνο και αν απαιτείται πατήστε το ελαφÏά. tag: name: ΜποÏείς να αλλάξεις μόνο το πλαίσιο των χαÏακτήÏων, για παÏάδειγμα για να γίνει πεÏισσότεÏο ευανάγνωστο user: @@ -91,6 +98,7 @@ el: types: disable: ΑπενεÏγοποίηση none: Καμία ενÎÏγεια + sensitive: Ευαίσθητο silence: Αποσιώπηση suspend: Αναστολή και αμετάκλητη διαγÏαφή στοιχείων λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï warning_preset_id: ΧÏήση Ï€ÏοκαθοÏισμÎνης Ï€Ïοειδοποίησης @@ -116,9 +124,10 @@ el: expires_in: Λήξη μετά από fields: ΜεταδεδομÎνα Ï€Ïοφίλ header: Επικεφαλίδα + honeypot: "%{label} (μη συμπληÏώνετε)" inbox_url: Το URL του inbox του ανταποκÏιτή (relay) irreversible: ΑπόÏÏιψη αντί για κÏÏψιμο - locale: Γλώσσα πεÏιβάλλοντος + locale: Γλώσσα χÏήσης locked: Κλείδωμα λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï max_uses: ΜÎγιστος αÏιθμός χÏήσεων new_password: ÎÎο συνθηματικό @@ -135,6 +144,7 @@ el: setting_default_privacy: Ιδιωτικότητα δημοσιεÏσεων setting_default_sensitive: Σημείωση όλων των πολυμÎσων ως ευαίσθητου πεÏιεχομÎνου setting_delete_modal: Επιβεβαίωση Ï€Ïιν τη διαγÏαφή ενός τουτ + setting_disable_swiping: ΑπενεÏγοποίηση κινήσεων συÏσίματος setting_display_media: Εμφάνιση πολυμÎσων setting_display_media_default: Î ÏοκαθοÏισμÎνο setting_display_media_hide_all: ΑπόκÏυψη όλων @@ -168,6 +178,13 @@ el: comment: Σχόλια invite_request: text: Γιατί θÎλεις να συμμετάσχεις; + ip_block: + comment: Σχόλιο + ip: IP + severities: + no_access: Αποκλεισμός Ï€Ïόσβασης + sign_up_requires_approval: ΠεÏιοÏισμός εγγÏαφών + severity: Κανόνας notification_emails: digest: Αποστολή συνοπτικών email favourite: Αποστολή email όταν κάποιος σημειώνει ως αγαπημÎνη τη δημοσίευσή σου @@ -188,4 +205,7 @@ el: required: mark: "*" text: απαιτείται + title: + sessions: + webauthn: ΧÏησιμοποιείστε Îνα από τα κλειδιά ασφαλείας σας για να συνδεθείτε 'yes': Îαι diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 0a8a6fd62885bdb72a0504cc5ea8e39d45249e1f..20c91656028cd28af717e3db2020f68f42a4651d 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -65,8 +65,17 @@ en: data: CSV file exported from another Mastodon server invite_request: text: This will help us review your application + ip_block: + comment: Optional. Remember why you added this rule. + expires_in: IP addresses are a finite resource, they are sometimes shared and often change hands. For this reason, indefinite IP blocks are not recommended. + ip: Enter an IPv4 or IPv6 address. You can block entire ranges using the CIDR syntax. Be careful not to lock yourself out! + severities: + no_access: Block access to all resources + sign_up_requires_approval: New sign-ups will require your approval + severity: Choose what will happen with requests from this IP sessions: otp: 'Enter the two-factor code generated by your phone app or use one of your recovery codes:' + webauthn: If it's an USB key be sure to insert it and, if necessary, tap it. tag: name: You can only change the casing of the letters, for example, to make it more readable user: @@ -89,10 +98,11 @@ en: text: Custom warning type: Action types: - disable: Disable login - none: Do nothing - silence: Silence - suspend: Suspend and irreversibly delete account data + disable: Freeze + none: Send a warning + sensitive: Sensitive + silence: Limit + suspend: Suspend warning_preset_id: Use a warning preset announcement: all_day: All-day event @@ -116,6 +126,7 @@ en: expires_in: Expire after fields: Profile metadata header: Header + honeypot: "%{label} (do not fill in)" inbox_url: URL of the relay inbox irreversible: Drop instead of hide locale: Interface language @@ -135,6 +146,7 @@ en: setting_default_privacy: Posting privacy setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog before deleting a toot + setting_disable_swiping: Disable swiping motions setting_display_media: Media display setting_display_media_default: Default setting_display_media_hide_all: Hide all @@ -168,6 +180,13 @@ en: comment: Comment invite_request: text: Why do you want to join? + ip_block: + comment: Comment + ip: IP + severities: + no_access: Block access + sign_up_requires_approval: Limit sign-ups + severity: Rule notification_emails: digest: Send digest e-mails favourite: Someone favourited your status @@ -188,4 +207,7 @@ en: required: mark: "*" text: required + title: + sessions: + webauthn: Use one of your security keys to sign in 'yes': 'Yes' diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index 308738c889ed770a009c244ccb085cf88ad15e46..3f399deaed1dc59eb751c81ab60b65bfd1791878 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -29,7 +29,7 @@ eo: phrase: Estos provita senzorge pri la uskleco de teksto aÅ averto pri enhavo de mesaÄo scopes: Kiujn API-ojn la aplikaĵo permesiÄos atingi. Se vi elektas supran amplekson, vi ne bezonas elekti la individuajn. setting_aggregate_reblogs: Ne montri novajn diskonigojn de mesaÄoj laste diskonigitaj (nur efikas al novaj diskonigoj) - setting_default_sensitive: Sentema komunikilo estas kaÅita defaÅlte kaj povas esti rivelita per alklako + setting_default_sensitive: Tiklaj aÅdovidaĵoj estas defaÅlte kaÅita kaj povas esti malkiÅita per klako setting_display_media_default: KaÅi aÅdovidaĵojn markitajn kiel tiklaj setting_display_media_hide_all: Ĉiam kaÅi ĉiujn aÅdovidaĵojn setting_display_media_show_all: Ĉiam montri aÅdovidaĵojn markitajn kiel tiklaj @@ -47,6 +47,9 @@ eo: data: CSV-dosiero el alia Mastodon-servilo invite_request: text: Ĉi tio helpos nin revizii vian kandidatiÄon + ip_block: + severities: + sign_up_requires_approval: Novaj registriÄoj devigos vian aprobon sessions: otp: 'Enmetu la kodon de dufaktora aÅtentigo el via telefono aÅ uzu unu el viaj realiraj kodoj:' user: @@ -64,12 +67,13 @@ eo: text: AntaÅagordita teksto title: Titolo admin_account_action: - send_email_notification: Atentigi la uzanton retpoÅte + send_email_notification: Sciigi la uzanton retpoÅte text: Propra averto type: Ago types: disable: Malebligi none: Fari nenion + sensitive: Tikla silence: Silentigi suspend: Haltigi kaj nemalfereble forigi kontajn datumojn warning_preset_id: Uzi antaÅagorditan averton @@ -95,6 +99,7 @@ eo: expires_in: EksvalidiÄas post fields: Profilaj metadatumoj header: Fonbildo + honeypot: "%{label} (ne plenigi)" inbox_url: URL de la ripetila enirkesto irreversible: Forĵeti anstataÅ kaÅi locale: Interfaca lingvo @@ -108,12 +113,12 @@ eo: setting_advanced_layout: Ebligi altnivelan retpaÄan interfacon setting_aggregate_reblogs: Grupigi diskonigojn en tempolinioj setting_auto_play_gif: AÅtomate ekigi GIF-ojn - setting_boost_modal: Montri fenestron por konfirmi antaÅ ol diskonigi mesaÄon + setting_boost_modal: Montri konfirman fenestron antaÅ ol diskonigi mesaÄon setting_crop_images: Stuci bildojn en negrandigitaj mesaÄoj al 16x9 setting_default_language: Publikada lingvo setting_default_privacy: MesaÄa videbleco setting_default_sensitive: Ĉiam marki aÅdovidaĵojn tiklaj - setting_delete_modal: Montri fenestron por konfirmi antaÅ ol forigi mesaÄon + setting_delete_modal: Montri konfirman fenestron antaÅ ol forigi mesaÄon setting_display_media: AÅdovidaĵa montrado setting_display_media_default: Dekomenca setting_display_media_hide_all: KaÅi ĉiujn @@ -126,10 +131,11 @@ eo: setting_system_font_ui: Uzi la dekomencan tiparon de la sistemo setting_theme: Reteja etoso setting_trends: Montri hodiaÅajn furoraĵojn - setting_unfollow_modal: Montri fenestron por konfirmi antaÅ ol ĉesi sekvi iun + setting_unfollow_modal: Montri konfirman fenestron antaÅ ol ĉesi sekvi iun setting_use_blurhash: Montri buntajn transirojn por kaÅitaj aÅdovidaĵoj setting_use_pending_items: Malrapida reÄimo severity: Graveco + sign_in_token_attempt: Sekureca kodo type: Importa tipo username: Uzantnomo username_or_email: Uzantnomo aÅ Retadreso @@ -144,6 +150,13 @@ eo: comment: Komento invite_request: text: Kial vi volas aliÄi? + ip_block: + comment: Komento + ip: IP + severities: + no_access: Bloki atingon + sign_up_requires_approval: Limigi registriÄojn + severity: Regulo notification_emails: digest: Sendi resumajn retmesaÄojn favourite: Sendi retmesaÄon kiam iu stelumas vian mesaÄon @@ -153,11 +166,11 @@ eo: pending_account: Sendi retmesaÄon kiam nova konto bezonas kontrolon reblog: Sendi retmesaÄon kiam iu diskonigas vian mesaÄon report: Nova signalo estas sendita - trending_tag: Sendi retpoÅtmesaÄon kiam nekontrolita kradvorto furoras + trending_tag: Nekontrolita kradvorto furoras tag: name: Kradvorto trendable: Permesi al ĉi tiu kradvorto aperi en furoraĵoj - usable: Permesi tootojn uzi ĉiun tiun haketon + usable: Permesi mesaÄojn uzi ĉi tiun kradvorton 'no': Ne recommended: Rekomendita required: diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index a3195f6b8d0f61d4839cf98e0148097e0c17bf4c..153c1101d1b868f6dd5bdbcf9e6b322ae3296f43 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -12,7 +12,7 @@ es-AR: admin_account_action: include_statuses: El usuario verá qué toots causaron la acción de moderación o advertencia send_email_notification: El usuario recibirá una explicación de lo que sucedió con su cuenta - text_html: Opcional. Podés usar sintaxis de toots. Podés <a href="%{path}">agregar preajustes de advertencia</a> para ahorrar tiempo. + text_html: Opcional. Podés usar sintaxis de toots. Podés <a href="%{path}">agregar preajustes de advertencia</a> para ahorrar tiempo type_html: Elegà qué hacer con <strong>%{acct}</strong> warning_preset_id: Opcional. TodavÃa podés agregar texto personalizado al final del preajuste announcement: @@ -20,31 +20,31 @@ es-AR: ends_at: Opcional. El anuncio desaparecerá automáticamente en este momento scheduled_at: Dejar en blanco para publicar el anuncio inmediatamente starts_at: Opcional. En caso de que tu anuncio esté vinculado a un rango de tiempo especÃfico - text: Podés usar la sintaxis de toot. Por favor, tené en cuenta el espacio que ocupará el anuncio en la pantalla del usuario + text: Podés usar sintaxis de toots. Por favor, tené en cuenta el espacio que ocupará el anuncio en la pantalla del usuario defaults: autofollow: Los usuarios que se registren mediante la invitación te seguirán automáticamente - avatar: 'PNG, GIF o JPG. Máximo: %{size}. Será subescalado a %{dimensions} pÃxeles.' + avatar: 'PNG, GIF o JPG. Máximo: %{size}. Será subescalado a %{dimensions} pÃxeles' bot: Esta cuenta ejecuta principalmente acciones automatizadas y podrÃa no ser monitorizada context: Uno o múltiples contextos en los que debe aplicarse el filtro current_password: Por razones de seguridad, por favor, ingresá la contraseña de la cuenta actual current_username: Para confirmar, por favor, ingresá el nombre de usuario de la cuenta actual - digest: Sólo enviado tras un largo periodo de inactividad, y sólo si has recibiste mensajes personales en tu ausencia + digest: Sólo enviado tras un largo periodo de inactividad, y sólo si recibiste mensajes personales en tu ausencia discoverable: El directorio del perfil es otra forma en la que tu cuenta puede llegar a un público más amplio email: Se te enviará un correo electrónico de confirmación fields: Podés tener hasta 4 elementos mostrados en una tabla en tu perfil - header: 'PNG, GIF o JPG. Máximo: %{size}. Será subescalado a %{dimensions} pÃxeles.' + header: 'PNG, GIF o JPG. Máximo: %{size}. Será subescalado a %{dimensions} pÃxeles' inbox_url: Copiá la dirección web desde la página principal del relé que querés usar irreversible: Los toots filtrados desaparecerán irreversiblemente, incluso si este filtro es eliminado después - locale: El idioma de la interface de usuario, correos electrónicos y notificaciones PuSH + locale: El idioma de la interface de usuario, correos electrónicos y notificaciones push locked: Requiere que manualmente aprobés seguidores password: Usá al menos 8 caracteres phrase: Se aplicará sin importar las mayúsculas o las advertencias de contenido de un toot scopes: Qué APIs de la aplicación tendrán acceso. Si seleccionás el alcance de nivel más alto, no necesitás seleccionar las individuales. setting_aggregate_reblogs: No mostrar nuevos retoots de los toots que fueron recientemente retooteados (sólo afecta a los retoots recibidos recientemente) setting_default_sensitive: El contenido de medios sensibles está oculto predeterminadamente y puede ser mostrado con un clic - setting_display_media_default: Ocultar medios que están marcados como sensibles + setting_display_media_default: Ocultar medios marcados como sensibles setting_display_media_hide_all: Siempre ocultar todos los medios - setting_display_media_show_all: Siempre mostrar todos los medios que están marcados como sensibles + setting_display_media_show_all: Siempre mostrar todos los medios setting_hide_network: A quiénes seguÃs y tus seguidores no serán mostrados en tu perfil setting_noindex: Afecta a tu perfil público y páginas de estado setting_show_application: La aplicación que usás para tootear se mostrará en la vista detallada de tus toots @@ -56,7 +56,7 @@ es-AR: domain: Este dominio podrá recolectar datos de este servidor, y los datos entrantes serán procesados y archivados email_domain_block: domain: Puede ser el nombre de dominio que aparece en la dirección de correo electrónico, el registro MX hacia el cual resuelve el dominio, o la dirección IP del servidor hacia el cual resuelve ese registro MX. Esto se comprobará en el momento del registro del usuario, y el registro será rechazado. - with_dns_records: Se hará un intento de resolver los registros DNS del dominio dado y los resultados serán también puestos en la lista de desaprobados + with_dns_records: Se hará un intento de resolver los registros DNS del dominio dado y los resultados serán también bloqueados featured_tag: name: 'Puede que quieras usar una de estas:' form_challenge: @@ -64,9 +64,18 @@ es-AR: imports: data: Archivo CSV exportado desde otro servidor de Mastodon invite_request: - text: Esto nos ayudará a revisar tu aplicación + text: Esto nos ayudará a revisar tu solicitud + ip_block: + comment: Opcional. Acordate por qué agregaste esta regla. + expires_in: Las direcciones IP son un recurso finito, a veces se comparten y cambian de personas frecuentemente. Por esta razón, no se recomiendan bloqueos indefinidos de direcciones IP. + ip: Ingresá una dirección IPv4 ó IPv6. Podés bloquear rangos completos usando la sintaxis CIDR. ¡Tené cuidado de no bloquearte vos mismo! + severities: + no_access: Bloquear acceso a todos los recursos + sign_up_requires_approval: Los nuevos registros requerirán tu aprobación + severity: Elegà lo que pasará con las solicitudes desde esta dirección IP sessions: - otp: 'Ingresá el código de autenticación de dos factores generado por la aplicación de tu dispositivo móvil, o usá uno de tus códigos de recuperación:' + otp: 'Ingresá el código de autenticación de dos factores generado por la aplicación en tu dispositivo, o usá uno de tus códigos de recuperación:' + webauthn: Si es una llave USB, asegurate de insertarla y, de ser necesario, tocarla. tag: name: Sólo podés cambiar la capitalización de las letras, por ejemplo, para que sea más legible user: @@ -89,16 +98,17 @@ es-AR: text: Advertencia personalizada type: Acción types: - disable: Deshabilitar inicio de sesión - none: No hacer nada - silence: Silenciar - suspend: Suspender y eliminar de forma irreversible los datos de la cuenta - warning_preset_id: Usar un texto predeterminado + disable: Congelar + none: Enviar una advertencia + sensitive: Sensible + silence: Limitar + suspend: Suspender + warning_preset_id: Usar una advertencia preestablecida announcement: all_day: Evento de todo el dÃa ends_at: Fin del evento scheduled_at: Programar publicación - starts_at: Comienzo del evento + starts_at: Inicio del evento text: Anuncio defaults: autofollow: Invitar para seguir tu cuenta @@ -116,6 +126,7 @@ es-AR: expires_in: Vence después de fields: Metadatos de perfil header: Cabecera + honeypot: "%{label} (no rellenar)" inbox_url: Dirección web de la bandeja de entrada del relé irreversible: Dejar en lugar de ocultar locale: Idioma de la interface @@ -135,6 +146,7 @@ es-AR: setting_default_privacy: Privacidad de toots setting_default_sensitive: Siempre marcar medios como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de eliminar un toot + setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización de medios setting_display_media_default: Predeterminada setting_display_media_hide_all: Ocultar todo @@ -147,7 +159,7 @@ es-AR: setting_system_font_ui: Utilizar la tipografÃa predeterminada del sistema setting_theme: Tema del sitio setting_trends: Mostrar las tendencias de hoy - setting_unfollow_modal: Mostrar diálogo de confirmación antes de dejar de seguir a alguien + setting_unfollow_modal: Mostrar diálogo de confirmación antes de dejar de seguir a una cuenta setting_use_blurhash: Mostrar gradientes coloridos para medios ocultos setting_use_pending_items: Modo lento severity: Severidad @@ -168,16 +180,23 @@ es-AR: comment: Comentar invite_request: text: "¿Por qué querés unirte?" + ip_block: + comment: Comentario + ip: Dirección IP + severities: + no_access: Bloquear acceso + sign_up_requires_approval: Limitar registros + severity: Regla notification_emails: digest: Enviar correos electrónicos compilatorios - favourite: Enviar correo electrónico cuando una cuenta marca como favorito tu estado - follow: Enviar correo electrónico cuando una cuenta te siga - follow_request: Enviar correo electrónico cuando una cuenta solicita seguirte - mention: Enviar correo electrónico cuando una cuenta te mencione - pending_account: Enviar correo electrónico cuando una nueva cuenta necesita revisión - reblog: Enviar correo electrónico cuando una cuenta retootee tu estado - report: Enviar correo electrónico cuando se envÃe un nuevo informe - trending_tag: Enviar correo electrónico cuando una etiqueta no revisada esté en tendencia + favourite: Una cuenta marca tu toot como favorito + follow: Una cuenta te sigue + follow_request: Una cuenta solicita seguirte + mention: Una cuenta te menciona + pending_account: Una nueva cuenta necesita revisión + reblog: Una cuenta retootea tu toot + report: Se envÃa una nueva denuncia + trending_tag: Una etiqueta no revisada está en tendencia tag: listable: Permitir que esta etiqueta aparezca en las búsquedas y en el directorio de perfiles name: Etiqueta @@ -188,4 +207,7 @@ es-AR: required: mark: "*" text: obligatorio + title: + sessions: + webauthn: Usá una de tus llaves de seguridad para iniciar sesión 'yes': Sà diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index bc29918f1ede66ff7256209362dbd584196be8f7..5da47d54a8817bff861c4f12efc988cff980e04a 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -65,8 +65,17 @@ es: data: Archivo CSV exportado desde otra instancia de Mastodon invite_request: text: Esto nos ayudará a revisar su aplicación + ip_block: + comment: Opcional. Recuerda por qué has añadido esta regla. + expires_in: Las direcciones IP son un recurso finito, a veces se comparten y a menudo cambian de manos. Por esta razón, no se recomiendan bloqueos de IP indefinida. + ip: Introduzca una dirección IPv4 o IPv6. Puede bloquear rangos completos usando la sintaxis CIDR. ¡Tenga cuidado de no quedarse fuera! + severities: + no_access: Bloquear acceso a todos los recursos + sign_up_requires_approval: Nuevos registros requerirán su aprobación + severity: Elegir lo que pasará con las peticiones desde esta IP sessions: otp: 'Introduce el código de autenticación de dos factores generado por tu aplicación de teléfono o usa uno de tus códigos de recuperación:' + webauthn: Si es una tecla USB, asegúrese de insertarla y, si es necesario, púlsela. tag: name: Sólo se puede cambiar el cajón de las letras, por ejemplo, para que sea más legible user: @@ -91,6 +100,7 @@ es: types: disable: Deshabilitar none: No hacer nada + sensitive: Sensible silence: Silenciar suspend: Suspender y eliminar de forma irreversible la información de la cuenta warning_preset_id: Usar un aviso predeterminado @@ -116,6 +126,7 @@ es: expires_in: Expirar tras fields: Metadatos de perfil header: Img. cabecera + honeypot: "%{label} (no rellenar)" inbox_url: URL de la entrada de relés irreversible: Dejar en lugar de ocultar locale: Idioma @@ -135,6 +146,7 @@ es: setting_default_privacy: Privacidad de publicaciones setting_default_sensitive: Marcar siempre imágenes como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de borrar un toot + setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización multimedia setting_display_media_default: Por defecto setting_display_media_hide_all: Ocultar todo @@ -168,6 +180,13 @@ es: comment: Comentar invite_request: text: "¿Por qué quiere unirse usted?" + ip_block: + comment: Comentario + ip: IP + severities: + no_access: Bloquear acceso + sign_up_requires_approval: Limitar registros + severity: Regla notification_emails: digest: Enviar resumen de correos electrónicos favourite: Enviar correo electrónico cuando alguien de a favorito en su publicación @@ -188,4 +207,7 @@ es: required: mark: "*" text: necesario + title: + sessions: + webauthn: Utilice una de sus claves de seguridad para iniciar sesión 'yes': Sà diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml index 83f2d206f68e69a96267bfb20641f9f2ed8ba48c..5960c261051c85499297f3b557449a38553c661f 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -65,8 +65,17 @@ fa: data: پروندهٔ CSV برون‌ریخته از دیگر کارساز ماستودون invite_request: text: این برای بررسی درخواست شما به ما Ú©Ù…Ú© خواهد کرد + ip_block: + comment: اختیاری. یادتان بماند چرا این قاعده را Ø§ÙØ²ÙˆØ¯ÛŒØ¯. + expires_in: نشانی‌های آی‌پی، منبعی Ù…ØØ¯ÙˆØ¯Ù†Ø¯. گاهی هم‌رسانی شده Ùˆ اغلب دست‌به‌دست می‌شوند. به این دلیل، مسدودیت‌های مبتنی بر آی‌پی پیشنهاد نمی‌شوند. + ip: یک آی‌پی نکارش Û´ یا Û¶ وارد کنید. می‌توانید تمامی دامنه‌ای را با Ø§Ø³ØªÙØ§Ø¯Ù‡ از ساختار CIDR مسدود کنید. مراقب باشید خودتان را بیرون نیندازید! + severities: + no_access: انسداد دسترسی به تمامی منابع + sign_up_requires_approval: ثبت‌نام‌های جدید، نیازمند تأییدتان خواهند بود + severity: بگزنید با درخواست‌ها از این آی‌پی Ú†Ù‡ شود sessions: otp: 'کد تأیید دومرØÙ„ه‌ای Ú©Ù‡ اپ روی تلÙÙ† شما ساخته را وارد کنید یا یکی از کدهای بازیابی را به کار ببرید:' + webauthn: اگر کلید USB باشد ØŒ از اتصاڵ آن مطمئن شوید و، اگر لازم باشد، به آن ضربه‌ایی بزنید. tag: name: شما تنها می‌توانید بزرگی Ùˆ Ú©ÙˆÚ†Ú©ÛŒ ØØ±ÙˆÙ را تغییر دهید تا مثلاً آن را خواناتر کنید user: @@ -91,6 +100,7 @@ fa: types: disable: ØºÛŒØ±ÙØ¹Ø§Ù„‌کردن none: کاری Ù†Ú©Ù† + sensitive: ØØ³Ø§Ø³ silence: بی‌صدا کردن suspend: تعلیق Ùˆ پاک‌کردن کامل همهٔ اطلاعات ØØ³Ø§Ø¨ warning_preset_id: یک هشدار از پیش‌آماده را به کار ببرید @@ -116,6 +126,7 @@ fa: expires_in: تاریخ انقضا fields: اطلاعات تکمیلی نمایه header: تصویر زمینه + honeypot: "%{label} (پر نکنید)" inbox_url: نشانی صندوق ورودی رله irreversible: به جای پنهان‌سازی، ØØ°Ù Ú©Ù† locale: زبان Ù…ØÛŒØ· کاربری @@ -135,6 +146,7 @@ fa: setting_default_privacy: ØØ±ÛŒÙ… خصوصی نوشته‌ها setting_default_sensitive: همیشه تصاویر را به عنوان ØØ³Ø§Ø³ علامت بزن setting_delete_modal: نمایش پیغام تأیید پیش از پاک کردن یک نوشته + setting_disable_swiping: از کار انداختن ØØ±Ú©Øªâ€ŒÙ‡Ø§ÛŒ کشیدنی setting_display_media: نمایش عکس Ùˆ ویدیو setting_display_media_default: Ù¾ÛŒØ´â€ŒÙØ±Ø¶ setting_display_media_hide_all: Ù†Ù‡ÙØªÙ† همه @@ -168,6 +180,13 @@ fa: comment: ØªÙˆØ¶ÛŒØ invite_request: text: چرا می‌خواهید عضو شوید؟ + ip_block: + comment: ØªÙˆØ¶ÛŒØ + ip: IP + severities: + no_access: بن کردن دسترسی + sign_up_requires_approval: Ù…ØØ¯ÙˆØ¯ کردن ثبت نام‌ها + severity: قانون notification_emails: digest: خلاصه‌کردن چند اعلان در یک ایمیل favourite: وقتی کسی نوشتهٔ شما را پسندید ایمیل Ø¨ÙØ±Ø³Øª @@ -188,4 +207,7 @@ fa: required: mark: "*" text: ضروری + title: + sessions: + webauthn: برای ورود از یکی از کلیدهای امنیتیتان Ø§Ø³ØªÙØ§Ø¯Ù‡ کنید 'yes': بله diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 5bfcae5922473529fd9b69532fe3a032e17ad0df..1b4acc9b9b083e933a033f7a57b1b85db6e3d2e7 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -2,8 +2,18 @@ fi: simple_form: hints: + account_alias: + acct: Määrittele käyttäjän käyttäjänimi@verkkotunnus mistä haluat siirtyä + account_migration: + acct: Määrittele käyttäjän käyttäjänimi@verkkotunnus mihin haluat siirtyä + account_warning_preset: + title: Vapaaehtoinen. Ei näytetä vastaanottajalle admin_account_action: + include_statuses: Käyttäjä näkee mitkä tuuttaukset johtivat toimenpiteeseen tai varoitukseen send_email_notification: Käyttäjä saa selityksen mitä tapahtui hänen tililleen + type_html: Valitse mitä teet käyttäjälle <strong>%{acct}</strong> + announcement: + scheduled_at: Jätä tyhjäksi julkaistaksesi ilmoituksen välittömästi defaults: avatar: PNG, GIF tai JPG. Enintään %{size}. Skaalataan kokoon %{dimensions} px bot: Tämä tili suorittaa enimmäkseen automaattisia toimintoja eikä sitä ehkä valvota @@ -26,12 +36,29 @@ fi: labels: account: fields: + name: Nimike value: Sisältö + account_warning_preset: + title: Otsikko + admin_account_action: + text: Mukautettu varoitus + type: Toimenpide + types: + disable: Poista kirjautuminen käytöstä + none: Älä tee mitään + silence: Hiljennä + suspend: Poista käytöstä ja tuhoa käyttäjätunnuksen tiedot peruuttamattomasti + announcement: + all_day: Koko päivän kestävä tapahtuma + text: Ilmoitus defaults: + autofollow: Kutsu seuraamaan tiliäsi avatar: Profiilikuva bot: Tämä on botti + chosen_languages: Suodata kieliä confirm_new_password: Vahvista uusi salasana confirm_password: Vahvista salasana + context: Suodata konteksteista current_password: Nykyinen salasana data: Tiedot discoverable: Listaa tämä tili hakemistoon @@ -47,32 +74,62 @@ fi: note: Kuvaus otp_attempt: Kaksivaiheisen tunnistuksen koodi password: Salasana + phrase: Avainsana tai lause + setting_advanced_layout: Ota käyttöön edistynyt web käyttöliittymä + setting_aggregate_reblogs: Ryhmitä boostaukset aikajanalla setting_auto_play_gif: Toista GIF-animaatiot automaattisesti setting_boost_modal: Kysy vahvistusta ennen buustausta + setting_crop_images: Rajaa kuvat avaamattomissa tuuttauksissa 16:9 kuvasuhteeseen + setting_default_language: Julkaisujen kieli setting_default_privacy: Julkaisun näkyvyys setting_default_sensitive: Merkitse media aina arkaluontoiseksi setting_delete_modal: Kysy vahvistusta ennen tuuttauksen poistamista + setting_display_media: Median näyttäminen + setting_display_media_default: Oletus + setting_display_media_hide_all: Piilota kaikki + setting_display_media_show_all: Näytä kaikki + setting_hide_network: Piilota verkkosi setting_noindex: Jättäydy pois hakukoneindeksoinnista setting_reduce_motion: Vähennä animaatioiden liikettä + setting_show_application: Näytä sovellus mistä lähetät tuuttauksia setting_system_font_ui: Käytä järjestelmän oletusfonttia setting_theme: Sivuston teema + setting_trends: Näytä päivän trendit setting_unfollow_modal: Kysy vahvistusta, ennen kuin lopetat seuraamisen + setting_use_pending_items: Hidastila severity: Vakavuus + sign_in_token_attempt: Turvakoodi type: Tietojen laji username: Käyttäjänimi username_or_email: Käyttäjänimi tai sähköposti + whole_word: Koko sana + email_domain_block: + with_dns_records: Sisällytä toimialueen MX tietueet ja IP-osoite + featured_tag: + name: Aihetunniste interactions: must_be_follower: Estä ilmoitukset käyttäjiltä, jotka eivät seuraa sinua must_be_following: Estä ilmoitukset käyttäjiltä, joita et seuraa must_be_following_dm: Estä suorat viestit käyttäjiltä, joita et seuraa + invite: + comment: Kommentoi + invite_request: + text: Miksi haluat liittyä? notification_emails: digest: Lähetä koosteviestejä sähköpostitse favourite: Lähetä sähköposti, kun joku tykkää tilastasi follow: Lähetä sähköposti, kun joku seuraa sinua follow_request: Lähetä sähköposti, kun joku pyytää seurata sinua mention: Lähetä sähköposti, kun sinut mainitaan + pending_account: Uusi tili tarvitsee tarkastusta reblog: Lähetä sähköposti, kun joku buustaa julkaisusi + tag: + name: Aihetunniste + trendable: Salli tämän aihetunnisteen näkyä trendeissä + usable: Salli tuuttauksien käyttää tätä aihetunnistetta 'no': Ei + recommended: Suositeltu required: + mark: "*" text: pakollinen tieto 'yes': Kyllä diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml index 01e3f8cceba3a051fee07aeb29b3937b23f1446f..e173dc0dc2f7c7657535c0ed1c7bd255b8229eda 100644 --- a/config/locales/simple_form.fr.yml +++ b/config/locales/simple_form.fr.yml @@ -29,14 +29,14 @@ fr: current_password: Pour des raisons de sécurité, veuillez saisir le mot de passe du compte courant current_username: Pour confirmer, veuillez saisir le nom d'utilisateur du compte courant digest: Uniquement envoyé après une longue période d’inactivité et uniquement si vous avez reçu des messages personnels pendant votre absence - discoverable: L’annuaire des profils est une autre façon pour votre compte d’atteindre une plus grand audience + discoverable: L’annuaire des profils est une autre façon pour votre compte d’atteindre une plus grande audience email: Vous recevrez un courriel de confirmation fields: Vous pouvez avoir jusqu’à 4 éléments affichés en tant que tableau sur votre profil header: Au format PNG, GIF ou JPG. %{size} maximum. Sera réduit à %{dimensions}px inbox_url: Copiez l’URL depuis la page d’accueil du relais que vous souhaitez utiliser irreversible: Les pouets filtrés disparaîtront irrémédiablement, même si le filtre est supprimé plus tard locale: La langue de l’interface, des courriels et des notifications - locked: Vous devrez approuver chaque abonné·e et vos statuts ne s’afficheront qu’à vos abonné·e·s + locked: Nécessite que vous approuviez manuellement chaque abonné·e password: Utilisez au moins 8 caractères phrase: Sera filtré sans que la casse ou l’avertissement sur le contenu du pouet soit pris en compte scopes: À quelles APIs l’application sera autorisée à accéder. Si vous sélectionnez une permission générale, vous n’avez pas besoin de sélectionner les permissions plus précises. @@ -65,8 +65,17 @@ fr: data: Un fichier CSV généré par un autre serveur de Mastodon invite_request: text: Cela nous aidera à considérer votre demande + ip_block: + comment: Optionnel. Pour ne pas oublier pourquoi vous avez ajouté cette règle. + expires_in: Les adresses IP sont une ressource finie, elles sont parfois partagées et changent souvent de mains. Pour cette raison, les blocages d’IP indéfiniment ne sont pas recommandés. + ip: Entrez une adresse IPv4 ou IPv6. Vous pouvez bloquer des plages entières en utilisant la syntaxe CIDR. Faites attention à ne pas vous bloquer vous-même ! + severities: + no_access: Bloquer l’accès à toutes les ressources + sign_up_requires_approval: Les nouvelles inscriptions nécessiteront votre approbation + severity: Choisir ce qui se passera avec les requêtes de cette adresse IP sessions: otp: 'Entrez le code d’authentification à deux facteurs généré par l’application de votre téléphone ou utilisez un de vos codes de récupération :' + webauthn: Si c'est une clé USB, assurez-vous de l'insérer et, si nécessaire, de la tapoter. tag: name: Vous ne pouvez modifier que la casse des lettres, par exemple, pour le rendre plus lisible user: @@ -91,6 +100,7 @@ fr: types: disable: Désactiver none: Ne rien faire + sensitive: Sensible silence: Masquer suspend: Suspendre et supprimer les données du compte de manière irréversible warning_preset_id: Utiliser un modèle d’avertissement @@ -116,6 +126,7 @@ fr: expires_in: Expire après fields: Métadonnées du profil header: Image d’en-tête + honeypot: "%{label} (ne pas remplir)" inbox_url: URL de la boîte de relais irreversible: Supprimer plutôt que masquer locale: Langue de l’interface @@ -135,6 +146,7 @@ fr: setting_default_privacy: Confidentialité des statuts setting_default_sensitive: Toujours marquer les médias comme sensibles setting_delete_modal: Afficher une fenêtre de confirmation avant de supprimer un pouet + setting_disable_swiping: Désactiver les actions par glissement setting_display_media: Affichage des médias setting_display_media_default: Défaut setting_display_media_hide_all: Masquer tout @@ -161,22 +173,29 @@ fr: featured_tag: name: Hashtag interactions: - must_be_follower: Masquer les notifications des personnes qui ne vous suivent pas - must_be_following: Masquer les notifications des personnes que vous ne suivez pas + must_be_follower: Bloquer les notifications des personnes qui ne vous suivent pas + must_be_following: Bloquer les notifications des personnes que vous ne suivez pas must_be_following_dm: Bloquer les messages directs des personnes que vous ne suivez pas invite: comment: Commentaire invite_request: text: Pourquoi voulez-vous vous inscrire ? + ip_block: + comment: Commentaire + ip: IP + severities: + no_access: Bloquer l’accès + sign_up_requires_approval: Limite des inscriptions + severity: Règle notification_emails: digest: Envoyer des courriels récapitulatifs - favourite: Envoyer un courriel lorsque quelqu’un ajoute mes statuts à ses favoris - follow: Envoyer un courriel lorsque quelqu’un me suit - follow_request: Envoyer un courriel lorsque quelqu’un demande à me suivre - mention: Envoyer un courriel lorsque quelqu’un me mentionne + favourite: Quelqu’un ajoute mon pouet à ses favoris + follow: Quelqu’un vient de me suivre + follow_request: Quelqu’un demande à me suivre + mention: Quelqu’un me mentionne pending_account: Nouveau compte en attente d’approbation - reblog: Quelqu’un a partagé votre pouet - report: Envoyer un courriel lorsqu’un nouveau rapport est soumis + reblog: Quelqu’un partage mon pouet + report: Un nouveau rapport est envoyé trending_tag: Un hashtag non approuvé est dans les tendances tag: listable: Autoriser ce hashtag à apparaître dans les recherches et dans l’annuaire des profils @@ -187,5 +206,8 @@ fr: recommended: Recommandé required: mark: "*" - text: Champs requis + text: champs requis + title: + sessions: + webauthn: Utilisez l'une de vos clés de sécurité pour vous connecter 'yes': Oui diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index f2e859acba32fff33514317bb34f50801f646739..799312e33837855094b62e42fac76a00df93cebf 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -56,7 +56,7 @@ gl: domain: Este dominio estará en disposición de obter datos desde este servidor e datos de entrada a el poderán ser procesados e gardados email_domain_block: domain: Esto pode ser o nome de dominio que aparece no enderezo do correo, o rexistro MX que resolve o dominio, ou o IP do servidor que resolve o rexistro MX. Estos confrontaranse contra o rexistro da usuaria e o rexistro será rexeitado. - with_dns_records: Vaise facer un intento de resolver os rexistros DNS propocionados e os resultados tamén irán a lista negra + with_dns_records: Vaise facer un intento de resolver os rexistros DNS proporcionados e os resultados tamén irán a lista de bloqueo featured_tag: name: 'PoderÃas usar algunha destas:' form_challenge: @@ -65,8 +65,17 @@ gl: data: Ficheiro CSV exportado desde outro servidor Mastodon invite_request: text: Esto axudaranos a revisar a tua aplicación + ip_block: + comment: Opcional. Lembrar a razón para engadir esta regra. + expires_in: Os enderezos IP son un recurso finito, a veces son compartidos e cambian de mans con frecuencia. Por esta razón, non se recomendan os bloqueos indefinidos de IPs. + ip: Escribe un enderezo IPv4 ou IPv6. Podes bloquear rangos completos usando a sintaxe CIDR. Ten coidado e non te bloquees a ti mesma! + severities: + no_access: Bloquear acceso a tódolos recursos + sign_up_requires_approval: Os novos rexistros requerirán a túa aprobación + severity: Escolle que acontecerá coas peticións desde este IP sessions: otp: 'Introduce o código do segundo factor creado pola aplicación do teu móbil ou usa un dos códigos de recuperación:' + webauthn: Se é unha chave USB asegúrate de que está conectada e preme o botón. tag: name: Só podes cambiar maiús/minúsculas, por exemplo, mellorar a lexibilidade user: @@ -89,10 +98,11 @@ gl: text: Aviso personalizado type: Acción types: - disable: Desactivar conexión - none: Non facer nada - silence: Acalar - suspend: Suspender e eliminar irreversiblemente datos da conta + disable: Desactivar + none: Enviar un aviso + sensitive: Sensible + silence: Limitar + suspend: Suspender warning_preset_id: Utilizar un aviso preestablecido announcement: all_day: Evento para todo o dÃa @@ -116,6 +126,7 @@ gl: expires_in: Caduca tras fields: Metadatos do perfil header: Cabeceira + honeypot: "%{label} (non completar)" inbox_url: URL da caixa de entrada do repetidor irreversible: Soltar en lugar de agochar locale: Idioma da interface @@ -135,6 +146,7 @@ gl: setting_default_privacy: Privacidade da publicación setting_default_sensitive: Marcar sempre multimedia como sensible setting_delete_modal: Solicitar confirmación antes de eliminar unha mensaxe + setting_disable_swiping: Desactivar opcións de desprazamento setting_display_media: Mostrar multimedia setting_display_media_default: Por omisión setting_display_media_hide_all: Ocultar todo @@ -168,6 +180,13 @@ gl: comment: Comentar invite_request: text: Por que queres unirte? + ip_block: + comment: Comentario + ip: IP + severities: + no_access: Bloquear acceso + sign_up_requires_approval: Limitar o rexistro + severity: Regra notification_emails: digest: Enviar correos con resumos favourite: Enviar un correo cando alguén marca como favorita unha das tuas publicacións @@ -188,4 +207,7 @@ gl: required: mark: "*" text: requerido + title: + sessions: + webauthn: Usa unha das túas chaves de seguridade para conectar 'yes': Si diff --git a/config/locales/simple_form.hr.yml b/config/locales/simple_form.hr.yml index 083343307f6a5f1d504a3cc4fc6fce0a10fc84dc..e8ef7bfbbad58edd025528aafb1c19ce04e0ccd9 100644 --- a/config/locales/simple_form.hr.yml +++ b/config/locales/simple_form.hr.yml @@ -3,39 +3,55 @@ hr: simple_form: hints: defaults: - avatar: PNG, GIF ili JPG. NajviÅ¡e %{size}. Bit će smanjen na %{dimensions}px - header: PNG, GIF ili JPG. NajviÅ¡e %{size}. Bit će smanjen na %{dimensions}px - locked: traži te da ruÄno odobriÅ¡ sljedbenike i postavlja privatnost postova na dostupnu samo sljedbenicima + avatar: PNG, GIF ili JPG. NajviÅ¡e %{size}. Bit će smanjeno na %{dimensions}px + header: PNG, GIF ili JPG. NajviÅ¡e %{size}. Bit će smanjeno na %{dimensions}px + locked: Zahtijeva ruÄno odobravanje pratitelja + setting_display_media_default: Sakrij medijski sadržaj oznaÄen kao osjetljiv + setting_display_media_hide_all: Uvijek sakrij medijski sadržaj + setting_display_media_show_all: Uvijek prikaži medijski sadržaj imports: - data: CSV fajl izvezen iz druge Mastodon instance + data: CSV datoteka izvezena iz drugog Mastodonovog poslužitelja labels: + account_warning_preset: + title: Naslov + admin_account_action: + type: Radnja defaults: confirm_new_password: Potvrdi novu lozinku confirm_password: Potvrdi lozinku current_password: Trenutna lozinka - data: Podaci - display_name: Ime koje ću prikazati - email: E-mail adresa - locale: Jezik - locked: UÄini raÄun privatnim + data: Podatci + display_name: Prikazano ime + email: Adresa e-poÅ¡te + locale: Jezik suÄelja + locked: ZakljuÄaj raÄun new_password: Nova lozinka - otp_attempt: Dvo-faktorski kod + note: Biografija + otp_attempt: Dvofaktorski kôd password: Lozinka - setting_auto_play_gif: Automatski pokreni animirane GIFove - setting_default_privacy: Privatnost posta - type: Tip uvoženja + setting_auto_play_gif: Automatski pokreni animirane GIF-ove + setting_default_privacy: Privatnost objavljivanja + setting_display_media_default: Zadano + setting_display_media_hide_all: Sakrij sve + setting_display_media_show_all: Prikaži sve + setting_system_font_ui: Koristi zadani font sustava + setting_theme: Tema stranice + type: Tip uvoza username: KorisniÄko ime interactions: - must_be_follower: Blokiraj notifikacije onih koji me ne slijede - must_be_following: Blokiraj notifikacije ljudi koje ne slijedim + must_be_follower: Blokiraj obavijesti korisnika koji me ne prate + must_be_following: Blokiraj obavijesti korisnika koje ne pratim notification_emails: - digest: Å alji mi e-mailove s notifikacijama - favourite: PoÅ¡alji mi e-mail kad netko lajka moj status - follow: PoÅ¡alji mi e-mail kad me netko poÄne slijediti - follow_request: PoÅ¡alji mi e-mail kad mi netko poÅ¡alje zahtjev da me želi slijediti - mention: PoÅ¡alji mi e-mail kad me netko spomene - reblog: PoÅ¡alji mi e-mail kad netko rebloga moj status + digest: Å alji e-poÅ¡tu sa sažetkom obavijesti + favourite: Netko oznaÄi VaÅ¡ status favoritom + follow: Netko Vas poÄinje pratiti + follow_request: Netko zatraži da Vas prati + mention: Netko Vas spomene + reblog: Netko boosta VaÅ¡ status + tag: + name: Hashtag 'no': Ne required: - text: traženo + mark: "*" + text: obavezno 'yes': Da diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index 0b164c5b652ba0c0b0d8e660d3a303d4f807fa0d..d5e82ecb26dfdb38b817426b537e41fa39ecd7fe 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -65,8 +65,17 @@ hu: data: Egy másik Mastodon szerverrÅ‘l exportált CSV fájl invite_request: text: Ez segÃt nekünk átnézni a jelentkezésedet + ip_block: + comment: Opcionális. EmlékeztetÅ‘, hogy miért is vetted fel ezt a szabályt. + expires_in: Az IP cÃmek korlátos erÅ‘források, ezért néha meg vannak osztva és gyakran gazdát is cserélnek. Ezért a korlátlan IP tiltások használatát nem javasoljuk. + ip: Ãrj be egy IPv4 vagy IPv6 cÃmet. A CIDR formátum használatával teljes tartományokat tilthatsz ki. Légy óvatos, hogy magadat véletlenül se zárd ki! + severities: + no_access: Elérés tiltása minden erÅ‘forráshoz + sign_up_requires_approval: Új regisztrációk csak a jóváhagyásoddal történhetnek majd meg + severity: Válaszd ki, mi történjen a kérésekkel errÅ‘l az IP-rÅ‘l sessions: otp: 'Add meg a telefonodon generált kétlépcsÅ‘s azonosÃtó kódodat vagy használd az egyik tartalék bejelentkezÅ‘ kódot:' + webauthn: Ha ez egy USB kulcs, ellenÅ‘rizd, hogy csatlakoztattad és ha szükséges, aktiváltad is. tag: name: Csak a kis/nagybetűséget változtathatod meg, pl. hogy olvashatóbb legyen user: @@ -91,6 +100,7 @@ hu: types: disable: Letiltás none: Ne csinálj semmit + sensitive: SzenzitÃv silence: ElnémÃtás suspend: Fiók felfüggesztése, adatok törlése visszaállÃthatatlanul warning_preset_id: Figyelmeztetés használata @@ -116,6 +126,7 @@ hu: expires_in: Elévül fields: Profil metaadatok header: Fejléc + honeypot: "%{label} (ne töltsd ki)" inbox_url: Relé inbox-hoz tartozó URL irreversible: Eldobás elrejtés helyett locale: Felhasználói felület nyelve @@ -135,6 +146,7 @@ hu: setting_default_privacy: Tülkök alapértelmezett láthatósága setting_default_sensitive: Minden médiafájl megjelölése szenzitÃvként setting_delete_modal: MegerÅ‘sÃtés kérése tülk törlése elÅ‘tt + setting_disable_swiping: Elhúzás művelet kikapcsolása setting_display_media: Média megjelenÃtése setting_display_media_default: Alapértelmezés setting_display_media_hide_all: Mindent elrejt @@ -168,6 +180,13 @@ hu: comment: Hozzászólás invite_request: text: Miért akarsz csatlakozni? + ip_block: + comment: Megjegyzés + ip: IP + severities: + no_access: Elérés letiltása + sign_up_requires_approval: Regisztrációk korlátozása + severity: Szabály notification_emails: digest: Összevont e-mailek küldése favourite: E-mail küldése, amikor valaki kedvencnek jelöli a tülködet @@ -188,4 +207,7 @@ hu: required: mark: "*" text: kötelezÅ‘ + title: + sessions: + webauthn: Használd valamelyik biztonsági kulcsodat a bejelentkezéshez 'yes': Igen diff --git a/config/locales/simple_form.hy.yml b/config/locales/simple_form.hy.yml index cd73ee679261f594c2d644c786b61aa1789d295f..ff4bfcaab7385bc812526659315a7291f4be36cf 100644 --- a/config/locales/simple_form.hy.yml +++ b/config/locales/simple_form.hy.yml @@ -12,31 +12,202 @@ hy: admin_account_action: include_statuses: Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¨ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¡ Õ¸Ö€ Õ©Õ©Õ¥Ö€Õ¶ Õ¥Õ¶ Õ¡Õ¼Õ¡Õ»Õ¡ÖÖ€Õ¥Õ¬ Õ´Õ¸Õ¤Õ¥Ö€Õ¡ÖÕ«Õ¡ÕµÕ« Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¯Õ¡Õ´ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´Ö‰ send_email_notification: Ö…Õ£Õ¿Õ¡Õ¿Õ§Ö€Õ¨ Õ¯Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õµ Õ¢Õ¡ÖÕ¡Õ¿Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¡ÕµÕ¶ Õ´Õ¡Õ½Õ«Õ¶ Õ©Õ§ Õ«Õ¶Õ¹ Õ§ ÕºÕ¡Õ¿Õ¡Õ°Õ¥Õ¬ Õ«Ö€Õ¥Õ¶Ö Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ°Õ¥Õ¿Ö‰ + text_html: Պայմանական․ Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Ô¹Õ¸Ö‚Õ©Õ« Õ·Õ¡Ö€Õ¡Õ¤Õ¡Õ½Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ <a href="%{path}">Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¶Õ¸Õ² Õ¶Õ¡ÕÕ¡Õ¤Õ«Ö€Õ¶Õ¥Ö€</a> ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ ÕÕ¶Õ¡ÕµÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ + type_html: Ô¸Õ¶Õ¿Ö€Õ«Ö€ Õ«Õ¶Õ¹ Õ¡Õ¶Õ¥Õ¬ <strong>%{acct}</strong>Õ« Õ°Õ¥Õ¿Ö‰ + warning_preset_id: Պայմանական․ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¡Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¿Õ¥Ö„Õ½Õ¿ Õ¶Õ¡ÕÕ¤Õ«Ö€Õ« Õ¾Õ¥Ö€Õ»Õ¸Ö‚Õ´ + announcement: + all_day: ÕŽÕ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚Ö ÕµÕ¥Õ¿Õ¸Õµ, ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡ÖÕ¸ÕµÖÕ«Ö Õ´Õ«Õ¡ÕµÕ¶ Õ¡Õ´Õ½Õ¡Õ©Õ«Ö‚Õ¨ ÖÕ¸ÕµÖ Õ¯Õ¨ Õ¿Ö€Õ¸Ö‚Õ« + ends_at: Պայմանական․ Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶ Õ¡Ö‚Õ¿Ö…Õ´Õ¡Õ¿ Õ¯Õ¨ Õ°Õ¡Õ¶Õ¸Ö‚Õ« Õ¡ÕµÕ½ ÕªÕ¡Õ´Õ«Õ¶ + scheduled_at: ÔµÕ©Õ§ Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ Õ©Õ¸Õ²Õ¶Õ¥Õ½ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ´Õ«Õ¡Õ¶Õ£Õ¡Õ´Õ«Ö Õ¯Õ¨ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¸Ö‚Õ« + starts_at: Պայմանական․ Õ¡ÕµÕ¶ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¤ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ¡Õ® Õ§ ÕµÕ½Õ¿Õ¡Õ¯ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡ÖÕ¸ÕµÖÕ¸Õ¾ + text: Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ©Õ©Õ« Õ·Õ¡Ö€Õ¡Õ¤Õ¡Õ½Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨Ö‰ Ô½Õ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„, Õ¥Õ²Õ«Ö€ ÕÕ¥Õ¬Õ¡Õ´Õ«Õ¿ ÕµÕ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Ö„Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ«Õ½, Õ¡ÕµÕ¶ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ§ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¶ + defaults: + autofollow: Õ€Ö€Õ¡Ö‚Õ§Ö€Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¸Õ² Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¨ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¶ Ö„Õ¥Õ¦ + avatar: PNG, GIF Õ¯Õ¡Õ´ JPGÖ‰ Ô±Õ¼Õ¡Ö‚Õ¥Õ¬Õ¡Õ£Õ¸ÕµÕ¶Õ¨Õ %{size}Ö‰ Ô¿Õ¨ ÖƒÕ¸Ö„Ö€Õ¡ÖÕ¸Ö‚Õ« Õ´Õ«Õ¶Õ¹Õ¥Ö‚ %{dimensions} + bot: Ô±ÕµÕ½ Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¸Ö‚Õ´ Õ§ Õ¡Ö‚Õ¿Ö…Õ´Õ¡Õ¿Õ¡ÖÕ¸Ö‚Õ¡Õ® Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ Õ£Õ¸Ö‚ÖÕ§ Õ¹Õ« Õ¾Õ¥Ö€Õ¡ÕµÕ½Õ¯Õ¸Ö‚Õ¸Ö‚Õ´ + context: Õ„Õ§Õ¯ Õ¯Õ¡Õ´ Õ´Õ« Ö„Õ¡Õ¶Õ« Õ¯Õ¸Õ¶Õ¿Õ¥Ö„Õ½Õ¿Õ¶Õ¥Ö€, Õ¸Ö€Õ¿Õ¥Õ² ÕºÕ§Õ¿Ö„ Õ§ Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ« Õ¦Õ¿Õ«Õ¹ + current_password: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¶Õ¯Õ¡Õ¿Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Ö Õ¥Õ¬Õ¶Õ¥Õ¬Õ¸Õ¾, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Õ¬ Õ¿Õ¸Ö‚Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ®Õ¡Õ®Õ¯Õ¡Õ£Õ«Ö€Õ¨ + current_username: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Õ¬ Õ¿Õ¸Ö‚Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ + digest: ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ ÕºÕ¡Õ½Õ«Ö‚Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¥Ö€Õ¯Õ¡Ö€ Õ·Ö€Õ»Õ¡Õ¶Õ«Ö ÕµÕ¥Õ¿Õ¸Õµ Õ¥Ö‚ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¶ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©Õ¥Õ¡Õ¶Õ¤ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¸Ö€Õ¥Ö‚Õ§ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ Õ¥Õ½ Õ½Õ¿Õ¡ÖÕ¥Õ¬ + discoverable: Ô·Õ»Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶Õ¶ Õ¡ÕµÕ¬ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯ Õ§ Õ°Õ¡Õ·Õ«Ö‚Õ¤ Õ¬Õ¡ÕµÕ¶ Õ·Ö€Õ»Õ¡Õ¶Õ¡Õ¯Õ¶Õ¥Ö€Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¸Ö‚ + email: Õ”Õ¥Õ¦ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ«Õ´Õ¡Õ¯ + fields: Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¸Ö‚Õ¶Õ¥Õ¶Õ¡Õ¬ Õ´Õ«Õ¶Õ¹Õ¥Ö‚ 4 Õ¯Õ§Õ¿ Õ°Õ¡Õ·Õ¸Ö‚Õ«Õ¤ Õ¡Õ²Õ«Ö‚Õ½Õ¡Õ¯Õ¸Ö‚Õ´ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬Õ¸Ö‚ + header: PNG, GIF Õ¯Õ¡Õ´ JPGÖ‰ Ô±Õ¼Õ¡Ö‚Õ¥Õ¬Õ¡Õ£Õ¸ÕµÕ¶Õ¨Õ %{size}Ö‰ Ô¿Õ¨ ÖƒÕ¸Ö„Ö€Õ¡ÖÕ¸Ö‚Õ« Õ´Õ«Õ¶Õ¹Õ¥Ö‚ %{dimensions} + inbox_url: ÕŠÕ¡Õ¿Õ³Õ§Õ¶Õ«Ö€ URL Õ¡ÕµÕ¶ Õ·Õ¥Ö€Õ¿Õ« Õ¤Õ«Õ´Õ¥Ö€Õ¥Õ½Õ«Ö, Õ¸Ö€Õ¨ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ + irreversible: Ô¶Õ¿Õ¸Ö‚Õ¡Õ® Õ©Õ©Õ¥Ö€Õ¨ Õ¯Õ¸Ö€Õ¹Õ¥Õ¬Õ¸Ö‚ Õ¥Õ¶ Õ¡Õ¶Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬Õ«Ö…Ö€Õ§Õ¶, Õ¶Õ¸ÕµÕ¶Õ«Õ½Õ¯ Õ¥Õ©Õ§ Õ¦Õ¿Õ«Õ¹Õ¨ ÕµÕ¥Õ¿Õ¸Õµ Õ°Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ½ + locale: Ô»Õ¶Õ¿Õ¥Ö€Ö†Õ¥ÕµÕ½Õ« Õ¬Õ¥Õ¦Õ¸Ö‚Õ¶, Õ§Õ¬. Õ¶Õ¡Õ´Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ Õ¥Ö‚ push Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + locked: Ô±Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ¯Õ¨ Õ¬Õ«Õ¶Õ« Õ±Õ¥Õ¼Ö„Õ¸Õ¾ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Õ¶ + password: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ Õ¡Õ¼Õ¶Õ¸Ö‚Õ¡Õ¦Õ¶ 8 Õ¶Õ«Õ· + phrase: Ô¿Õ¨ Õ°Õ¡Õ´Õ¨Õ¶Õ¯Õ¶Õ« Õ¡Õ¶Õ¯Õ¡Õ Õ¿Õ¥Ö„Õ½Õ¿Õ« Õ±Õ¥Ö‚Õ«Ö Õ¯Õ¡Õ´ Õ©Õ©Õ« Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¶Õ¸Õ² Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ«Ö + scopes: ÕˆÖ€ APIÖŠÕ«Õ¶ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¶ Õ¸Ö‚Õ¶Õ« Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶Ö‰ ÔµÕ©Õ§ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ¥Õ½ Õ¢Õ¡Ö€Õ±Ö€ Õ´Õ¡Õ¯Õ¡Ö€Õ¤Õ¡Õ¯Õ« Õ¤Õ¡Õ·Õ¿, Õ¡ÕºÕ¡ Õ¡Õ¶Õ°Õ¡Õ¿Õ¡Õ¯Õ¡Õ¶ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Ö€Õ«Ö„ Õ¹Õ¯Õ¡ÕµÖ‰ + setting_aggregate_reblogs: Õ‰ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶ Õ¡ÕµÕ¶ Õ©Õ©Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€, Õ¸Ö€Õ¸Õ¶Ö„ Ö„Õ«Õ¹ Õ¡Õ¼Õ¡Õ» Õ¡Ö€Õ¤Õ§Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ¥Õ¬ Õ¥Õ¶(Õ¾Õ¥Ö€Õ¡Õ¢Õ¥Ö€Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¡ÕµÕ¶ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«Õ¶) + setting_default_sensitive: Ô¿Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¬Õ¼Õ¥Õ¬Õ¥Õ¡ÕµÕ¶ ÖƒÕ¡Õ¯ Õ§ Õ¥Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¢Õ¡ÖÕ¸Ö‚Õ¥Õ¬ Õ½Õ¥Õ²Õ´Õ¥Õ¬Õ¸Õ¾ + setting_display_media_default: Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ + setting_display_media_hide_all: ÔµÖ€Õ¢Õ¥Ö„ Õ´Õ¥Õ¤Õ«Õ¡ ÖÕ¸ÕµÖ Õ¹Õ¿Õ¡Õ¬ + setting_display_media_show_all: Õ„Õ¥Õ¤Õ«Õ¡ Õ´Õ«Õ·Õ¿ ÖÕ¸ÕµÖ Õ¿Õ¡Õ¬ + setting_hide_network: ÕˆÖ‚Ö€Õ«Õ·Õ¶Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Õµ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ±Õ¥Õ¦ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Õ²Õ¶Õ¥Ö€Õ«Õ¶ Õ¥Ö‚ Õ©Õ¥ Õ¸Ö‚Õ´ Õ§Ö„ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ Õ¤Õ¸Ö‚Ö„ + setting_noindex: Ô±Õ¦Õ¤Õ¸Ö‚Õ´ Õ§ Ö„Õ¸ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¥Ö‚ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ§Õ»Õ« Õ¾Ö€Õ¡Õµ + setting_show_application: Ô¹Õ¸Ö‚Õ© Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¯Õ¥Ö€Õ¥Ö‚Õ¡Õµ Õ©Õ§ Õ¸Ö€ Õ®Ö€Õ¡Õ£Ö€Õ¸Õ¾ Õ¥Õ½ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¥Õ¬ Õ¡ÕµÕ¶ + setting_use_blurhash: Ô¿Õ¿Õ¸Ö€Õ¶Õ¥Ö€Õ¨ Õ°Õ«Õ´Õ¶Õ¸Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ©Õ¡Ö„ÖÕ¸Ö‚Õ¡Õ® Õ¾Õ«Õ¦Õ¸Ö‚Õ¡Õ¬Õ« Õ¾Ö€Õ¡ÕµÕ ÕÕ¡Õ´Ö€Õ¥ÖÕ¶Õ¥Õ¬Õ¸Õ¾ Õ¤Õ¥Õ¿Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ + setting_use_pending_items: Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ°Õ¸Õ½Ö„Õ« Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¿Õ¿Õ¸Õ« Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´Õ Õ¡Ö‚Õ¿Ö…Õ´Õ¡Õ¿ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ¸Õ² Õ°Õ¸Õ½Ö„Õ« ÖƒÕ¸ÕÕ¡Ö€Õ§Õ¶ + username: Õ”Õ¸ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ ÕºÕ§Õ¿Ö„ Õ§ Õ¥Õ¦Õ¡Õ¯Õ« Õ¬Õ«Õ¶Õ« %{domain}-Õ¸Ö‚Õ´Ö‰ + whole_word: ÔµÕ©Õ§ Õ¢Õ¡Õ¶Õ¡Õ¬Õ« Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ´ Õ¡Ö€Õ¿Õ¡ÕµÕ¡ÕµÕ¿Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¢Õ¢Õ¥Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¶Õ«Õ·Õ¥Ö€ Õ¥Ö‚ Õ©Õ¸Ö‚Õ¥Ö€, Õ¡ÕºÕ¡ Õ¡ÕµÕ¶ Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ§ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ¢Õ¡Õ¼Õ« Õ°Õ¥Õ¿ Õ°Õ¡Õ´Õ¨Õ¶Õ¯Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¤Õ§ÕºÖ„Õ¸Ö‚Õ´ Õ´Õ«Õ¡ÕµÕ¶ + domain_allow: + domain: Ô±ÕµÕ½ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ½Õ¿Õ¡Õ¶Õ¡Õ¬ Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€ Õ¡ÕµÕ½ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ«Ö Õ¥Ö‚ Õ½Õ¿Õ¡ÖÕ¸Ö‚Õ¸Õ² Õ¿Õ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¥Õ¬ Õ¥Ö‚ ÕºÕ¡Õ°Õ¸Ö‚Õ¥Õ¬ + email_domain_block: + domain: ÕÕ¡ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« Õ¡Õ¶Õ¸Ö‚Õ¶, Õ¸Ö€Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ´ Õ§ էլ․ Õ°Õ¡Õ½ÖÕ§Õ¶, MX Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´, Õ¸Ö€Õ«Õ¶ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ¨ ÕºÕ¡Õ¿Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ§, Õ¯Õ¡Õ´ MX Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« IPÖ‰ Ô´Ö€Õ¡Õ¶Ö„ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ£Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ ÕºÕ¡Õ°Õ«Õ¶ Õ¥Ö‚ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¨ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ§Ö‰ + with_dns_records: Ô±ÕµÕ½ Õ¿Õ«Ö€Õ¸ÕµÕ©Õ« DNS Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¨ Õ¿Õ¡Ö€Ö€Õ¡Õ¬Õ¸Ö‚Õ®Õ¸Ö‚Õ¥Õ¶ Õ¥Ö‚ Õ¡Ö€Õ¤Õ«Ö‚Õ¶Ö„Õ¶Õ¥Ö€Õ¨ Õ¶Õ¸ÕµÕ¶ÕºÕ§Õ½ Õ¯Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¶ Õ½Õ¥Ö‚ ÖÕ¸Ö‚ÖÕ¡Õ¯ + featured_tag: + name: Ô³Õ¸Ö‚ÖÕ§ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¡Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ½Ö€Õ¡Õ¶ÖÕ«Ö Õ´Õ§Õ¯Õ¨â€¤ + form_challenge: + current_password: Õ„Õ¸Ö‚Õ¿Ö„ Õ¥Õ½ Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¿Õ¡Ö€Õ¡Õ®Ö„ + imports: + data: CSV Ö†Õ¡ÕµÕ¬Õ¨ Õ¶Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ¸Ö‚Õ¥Õ¬ Õ§ Õ„Õ¡Õ½Õ¿Õ¸Õ¤Õ¸Õ¶Õ« Õ¡ÕµÕ¬ Õ½Õ¥Ö€Õ¸Ö‚Õ¥Ö€Õ«Ö + invite_request: + text: ÕÕ¡ Õ¯Ö…Õ£Õ¶Õ« Õ´Õ¥Õ¦ Õ½Õ¿Õ¸Ö‚Õ£Õ¥Õ¬ Ö„Õ¸ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ¨ + ip_block: + comment: Պայմանական․ Õ…Õ«Õ·Õ«Ö€ Õ«Õ¶Õ¹Õ¸Ö‚ Õ¥Õ½ Õ¡Ö‚Õ¥Õ¬Õ¡ÖÖ€Õ¥Õ¬ Õ¡ÕµÕ½ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¨Ö‰ + expires_in: IP Õ°Õ¡Õ½ÖÕ§Õ¶Õ¥Ö€Õ¨ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯ Õ¥Õ¶, Õ¤Ö€Õ¡Õ¶Ö„ Õ¥Ö€Õ¢Õ¥Õ´Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Õ¸Ö‚Ö€ Õ¯Õ¡Õ´ Õ¡Õ¶ÖÕ¶Õ¸Ö‚Õ´ Õ±Õ¥Õ¼Ö„Õ«Ö Õ±Õ¥Õ¼Ö„Ö‰ Ô±ÕµÕ¤ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾ ÕÕ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¹Õ« Õ¿Ö€Ö‚Õ¸Ö‚Õ´ IP-Õ¶Õ¥Ö€Õ« Õ¡Õ¶ÕªÕ¡Õ´Õ¯Õ¥Õ¿ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ¨Ö‰ + ip: Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ§Ö„ IPv4 Õ¯Õ¡Õ´ IPv6 Õ°Õ¡Õ½ÖÕ§Õ¶Ö‰ Õ†Õ¡Ö‡ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ½ÖÕ§Õ¶Õ¥Ö€Õ« Õ´Õ«Õ»Õ¡Õ¯Õ¡ÕµÖ„Õ¥Ö€ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Õ¾ CIDR Õ½Õ«Õ¶Õ¿Õ¡Ö„Õ½Õ¨Ö‰ Ô¶Õ£Õ¸ÕµÕ· Õ¥Õ²Õ«Ö€Õ Õ«Õ¶Ö„Õ¤ Ö„Õ¥Õ¦ Õ¹Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ½Ö‰ + severities: + no_access: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ«Ö€ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¨ Õ¢Õ¸Õ¬Õ¸Ö€ ÕºÕ¡Õ·Õ¡Ö€Õ¶Õ¥Ö€Õ«Õ¶Ö‰ + sign_up_requires_approval: Õ†Õ¸Ö€ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¨ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¶ Ö„Õ¸ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´Õ¨ + severity: Ô¸Õ¶Õ¿Ö€Õ«Ö€, Õ©Õ§ Õ«Õ¶Õ¹ Õ¯Õ¡Ö€Õ¸Õ² Õ§ ÕºÕ¡Õ¿Õ¡Õ°Õ¥Õ¬ Õ¡ÕµÕ½ IPÖŠÕ«Ö Õ¥Õ¯Õ¸Õ² ÕµÕ¡ÕµÕ¿Õ¥Ö€Õ« Õ°Õ¥Õ¿ + sessions: + otp: Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ¥Ö€Õ¯Ö„Õ¡ÕµÕ¬ Õ¶Õ¸ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ¯Õ¸Õ¤Õ¨, Õ¸Ö€Õ¨ Õ£Õ¥Õ¶Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ¥Õ½ Õ¥Õ½ Ö„Õ¸ Õ¢Õ»Õ»Õ¡ÕµÕ«Õ¶ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®Õ« Ö…Õ£Õ¶Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ Õ¯Õ¡Õ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ Õ¡ÕµÕ½ Õ¯Õ¸Õ¤Õ¥Ö€Õ«Ö Õ¯Õ§Õ¯Õ¨Õ + webauthn: ÔµÕ©Õ§ Õ½Õ¡ USB Õ§Õ Õ¾Õ½Õ¿Õ¡Õ° Õ¥Õ²Õ«Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Õ¡ÕµÕ¶ Õ¥Ö‚ Õ¥Õ©Õ§ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§Õ Õ©Õ¡ÖƒÕ¡Õ°Õ¡Ö€Õ¥Õ¬Ö‰ + tag: + name: Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ«Õ¡ÕµÕ¶ ÖƒÕ¸ÕÕ¥Õ¬ Õ¿Õ¡Õ¼Õ¥Ö€Õ« Õ±Õ¥Ö‚Õ¨, Ö…Ö€Õ«Õ¶Õ¡Õ¯, Õ¡ÕµÕ¶ Õ¡Ö‚Õ¥Õ¬Õ« Õ¨Õ¶Õ©Õ¥Õ¼Õ¶Õ¥Õ¬Õ« Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ + user: + chosen_languages: Õ†Õ·Õ¸Ö‚Õ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ Õ¯Õ¥Ö€Õ¥Ö‚Õ¡Õµ Õ´Õ«Õ¡ÕµÕ¶ Õ¨Õ¶Õ¿Ö€Õ¸Ö‚Õ¡Õ® Õ¬Õ¥Õ¦Õ¸Ö‚Õ¸Õ¾ Õ©Õ¸Ö‚Õ©Õ¥Ö€Õ¨ labels: account: fields: name: ÕŠÕ«Õ¿Õ¡Õ¯ value: ÕŠÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ + account_alias: + acct: Õ€Õ«Õ¶ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¸Ö‚Õ´ + account_migration: + acct: Õ†Õ¸Ö€ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¸Ö‚Õ´ account_warning_preset: + text: Õ†Õ¡ÕÕ¡Õ¤Ö€Õ¸Ö‚Õ¡Õ® Õ¿Õ¥Ö„Õ½Õ¿ title: ÕŽÕ¥Ö€Õ¶Õ¡Õ£Õ«Ö€ admin_account_action: + include_statuses: Õ†Õ¥Ö€Õ¡Õ¼Õ¥Õ¬ Õ¢Õ¸Õ²Õ¸Ö„Õ¡Ö€Õ¯Õ¸Ö‚Õ¡Õ® Õ©Õ©Õ¥Ö€Õ¨ Õ«Õ´Õ¡Õ¯Õ¸Ö‚Õ´ + send_email_notification: ÕÕ¥Õ²Õ¥Õ¯Õ¡ÖÕ¶Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨ Õ«Õ´Õ¡Õ¯Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ + text: Õ†Õ¡ÕÕ¡Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´ type: Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ types: + disable: Õ“Õ¡Õ¯Õ¥Õ¬ Õ´Õ¸Ö‚Õ¿Ö„Õ¨ none: ÕˆÕ¹Õ«Õ¶Õ¹ Õ¹Õ¡Õ¶Õ¥Õ¬ + sensitive: Ô¶Õ£Õ¡ÕµÕ¸Ö‚Õ¶ silence: Ô¼Õ¸Ö‚Õ¼ + suspend: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¥Ö‚ Õ¡Õ¶Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Ö€Õ± Õ»Õ¶Õ»Õ¥Õ¬ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ«Õ¶Ö†Õ¸Ö€Õ´Õ¡ÖÕ«Õ¡Õ¶ + warning_preset_id: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¶Õ¸Õ² Õ¶Õ¡ÕÕ¡Õ¤Õ«Ö€ + announcement: + all_day: Õ•Ö€Õ¸Ö‚Õ¡Õµ Õ«Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + ends_at: Ô»Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¡Ö‚Õ¡Ö€Õ¿ + scheduled_at: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ´Õ¡Õ¶ Ö…Ö€Õ¡ÖÕ¸ÕµÖ + starts_at: Ô»Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ½Õ¯Õ«Õ¦Õ¢ + text: Õ…Õ¡ÕµÕ¿Õ¡Ö€Õ¡Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶ defaults: + autofollow: Õ€Ö€Õ¡Ö‚Õ«Ö€Õ¥Õ¬ Õ§Õ»Õ«Õ¤ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ + avatar: Ô±Ö‚Õ¡Õ¿Õ¡Ö€ + bot: ÕÕ¡ Õ¢Ö…Õ¿Õ« Õ°Õ¡Õ·Õ«Ö‚ Õ§ + chosen_languages: Ô¶Õ¿Õ¥Õ¬ Õ¬Õ¥Õ¦Õ¸Ö‚Õ¶Õ¥Ö€Õ¨ + confirm_new_password: Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¶Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ + confirm_password: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´ + context: Ô¶Õ¿Õ¥Õ¬ Õ¯Õ¸Õ¶Õ¿Õ¥Ö„Õ½Õ¿Õ¶Õ¥Ö€Õ¨ + current_password: Õ†Õ¥Ö€Õ¯Õ¡ÕµÕ«Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ + data: ÕÕ¸Ö‚Õ¥Õ¡Õ¬Õ¶Õ¥Ö€ + discoverable: Ô±Ö‚Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Ö„Õ¸Ö‚Õ´ + display_name: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ¸Õ² Õ¡Õ¶Õ¸Ö‚Õ¶ + email: Էլ․ Õ°Õ¡Õ½ÖÕ§ + expires_in: ÕÕºÕ¡Õ¼Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ + fields: Õ€Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¥Õ¿Õ¡Õ¤Õ¡Õ¿Õ¡ header: ÕŽÕ¥Ö€Õ¶Õ¡Õ£Õ«Ö€ + honeypot: "%{label} (Õ¹Õ¬Ö€Õ¡ÖÕ¶Õ¥Õ¬)" + inbox_url: Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ´Õ¡Õ¶ Õ·Õ¥Ö€Õ¿Õ« URL + irreversible: Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬Õ¸Ö‚ ÖƒÕ¸ÕÕ¡Ö€Õ§Õ¶ Õ»Õ¶Õ»Õ¥Õ¬ + locale: Ô»Õ¶Õ¿Õ¥Ö€Ö†Õ¥ÕµÕ½Õ« Õ¬Õ¥Õ¦Õ¸Ö‚ + locked: Õ“Õ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Ö‚Õ¨ + max_uses: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ Õ¡Õ¼Õ¡Ö‚Õ¥Õ¬Õ¡Õ£Õ¸ÕµÕ¶ Ö„Õ¡Õ¶Õ¡Õ¯ + new_password: Õ†Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ note: Ô²Õ«Õ¸ + otp_attempt: 2F Õ¯Õ¸Õ¤ password: Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ + phrase: Õ€Õ«Õ´Õ¶Õ¡Õ¢Õ¡Õ¼ Õ¯Õ¡Õ´ Õ¡Ö€Õ¿Õ¡ÕµÕ¡ÕµÕ¿Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + setting_advanced_layout: Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¸Ö‚Õ¡Õ® Õ¾Õ¥Õ¢ Õ«Õ¶Õ¿Õ¥Ö€Ö†Õ¥ÕµÕ½ + setting_aggregate_reblogs: ÕÕ¡Ö€Õ®Õ¡Õ®Õ¶Õ¥Ö€Õ¨ ÕÕ´Õ¢Õ¡Ö‚Õ¸Ö€Õ¥Õ¬ Õ°Õ¸Õ½Ö„Õ¸Ö‚Õ´ + setting_auto_play_gif: Ô±Ö‚Õ¿Õ¸Õ´Õ¡Õ¿ Õ´Õ¥Õ¯Õ¶Õ¡Ö€Õ¯Õ¥Õ¬ GIFs Õ¡Õ¶Õ«Õ´Õ¡ÖÕ«Õ¡Õ¶Õ¥Ö€Õ¨ + setting_boost_modal: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨ Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» + setting_crop_images: Õ‘Õ¸ÕµÖ Õ¿Õ¡Õ¬ Õ©Õ¸Ö‚Õ©Õ« Õ¶Õ¯Õ¡Ö€Õ¨ 16x9 Õ°Õ¡Õ´Õ¡Õ´Õ¡Õ½Õ¶Õ¸Ö‚Õ©Õ¥Õ¡Õ´Õ¢ + setting_default_language: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ´Õ¡Õ¶ Õ¬Õ¥Õ¦Õ¸Ö‚ + setting_default_privacy: Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ´Õ¡Õ¶ Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©Õ«Ö‚Õ¶ + setting_default_sensitive: Õ„Õ«Õ·Õ¿ Õ¶Õ·Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡Õ¶ Õ¸Ö€ÕºÕ§Õ½ Õ¤Õ«Ö‚Ö€Õ¡Õ¦Õ£Õ¡Ö + setting_delete_modal: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨ Õ»Õ¶Õ»Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» + setting_disable_swiping: Ô¿Õ¡Õ½Õ¥ÖÕ¶Õ¥Õ¬ Õ½Õ¡Õ°Õ¸Õ² Õ·Õ¡Ö€ÕªÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + setting_display_media: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ´Õ¥Õ¤Õ«Õ¡ + setting_display_media_default: Ô¼Õ¼Õ¥Õ¬Õ¥Õ¡ÕµÕ¶ + setting_display_media_hide_all: Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨ + setting_display_media_show_all: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ¨ + setting_expand_spoilers: Õ„Õ«Õ·Õ¿ Õ¢Õ¡ÖÕ¥Õ¬ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ´Õ¡Õ´Õ¢ Õ©Õ©Õ¥Ö€Õ¨ + setting_hide_network: Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ ÖÕ¡Õ¶ÖÕ¤ + setting_noindex: Ô½Õ¸Ö‚Õ½Õ¡ÖƒÕ¥Õ¬ Õ¸Ö€Õ¸Õ¶Õ¸Õ²Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¥Ö€Õ« Õ«Õ¶Õ¤Õ§Ö„Õ½Õ¡Ö‚Õ¸Ö€Õ¸Ö‚Õ´Õ«Ö + setting_reduce_motion: Ô¿Ö€Õ³Õ¡Õ¿Õ¥Õ¬ Õ¡Õ¶Õ«Õ´Õ¡ÖÕ«Õ¡Õ¶Õ¥Ö€Õ« Õ·Õ¡Ö€ÕªÕ¸Ö‚Õ´Õ¨ + setting_show_application: Ô²Õ¡ÖÕ¡ÕµÕ¡ÕµÕ¿Õ¥Õ¬ ÕµÕ¡Ö‚Õ¥Õ¬Õ¸Ö‚Õ¡Õ®, Õ¸Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¸Ö‚Õ´ Õ§ Õ©Õ©Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ + setting_system_font_ui: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ« Õ¬Õ¼Õ¥Õ¬Õ¥Õ¡ÕµÕ¶ Õ¿Õ¡Õ¼Õ¡Õ¿Õ¥Õ½Õ¡Õ¯Õ¨ setting_theme: Ô¿Õ¡ÕµÖ„Õ« Õ©Õ¥Õ´Õ¡Õ¶ + setting_trends: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Ö…Ö€Õ¸Ö‚Õ¡Õµ Õ©Ö€Õ¥Õ¶Õ¤Õ¶Õ¥Ö€Õ¨ + setting_unfollow_modal: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¨ Õ¸Ö€Õ¥Ö‚Õ§ Õ´Õ¥Õ¯Õ«Õ¶ Õ¹Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» + setting_use_blurhash: Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ£Õ¸Ö‚Õ¶Õ¡Ö‚Õ¸Ö€ Õ¯Õ¿Õ¸Ö€Õ¶Õ¥Ö€ Õ©Õ¡Ö„ÖÕ¸Ö‚Õ¡Õ® Õ´Õ¥Õ¤Õ«Õ¡ÕµÕ«Ö + setting_use_pending_items: Ô´Õ¡Õ¶Õ¤Õ¡Õ² Õ¼Õ¥ÕªÕ«Õ´ severity: ÕÖ€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ sign_in_token_attempt: Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¸Õ¤ + type: Õ†Õ¥Ö€Õ´Õ¸Ö‚Õ®Õ´Õ¡Õ¶ Õ¿Õ¥Õ½Õ¡Õ¯ username: Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ¶Õ¸Ö‚Õ¶ + username_or_email: Ô¾Õ¡Õ®Õ¯Õ¡Õ¶Õ¸Ö‚Õ¶ Õ¯Õ¡Õ´ էլ․ ÖƒÕ¸Õ½Õ¿ + whole_word: Ô±Õ´Õ¢Õ¸Õ²Õ» Õ¢Õ¡Õ¼Õ¨ + email_domain_block: + with_dns_records: Õ†Õ¥Ö€Õ¡Õ¼Õ¥Õ¬ MX Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Õ¤Õ¸Õ´Õ§ÕµÕ¶Õ« IP + featured_tag: + name: ÕŠÕ«Õ¿Õ¡Õ¯ + interactions: + must_be_follower: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Õ¹ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö€Õ¤Õ¶Õ¥Ö€Õ«Ö + must_be_following: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶ÖÕ«Ö, Õ¸Ö€Õ¸Õ¶Ö Õ¹Õ¥Õ½ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ + must_be_following_dm: Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ½ÖÕ§Õ¡Õ£Ö€Õ¸Ö‚Õ¡Õ® Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©Õ«Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶ÖÕ«Ö, Õ¸Ö€Õ¸Õ¶Ö Õ¹Õ¥Õ½ Õ°Õ¥Õ¿Õ¥Ö‚Õ¸Ö‚Õ´ invite: comment: Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ + invite_request: + text: Ô»Õ¶Õ¹Õ¸ÕžÖ‚ Õ¥Õ½ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ´Õ«Õ¡Õ¶Õ¡Õ¬ + ip_block: + comment: Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ + ip: IP + severities: + no_access: Õ„Õ¸Ö‚Õ¿Ö„Õ¨ Õ¡Ö€Õ£Õ¥Õ¬Õ¥Õ¬ + sign_up_requires_approval: ÕÕ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ + severity: Ô¿Õ¡Õ¶Õ¸Õ¶ + notification_emails: + digest: ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¤Õ¡Õ½Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ¡Õ® Õ«Õ´Õ¡Õ¯Õ¶Õ¥Ö€ + favourite: ÕˆÖ€Õ¥Ö‚Õ§ Õ´Õ¥Õ¯Õ¨ Õ°Õ¡Ö‚Õ¡Õ¶Õ¥Ö Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ + follow: ÕˆÖ€Õ¥Ö‚Õ§ Õ´Õ§Õ¯Õ¨ Õ½Õ¯Õ½Õ¥Ö Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬ Ö„Õ¥Õ¦ + follow_request: ÕˆÖ€Õ¥Ö‚Õ§ Õ´Õ§Õ¯Õ¨ Ö„Õ¥Õ¦ Õ°Õ¥Õ¿Õ¥Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÖ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ + mention: ÕˆÖ€Õ¥Ö‚Õ§ Õ´Õ¥Õ¯Õ¨ Õ¶Õ·Õ¥Ö Ö„Õ¥Õ¦ + pending_account: ÕŽÕ¥Ö€Õ¡Õ¶Õ¡ÕµÕ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ«Ö„ Õ¸Ö‚Õ¶Õ¥ÖÕ¸Õ² Õ¶Õ¸Ö€ Õ°Õ¡Õ·Õ«Ö‚ + reblog: Ô»Õ¶Õ¹ÖŠÕ¸Ö€ Õ´Õ§Õ¯Õ¨ Õ©Õ¸Ö‚Õ©Õ¤ Õ¿Õ¡Ö€Õ¡Õ®Õ¥Ö + report: Õ†Õ¸Ö€ Õ¢Õ¸Õ²Õ¸Ö„ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ¥Õ¬ + trending_tag: Õ‰Õ¾Õ¥Ö€Õ¡Õ¶Õ¡ÕµÕ¸Ö‚Õ¡Õ® ÕºÕ«Õ¿Õ¡Õ¯Õ¨ Õ©Ö€Õ¥Õ¶Õ¤Õ« Õ´Õ§Õ» Õ§ + tag: + listable: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬, Õ¸Ö€ Õ¡ÕµÕ½ ÕºÕ«Õ¿Õ¡Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ« Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¥Ö‚ Õ°Õ¡Õ·Õ¸Ö‚Õ« Õ´Õ¡Õ¿Õ¥Õ¡Õ¶Õ¸Ö‚Õ´ + name: ÕŠÕ«Õ¿Õ¡Õ¯ + trendable: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬, Õ¸Ö€ Õ¡ÕµÕ½ ÕºÕ«Õ¿Õ¡Õ¯Õ¨ ÕµÕ¡ÕµÕ¿Õ¶Õ¸Ö‚Õ« Õ©Ö€Õ¥Õ¶Õ¤Õ¶Õ¥Ö€Õ¸Ö‚Õ´ + usable: Ô¹Õ¸ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ©Õ©Õ¥Ö€Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¡ÕµÕ½ ÕºÕ«Õ¿Õ¡Õ¯Õ¨ 'no': ÕˆÕ¹ recommended: Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´ required: mark: "*" text: ÕºÕ¡Ö€Õ¿Õ¡Õ¤Õ«Ö€ + title: + sessions: + webauthn: Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©Õ¥Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ¨ Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ 'yes': Ô±ÕµÕ¸ diff --git a/config/locales/simple_form.id.yml b/config/locales/simple_form.id.yml index 1717d0722cd8871ce169b6d179033fcd7f885343..4b469cd9363e0ef3a1a3c6675b119356282b79c4 100644 --- a/config/locales/simple_form.id.yml +++ b/config/locales/simple_form.id.yml @@ -65,8 +65,17 @@ id: data: File CSV yang diexpor dari server Mastodon lain invite_request: text: Ini akan membantu kami meninjau aplikasi Anda + ip_block: + comment: Opsional. Harap ingat alasan Anda menambahkan peraturan ini. + expires_in: Alamat IP terbatas, kadang-kadang dibagikan dan dipindah tangan. Oleh karena itu, blok IP tidak terbatas tidak disarankan. + ip: Masukkan alamat IPv4 atau IPv6. Anda dapat memblokir seluruh rentang dengan sintaks CIDR. Hati-hati, jangan mengunci Anda sendiri! + severities: + no_access: Blokir akses ke seluruh sumber daya + sign_up_requires_approval: Pendaftaran baru memerlukan persetujuan Anda + severity: Pilih apa yang akan dilakukan dengan permintaan dari IP ini sessions: otp: Masukkan kode dua-faktor dari handphone atau gunakan kode pemulihan anda. + webauthn: Jika ini kunci USB pastikan dalam keadaan tercolok dan, jika perlu, ketuk. tag: name: Anda hanya dapat mengubahnya ke huruf kecil/besar, misalnya, agar lebih mudah dibaca user: @@ -91,6 +100,7 @@ id: types: disable: Matikan none: Biarkan + sensitive: Sensitif silence: Diamkan suspend: Tangguhkan dan hapus data akun scr permanen warning_preset_id: Gunakan preset peringatan @@ -116,6 +126,7 @@ id: expires_in: Kedaluwarsa setelah fields: Metadata profil header: Tajuk + honeypot: "%{label} (jangan diisi)" inbox_url: URL kotak relai irreversible: Hapus alih-alih sembunyikan locale: Bahasa @@ -135,6 +146,7 @@ id: setting_default_privacy: Privasi postingan setting_default_sensitive: Selalu tandai media sebagai sensitif setting_delete_modal: Tampilkan dialog konfirmasi sebelum hapus toot + setting_disable_swiping: Nonaktifkan gerak usap setting_display_media: Tampilan media setting_display_media_default: Bawaan setting_display_media_hide_all: Sembunyikan semua @@ -151,6 +163,7 @@ id: setting_use_blurhash: Tampilkan gradien penuh warna utk media tersembunyi setting_use_pending_items: Mode pelan severity: Keparahan + sign_in_token_attempt: Kode keamanan type: Tipe impor username: Nama pengguna username_or_email: Nama pengguna atau Surel @@ -167,6 +180,13 @@ id: comment: Komentar invite_request: text: Mengapa Anda ingin gabung? + ip_block: + comment: Komentar + ip: IP + severities: + no_access: Blok akses + sign_up_requires_approval: Batasi pendaftaran + severity: Aturan notification_emails: digest: Kirim email berisi rangkuman favourite: Kirim email saat seseorang menyukai status anda @@ -187,4 +207,7 @@ id: required: mark: "*" text: wajib + title: + sessions: + webauthn: Gunakan salah satu kunci keamanan untuk masuk 'yes': Ya diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index 5a1c51883e0ebcd780e5c8b472ffc98010e26ad1..53e34f00cb0eaba127f468f262e106c7184ba177 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -65,8 +65,17 @@ is: data: CSV-skrá sem flutt hefur verið út af öðrum Mastodon-þjóni invite_request: text: Þetta mun hjálpa okkur við að yfirfara umsóknina þÃna + ip_block: + comment: Valfrjálst. Mundu hvers vegna þú bættir þessari reglu við. + expires_in: IP-vistföng eru ekki óendanleg, þeim er stundum deilt og skipta oftu um eigendur. Af þessum ástæðum er ekki mælt með ótakmörkuðum lokunum á blokkir IP-vistfanga. + ip: Settu inn IPv4 eða IPv6 vistfang. Þú getur lokað á svið vistfanga með þvà að nota CIDR-framsetningu. Gættu þess að loka ekki sjálfa/n þig úti! + severities: + no_access: Loka á aðgang að öllum tilföngum + sign_up_requires_approval: Nýskráningar munu þurfa samþykki þitt + severity: Veldu hvað munir gerast við beiðnir frá þessu IP-vistfangi sessions: otp: 'Settu inn tveggja-þátta kóðann sem farsÃmaforritið útbjó eða notaðu einn af endurheimtukóðunum þÃnum:' + webauthn: Ef þetta er USB-lykill, gakktu úr skugga um að honum sé stungið à samband og ef þörf þykir að ýta á hann. tag: name: Þú getur aðeins breytt stafstöði mill há-/lágstafa, til gæmis til að gera þetta læsilegra user: @@ -91,6 +100,7 @@ is: types: disable: Gera innskráningu óvirka none: Gera ekkert + sensitive: Viðkvæmt silence: Hylja suspend: Setja à bið og eyða endanlega gögnum notandaaðgangsins warning_preset_id: Nota forstillta aðvörun @@ -116,6 +126,7 @@ is: expires_in: Rennur út eftir fields: Lýsigögn notandasniðs header: SÃðuhaus + honeypot: "%{label} (ekki fylla út)" inbox_url: URL-slóð á innhólf endurvarpa irreversible: Fella niður à staðinn fyrir að fela locale: Tungumál viðmóts @@ -135,6 +146,7 @@ is: setting_default_privacy: Gagnaleynd færslna setting_default_sensitive: Alltaf merkja myndefni sem viðkvæmt setting_delete_modal: Birta staðfestingarglugga áður en tÃsti er eytt + setting_disable_swiping: Gera strokuhreyfingar óvirkar setting_display_media: Birting myndefnis setting_display_media_default: Sjálfgefið setting_display_media_hide_all: Fela allt @@ -168,6 +180,13 @@ is: comment: Athugasemd invite_request: text: Hvers vegna viltu taka þátt? + ip_block: + comment: Athugasemd + ip: IP-vistfang + severities: + no_access: Loka á aðgang + sign_up_requires_approval: Takmarka nýskráningar + severity: Regla notification_emails: digest: Senda uppsafnaðan tölvupóst favourite: Einhver setti stöðufærslu þÃna à eftirlæti @@ -188,4 +207,7 @@ is: required: mark: "*" text: nauðsynlegt + title: + sessions: + webauthn: Nota einn af öryggislyklunum þÃnum til að skrá inn 'yes': Já diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index f76ca05b674153aea6054660c75efeda57268efb..82f12861f48bf84ec164fba5e44e77c380544ea9 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -44,7 +44,7 @@ it: setting_default_sensitive: Media con contenuti sensibili sono nascosti in modo predefinito e possono essere rivelati con un click setting_display_media_default: Nascondi media segnati come sensibili setting_display_media_hide_all: Nascondi sempre tutti i media - setting_display_media_show_all: Nascondi sempre i media segnati come sensibili + setting_display_media_show_all: Mostra sempre i media segnati come sensibili setting_hide_network: Chi segui e chi segue te non saranno mostrati sul tuo profilo setting_noindex: Ha effetto sul tuo profilo pubblico e sulle pagine degli status setting_show_application: L'applicazione che usi per pubblicare i toot sarà mostrata nella vista di dettaglio dei tuoi toot @@ -65,8 +65,17 @@ it: data: File CSV esportato da un altro server Mastodon invite_request: text: Questo ci aiuterà ad esaminare la tua richiesta + ip_block: + comment: Opzionale. Ricorda perché hai aggiunto questa regola. + expires_in: Gli indirizzi IP sono una risorsa finita, a volte sono condivisi e spesso cambiano possessore. Per questo motivo, i blocchi IP indefiniti non sono consigliati. + ip: Inserisci un indirizzo IPv4 o IPv6. Puoi bloccare interi intervalli usando la sintassi CIDR. Fai attenzione a non bloccare te stesso! + severities: + no_access: Blocca l'accesso a tutte le risorse + sign_up_requires_approval: Le nuove iscrizioni richiederanno la tua approvazione + severity: Scegli cosa accadrà con le richieste da questo IP sessions: otp: 'Inserisci il codice a due fattori generato dall''app del tuo telefono o usa uno dei codici di recupero:' + webauthn: Se si tratta di una chiavetta USB assicurati di inserirla e, se necessario, toccarla. tag: name: Puoi cambiare solo il minuscolo/maiuscolo delle lettere, ad esempio, per renderlo più leggibile user: @@ -91,6 +100,7 @@ it: types: disable: Disabilita none: Non fare nulla + sensitive: Sensibile silence: Silenzia suspend: Sospendi e cancella i dati dell'account in modo irreversibile warning_preset_id: Usa un avviso preimpostato @@ -116,6 +126,7 @@ it: expires_in: Scade dopo fields: Metadati del profilo header: Intestazione + honeypot: "%{label} (non compilare)" inbox_url: URL della inbox del ripetitore irreversible: Elimina invece di nascondere locale: Lingua dell'interfaccia @@ -135,6 +146,7 @@ it: setting_default_privacy: Privacy dei post setting_default_sensitive: Segna sempre i media come sensibili setting_delete_modal: Mostra dialogo di conferma prima di eliminare un toot + setting_disable_swiping: Disabilita i movimenti di scorrimento setting_display_media: Visualizzazione dei media setting_display_media_default: Predefinita setting_display_media_hide_all: Nascondi tutti @@ -168,6 +180,13 @@ it: comment: Commento invite_request: text: Perché vuoi iscriverti? + ip_block: + comment: Commento + ip: IP + severities: + no_access: Blocca accesso + sign_up_requires_approval: Limita iscrizioni + severity: Regola notification_emails: digest: Invia email riassuntive favourite: Invia email quando segna come preferito al tuo stato @@ -188,4 +207,7 @@ it: required: mark: "*" text: richiesto + title: + sessions: + webauthn: Usa una delle tue chiavi di sicurezza per accedere 'yes': Si diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index bbc0b5fd77ead61493683745ff5d3c35bd24f964..abe986acd4a6c2c49e95c86679109428bb64a0e5 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -65,8 +65,17 @@ ja: data: ä»–ã® Mastodon サーãƒãƒ¼ã‹ã‚‰ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ãŸCSVãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ä¸‹ã•ã„ invite_request: text: ã“ã®ã‚µãƒ¼ãƒãƒ¼ã¯ç¾åœ¨æ‰¿èªåˆ¶ã§ã™ã€‚申請を承èªã™ã‚‹éš›ã«å½¹ç«‹ã¤ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ·»ãˆã¦ãã ã•ã„ + ip_block: + comment: オプションã§ã™ã€‚ã“ã®ãƒ«ãƒ¼ãƒ«ã‚’è¿½åŠ ã—ãŸç†ç”±ã®è¦šãˆæ›¸ãã«ã”利用ãã ã•ã„。 + expires_in: IPã‚¢ãƒ‰ãƒ¬ã‚¹ã¯æœ‰é™ã®ãƒªã‚½ãƒ¼ã‚¹ã§ã™ã€‚複数人ã§å…±æœ‰ã•れãŸã‚Šå¤‰æ›´ã•れるã“ã¨ã‚‚ã‚りã¾ã™ã€‚ãã®ãŸã‚無期é™ã«IPアドレスをブãƒãƒƒã‚¯ã™ã‚‹ã®ã¯æŽ¨å¥¨ã•れã¾ã›ã‚“。 + ip: IPv4ã¾ãŸã¯IPv6アドレスを入力ã—ã¦ãã ã•ã„。CIDR構文を用ã„ã¦ç¯„囲指定ã§ãƒ–ãƒãƒƒã‚¯ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚è‡ªåˆ†è‡ªèº«ã‚’ç· ã‚出ã•ãªã„ã‚ˆã†æ³¨æ„ã—ã¦ãã ã•ã„ï¼ + severities: + no_access: ã™ã¹ã¦ã®ãƒªã‚½ãƒ¼ã‚¹ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’ブãƒãƒƒã‚¯ã—ã¾ã™ + sign_up_requires_approval: 承èªã™ã‚‹ã¾ã§æ–°è¦ç™»éŒ²ãŒå®Œäº†ã—ãªããªã‚Šã¾ã™ + severity: ã“ã®IPã«å¯¾ã™ã‚‹æŽªç½®ã‚’é¸æŠžã—ã¦ãã ã•ã„ sessions: otp: 'æºå¸¯é›»è©±ã®ã‚¢ãƒ—リã§ç”Ÿæˆã•れãŸäºŒæ®µéšŽèªè¨¼ã‚³ãƒ¼ãƒ‰ã‚’入力ã™ã‚‹ã‹ã€ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’使用ã—ã¦ãã ã•ã„:' + webauthn: USBã‚ーã®å ´åˆã¯ã€å¿…ãšæŒ¿å…¥ã—ã€å¿…è¦ã«å¿œã˜ã¦ã‚¿ãƒƒãƒ—ã—ã¦ãã ã•ã„。 tag: name: è¦–èªæ€§å‘上ãªã©ã®ãŸã‚ã«ã‚¢ãƒ«ãƒ•ァベット大文å—å°æ–‡å—ã®å¤‰æ›´ã®ã¿è¡Œã†ã“ã¨ãŒã§ãã¾ã™ user: @@ -90,9 +99,10 @@ ja: type: アクション types: disable: ãƒã‚°ã‚¤ãƒ³ã‚’無効化 - none: 何もã—ãªã„ + none: è¦å‘Šã‚’é€ä¿¡ + sensitive: é–²è¦§æ³¨æ„ silence: サイレンス - suspend: åœæ¢ã—アカウントã®ãƒ‡ãƒ¼ã‚¿ã‚’æ’ä¹…çš„ã«å‰Šé™¤ã™ã‚‹ + suspend: åœæ¢ warning_preset_id: プリセットè¦å‘Šæ–‡ã‚’使用 announcement: all_day: 終日 @@ -116,6 +126,7 @@ ja: expires_in: æœ‰åŠ¹æœŸé™ fields: プãƒãƒ•ã‚£ãƒ¼ãƒ«è£œè¶³æƒ…å ± header: ヘッダー + honeypot: "%{label} (入力ã—ãªã„)" inbox_url: リレーサーãƒãƒ¼ã® inbox URL irreversible: éš ã™ã®ã§ã¯ãªã除外ã™ã‚‹ locale: 言語 @@ -135,6 +146,7 @@ ja: setting_default_privacy: 投稿ã®å…¬é–‹ç¯„囲 setting_default_sensitive: メディアを常ã«é–²è¦§æ³¨æ„ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã™ã‚‹ setting_delete_modal: トゥートを削除ã™ã‚‹å‰ã«ç¢ºèªãƒ€ã‚¤ã‚¢ãƒã‚°ã‚’表示ã™ã‚‹ + setting_disable_swiping: スワイプã§ã®åˆ‡ã‚Šæ›¿ãˆã‚’無効ã«ã™ã‚‹ setting_display_media: メディアã®è¡¨ç¤º setting_display_media_default: 標準 setting_display_media_hide_all: éžè¡¨ç¤º @@ -168,6 +180,13 @@ ja: comment: コメント invite_request: text: æ„æ°—è¾¼ã¿ã‚’ãŠèžã‹ã›ãã ã•ã„ + ip_block: + comment: コメント + ip: IP + severities: + no_access: ブãƒãƒƒã‚¯ + sign_up_requires_approval: ç™»éŒ²ã‚’åˆ¶é™ + severity: ルール notification_emails: digest: タイムラインã‹ã‚‰ãƒ”ックアップã—ã¦ãƒ¡ãƒ¼ãƒ«ã§é€šçŸ¥ã™ã‚‹ favourite: ãŠæ°—ã«å…¥ã‚Šç™»éŒ²ã•ã‚ŒãŸæ™‚ @@ -188,4 +207,7 @@ ja: required: mark: "*" text: å¿…é ˆ + title: + sessions: + webauthn: ã‚»ã‚ュリティã‚ーを使用ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ 'yes': ã¯ã„ diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index d76af2c5737988cefce3d55fe2fc9a122fda8fb9..bbc23ed5127f7eb90ca212790becba0edecf5812 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -26,6 +26,10 @@ kab: name: 'Ahat ad tebγuḠad tesqedceḠyiwen gar-asen:' imports: data: Afaylu CSV id yusan seg uqeddac-nniá¸en n Maá¹£á¹udun + ip_block: + comment: D afrayan. Cfu É£ef wayÉ£er i terniḠalugen-a. + severities: + no_access: Sewḥel anekcu É£er akk tiÉ£bula labels: account: fields: @@ -42,6 +46,7 @@ kab: disable: Sens anekcum none: Ur teg kra silence: Sgugem + suspend: Ḥbes di leεá¸il announcement: ends_at: Tagara n tedyant text: AlÉ£u @@ -72,6 +77,7 @@ kab: setting_hide_network: Ffer azetta-k·m setting_theme: Asental n wesmel setting_use_pending_items: Askar aleγwayan + sign_in_token_attempt: Tangalt n tÉ£ellist username: Isem n useqdac username_or_email: Isem n useqdac neγ imal whole_word: Awal akk @@ -81,6 +87,15 @@ kab: comment: Awennit invite_request: text: Acimi tebγiḠad ternuḠiman-ik? + ip_block: + comment: Awennit + ip: IP + severities: + no_access: Sewḥel anekcum + severity: Alugen + notification_emails: + mention: Yuder-ik·em-id walbÉ›aḠ+ reblog: Yella win yesselhan adda-dik·im tag: name: Ahacá¹ag 'no': Ala diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index 7c05521fe452054052d69746b75aef1ed64b0046..5c47a99c446d2cdc7112c0406c32a10215d64469 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -65,8 +65,17 @@ ko: data: 다른 ë§ˆìŠ¤í† ëˆ ì„œë²„ì—서 ì¶”ì¶œëœ CSV íŒŒì¼ invite_request: text: ì´ ì •ë³´ëŠ” 우리가 심사를 하는 ë°ì— ì°¸ê³ í• ìˆ˜ 있습니다 + ip_block: + comment: 필수 아님. 왜 ì´ ê·œì¹™ì„ ì¶”ê°€í–ˆëŠ”ì§€ 기억하세요. + expires_in: IP 주소는 í•œì •ëœ ìžì›ìž…니다, ì´ê²ƒë“¤ì€ ê°€ë” ê³µìœ ë˜ê±°ë‚˜ ìžì£¼ ì†Œìœ ìžê°€ ë°”ë€Œê¸°ë„ í•©ë‹ˆë‹¤. ì´ëŸ° ì´ìœ 로 ì¸í•´, IP ì°¨ë‹¨ì„ ì˜êµ¬ížˆ ìœ ì§€í•˜ëŠ” ê²ƒì€ ì¶”ì²œí•˜ì§€ 않습니다. + ip: IPv4 ë˜ëŠ” IPv6 주소를 ìž…ë ¥í•˜ì„¸ìš”. CIDR ë¬¸ë²•ì„ ì‚¬ìš©í•´ì„œ ëª¨ë“ ë²”ìœ„ë¥¼ ì°¨ë‹¨í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. ìžê¸° ìžì‹ ì„ ìž ê°€ë²„ë¦¬ì§€ 않ë„ë¡ ì£¼ì˜í•˜ì„¸ìš”! + severities: + no_access: ëª¨ë“ ìžì›ì— 대한 ì ‘ê·¼ 차단 + sign_up_requires_approval: 새 ê°€ìž…ì´ ìŠ¹ì¸ì„ 필요로 하ë„ë¡ í•©ë‹ˆë‹¤ + severity: 해당 IPë¡œë¶€í„°ì˜ ìš”ì²ì— 대해 ë¬´ì—‡ì´ ì¼ì–´ë‚˜ê²Œ í• ì§€ ê³ ë¥´ì„¸ìš” sessions: otp: 'íœ´ëŒ€ì „í™”ì—서 ìƒì„± ëœ 2단계 ì¸ì¦ 코드를 ìž…ë ¥í•˜ê±°ë‚˜, 복구 코드 중 하나를 사용하세요:' + webauthn: USB 키ë¼ë©´ 삽입했는지 확ì¸í•˜ê³ , 필요하다면 누르세요. tag: name: ì½ê¸° 쉽게하기 위한 글ìžì˜ 대소문ìžë§Œ ë³€ê²½í• ìˆ˜ 있습니다. user: @@ -91,6 +100,7 @@ ko: types: disable: 비활성화 none: 아무 ê²ƒë„ í•˜ì§€ 않기 + sensitive: 민ê°í•¨ silence: 침묵 suspend: ì •ì§€í•˜ê³ ë˜ëŒë¦´ 수 없는 ë°ì´í„° ì‚ì œ warning_preset_id: ê²½ê³ í‹€ 사용하기 @@ -116,6 +126,7 @@ ko: expires_in: ë§Œë£Œì‹œê° fields: 프로필 메타ë°ì´í„° header: í—¤ë” + honeypot: "%{label} (채우지 마시오)" inbox_url: ë¦´ë ˆì´ ì„œë²„ì˜ inbox URL irreversible: 숨기는 ëŒ€ì‹ ì‚ì œ locale: ì¸í„°íŽ˜ì´ìФ 언어 @@ -135,6 +146,7 @@ ko: setting_default_privacy: 툿 프ë¼ì´ë²„시 setting_default_sensitive: 미디어를 ì–¸ì œë‚˜ 민ê°í•œ 컨í…ì¸ ë¡œ ì„¤ì • setting_delete_modal: 툿 ì‚ì œ ì „ í™•ì¸ ì°½ì„ í‘œì‹œ + setting_disable_swiping: 스와ì´í”„ 모션 비활성화 setting_display_media: 미디어 표시 setting_display_media_default: 기본 setting_display_media_hide_all: ëª¨ë‘ ê°€ë¦¬ê¸° @@ -168,6 +180,13 @@ ko: comment: ì£¼ì„ invite_request: text: ê°€ìž…í•˜ë ¤ëŠ” ì´ìœ ê°€ 무엇ì¸ê°€ìš”? + ip_block: + comment: ì£¼ì„ + ip: IP + severities: + no_access: ì ‘ê·¼ 차단 + sign_up_requires_approval: 가입 ì œí•œ + severity: 규칙 notification_emails: digest: 요약 ì´ë©”ì¼ ë³´ë‚´ê¸° favourite: 누군가 ë‚´ ìƒíƒœë¥¼ ì¦ê²¨ì°¾ê¸°ë¡œ 등ë¡í–ˆì„ 때 ì´ë©”ì¼ ë³´ë‚´ê¸° @@ -188,4 +207,7 @@ ko: required: mark: "*" text: 필수 í•목 + title: + sessions: + webauthn: 로그ì¸í•˜ê¸° 위해서 보안 키를 사용해 주세요 'yes': 네 diff --git a/config/locales/simple_form.ku.yml b/config/locales/simple_form.ku.yml index cc251e86ae3fc9c96ba4a32a86e9e41868ac09d9..8ff8a5a46c6523339cc581072272d2923d34ee75 100644 --- a/config/locales/simple_form.ku.yml +++ b/config/locales/simple_form.ku.yml @@ -1 +1,212 @@ -ckb-IR: +--- +ku: + simple_form: + hints: + account_alias: + acct: دیاریکردنی username@domain ئەو هەژمارە Ú©Û• دەتەوێت بیگوازیەوە Ù„Û• + account_migration: + acct: دیاریکردنی username@domain ئەو هەژمارە Ú©Û• دەتەوێت بیگوازیەوە Ù„Û• + account_warning_preset: + text: دەتوانی ڕستەسازی ÛŒ توت بەکاربێنیت، ÙˆÛ•Ú© لینک، هاشتاگ Ùˆ باسەکان + title: ئارەزوومەندانە. دیار نیە بۆ وەرگر + admin_account_action: + include_statuses: بەکارهێنەرەکە دەبینێت کام توتی هۆکاری کرداری بەڕێوەبەر یان ئاگادارکردنەوە + send_email_notification: بەکارهێنەر ڕوننکردەوەیەک دەبینێت Ú©Û• تێدا دەزانێت Ú†ÛŒ بە سەر هەژمارەکەی هاتووە + text_html: ئارزوومەندانە. دەتوانن ÙˆÛ•Ú© توتی ئاسایی بینووسن. دەتوانن بۆ کەمکردنەوەی کات <a href="%{path}">ئاگادارییەکان Ù„Û• Ù¾ÛŽØ´Û•ÙˆÛ• زیادبکەن</a> + type_html: گەرکتە Ù„Û•Ú¯Û•Úµ هەژمارەی <strong>%{acct}</strong> Ú†ÛŒ بکەیت + warning_preset_id: ئارەزوومەندانەیە. هێشتا دەتوانیت Ù„Û• کۆتایی دەق شتێک زیاد بکەی + announcement: + all_day: کاتێک چاودێریکرا، تەنها بەروارەکانی مەودای کات پیشان دەدرێت + ends_at: ئارەزوومەندانەیە. ئەم کاتە راگەیەنراوەکە بە شێوەیەکی خۆکارانە بڵاوناکرێتەوە + scheduled_at: Ú†Û†Úµ یبهێڵەوە بۆ بڵاوکردنەوەی دەستبەجێی بانگەوازەکە + starts_at: ئارەزوومەندانەیە. Ù„Û• ØØ§ÚµÛ•تی ڕاگەیاندنی تۆ بەستراو بە مەودایەکی کاتی دیاریکراو + text: دەتوانیت ڕستەسازی توت بەکار بێنیت. تکایە بیر Ù„Û•Ùˆ بۆشاییە بکەوە Ú©Û• بانگەوازەکە لەسەر شاشەی بەکارهێنەرەکە دەست نیشان دەکات + defaults: + autofollow: ئەو کەسانەی Ú©Û• Ù„Û• Ú•ÛŽÚ¯Û•ÛŒ بانگهێشتکردنەوە تۆمار دەکرێن بە خۆکارانە شوێنت دەکەون + avatar: PNG, GIF یان JPG. Ù„Û• زۆربەی %{size}. دەبێتە ئەندازەیەکی کەمکراوە بۆ %{dimensions}px + bot: ئەم هەژمارە بەشێوەیەکی سەرەکی کردارە خۆکارانە ئەنجام دەدات Ùˆ لەوانەیە چاودێری نەکرێت + context: یەک یان چەند دەقێک Ú©Û• Ù¾Ø§Ù„Ø§ÙØªÙ†Û•Ú©Û• جێبەجێ بکات + current_password: بۆ مەبەستی پاراستن تکایە تێپەروشەی هەژمارەی ئێستاکەت بنووسە + current_username: بۆ دڵنیابوون، تکایە ناوی بەکارهێنەری ئەم هەژمارەیە بنووسە + digest: تەنیا دوای ماوەیەکی زۆر Ù„Û• بێ چالاکیدەنێردرێت Ùˆ تەنیا ئەگەر نامەیەکی کەسیت بۆ نووسرابێت + discoverable: پێرستی هەڵبژاردەی بەکارهێنەران،تەنها ڕیگایەکی دیکەیە بۆ گەیشتنی بەکارهێنەری ÙØ±Û•تر بۆ هەژمارەکەت + email: ئیمەیڵێکی پشتڕاستکردنەوەت بۆ دەنێردرێت + fields: دەتوانیت تا ٤بڕگەت هەبێت Ú©Û• ÙˆÛ•Ú© خشتەیەک لەسەر Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت پیشان بدرێت + header: PNG, GIF یان JPG. Ù„Û• زۆربەی %{size}. دەبێتە ئەندازەیەکی کەمکراوە بۆ %{dimensions}پیکسێڵ + inbox_url: نیشانەی Ù¾Û•Ú•Û•ÛŒ سەرەکی ئەو رێڵە Ú©Û• هەرەکتە بەکاریببەیت ڕوونووس دەکات + irreversible: توتە Ùلتەرکراوەکە بە شێوەیەکی نەگەڕاو ÙØ±Û•دەدرێن، تەنانەت ئەگەر Ùلتەردواتر لاببرێت + locale: زمانی ڕووکاری بەکارهێنەر، ئیمەیلەکان Ùˆ ئاگانامەکان + locked: بە دەستی شوێنکەوتوانی خۆت پەسەند بکە + password: بەلایەنی Ú©Û•Ù…Û•ÙˆÛ• Ù¨ نووسە بەکاربهێنە + phrase: سەربەخۆ Ù„Û• بچکۆلی Ùˆ گەورەیی پیتەکان، Ù„Û•Ú¯Û•Úµ دەقی ئەسڵی یان ئاگانامەکانی ناوەرۆکی توتەکان هاوئاهەنگ دەکرێت + scopes: APIـیەکانی بەرنامەنووسی Ú©Û• ئەم ماڵپەڕە دەستپێگەیشتنی لەگەڵیان هیە. ئەگەر بەرزترین ئاست هەڵبژێرن ئیتر نیاز بە بژاردەی ئاستی نزم نییە. + setting_aggregate_reblogs: بۆ ئەو دووبارە توتانە Ú©Û• بە نوێیی پێتان نیشان دراوە،دووبارە توتەکانی پێشتر زیاد Ù…Û•Ú©Û•(تەنها کاریگەری لەسەر توتەکانی ئەم دواییە هەیە) + setting_default_sensitive: میدیای هەستیار Ù„Û• بنەڕەت شاراوەیە Ùˆ دەتوانرێت بە کلیکیک ئاشکرا بکرێت + setting_display_media_default: شاردنەوەی ئەو میدیایانەی ÙˆÛ•Ú© هەستیار نیشانکراون + setting_display_media_hide_all: هەمیشە میدیا بشارەوە + setting_display_media_show_all: هەمیشە میدیا نیشان بدە + setting_hide_network: Ú©ÛŽ دوای دەکەویت Ùˆ Ú©ÛŽ دوای تۆ دەکەوێت Ù„Û• Ù¾Ø±Û†ÙØ§ÛŒÙ„ەکەت پیشان نادرێت + setting_noindex: کاردەکاتە سەر Ù¾Ø±Û†ÙØ§ÛŒÙ„ Ùˆ لاپەڕە گشتیەکانت + setting_show_application: بەرنامەیەک Ú©Û• بە یارمەتیت توت دەکەیت، Ù„Û• دیمەنی وردی توتەکان پیشان دەدرێت + setting_use_blurhash: سێبەرەکان Ù„Û• سەر بنەمای ڕەنگەکانی بەکارهاتوو Ù„Û• ÙˆÛŽÙ†Û• داشاراوەکان دروست دەبن بەڵام وردەزانیاری ÙˆÛŽÙ†Û• تێیدا ڕوون نییە + setting_use_pending_items: لەجیاتی ئەوەی بە خۆکارانە کێشان هەبێت Ù„Û• نووسراوەکان بە کرتەیەک بەڕۆژبوونی پێرستی نووسراوەکان بشارەوە + username: ناوی بەکارهێنەری ئێوە لەسەر %{domain} یەکتا دەبێت + whole_word: کاتێک کلیل‌وشە بریتییە Ù„Û• ژمارە Ùˆ پیت، تنەها کاتێک پەیدا دەبێت Ú©Û• Ù„Û•Ú¯Û•Úµ گشتی وشە Ù„Û• Ù†ÛŽÙˆ دەقەکە هاوئاهەنگ بێت، Ù†Û• تەنها Ù„Û•Ú¯Û•Úµ بەشێک Ù„Û• وشە + domain_allow: + domain: ئەم دۆمەینە دەتوانێت دراوە Ù„Û• ئەم ڕاژە وەربگرێت Ùˆ دراوەی ئەم دۆمەینە لێرە ڕێکدەخرین Ùˆ پاشکەوت دەکرێن + email_domain_block: + domain: ئەمە دەکرێت ناوی دۆمەینەکە بێت Ú©Û• Ù„Û• ناونیشانی ئیمەیلدا دەرکەوێ، تۆماری MX Ú©Û• دۆمەین چارەسەری دەکات یان IPÛŒ ڕاژەکە Ú©Û• تۆماری MX چارەسەری دەکات. ئەوانە دەپشکنن لەسەر تۆمارکردنی بەکارهێنەر Ùˆ تۆمارکردن ڕەت دەکرێت. + with_dns_records: Ù‡Û•ÙˆÚµÛŽÚ© بۆ چارەسەرکردنی تۆمارەکانی DNSÛŒ دۆمەین دراوە Ú©Û• ئەنجامەکان بلۆک دەکرێت + featured_tag: + name: 'لەوانەیە بتەوێت یەکێک لەمانە بەکاربهێنیت:' + form_challenge: + current_password: تۆ دەچیتە ناو ناوچەی پارێزراو + imports: + data: ÙØ§ÛŒÙ„ÛŒ CSV هەناردەکراوە Ù„Û• ڕاژەیەکی تری ماستۆدۆن + invite_request: + text: ئەمە یارمەتیمان دەدات بۆ پێداچوونەوەی بەرنامەکەت + ip_block: + comment: دڵخوازە. لەبیرتە بۆچی ئەم یاسایەت زیاد کرد. + expires_in: ناونیشانی IP سەرچاوەی سنوردارن، هەندێک جار هاوبەشکراون Ùˆ زۆر جار دەستەکان دەگۆڕن. لەبەر ئەم هۆیە، بلۆکی IP بێ نەناسراو پێشنیار نەکراوە. + ip: ناونیشانی IPv4 یان IPv6 تێبنووسە. دەتوانیت هەموو مەوداکان بلۆک بکەیت بە بەکارهێنانی داڕستانی CIDR. وریابە خۆت Ù‚ÙÚµ Ù…Û•Ú©Û•! + severities: + no_access: بلۆککردنی گەیشتن بە هەموو سەرچاوەکان + sign_up_requires_approval: نوێ ناوتۆمارکردن پێویستی بە ڕەزامەندی تۆیە + severity: هەڵبژێرە Ú†ÛŒ ڕوودەدات Ù„Û•Ú¯Û•Úµ داواکاریەکانی ئەم IP + sessions: + otp: 'کۆدی دوو-ÙØ§Ú©ØªÛ†Ø± بنووسە Ú©Û• لەلایەن ئەپی تەلەÙۆنەکەتەوە دروست کراوە یان یەکێک Ù„Û• کۆدەکانی هێنانەوەی خۆت بەکاربهێنە:' + webauthn: ئەگەر کلیلی USB بێت دڵنیابە Ù„Û• تێکردنی Ùˆ ئەگەر پێویست بوو، لێیبدە. + tag: + name: ئێوە دەتوانن گەورەیی Ùˆ بجکۆلیی پیتەکان دەستکاری بکەن تاکوو خوێنەوارتر دیاربن + user: + chosen_languages: کاتێک چاودێری کرا، تەنها توتەکان بە زمانە دیاریکراوەکان Ù„Û• هێڵی‌کاتی گشتی پیشان دەدرێت + labels: + account: + fields: + name: ناونیشان + value: ناوەڕۆک + account_alias: + acct: چارەسەرکردنی هەژمارە Ú©Û†Ù†Û•Ú©Û• + account_migration: + acct: چارەسەرکردنی هەژمارە نوێکە + account_warning_preset: + text: دەقی پێشوەختی ڕێکخستن + title: سەردێڕ + admin_account_action: + include_statuses: لەخۆگرتنی توتەکانی گوزارشت Ù„Û• ئیمەیل + send_email_notification: بەکارهێنەر ئاگادار بکەوە بۆ هەر ئیمەیڵێک + text: ئاگاداری تایبەتمەند + type: کردار + types: + disable: بەستن + none: ناردنی ئاگاداری + sensitive: هەستیار + silence: سنوور + suspend: ڕاگرتن + warning_preset_id: بەکاهێنانی ئاگاداری Ù¾ÛŽØ´ وەختە + announcement: + all_day: ڕووداوی هەموو Ú•Û†Ú˜Û•Ú©Û• + ends_at: کۆتایی ڕووداو + scheduled_at: بڵاوکراوەکە خشتە بکە + starts_at: دەستپێکردنی ڕووداو + text: بانگەواز + defaults: + autofollow: بانگهێشت کردن بۆ شوێنکەوتنی هەژمارەکەت + avatar: ÙˆÛŽÙ†Û†Ú†Ú©Û• + bot: ئەمە هەژمارێکی ساختەیە + chosen_languages: پاڵاوتنی زمانەکان + confirm_new_password: پشتڕاستکردنەوەی تێپەڕوشەی نوێ + confirm_password: پشتڕاستکردنەوەی تێپەڕوشە + context: چوارچێوەی Ù¾Ø§ÚµØ§ÙØªÙ† + current_password: تێپەروشەی ئێستا + data: دراوه + discoverable: ئەم هەژمێرە Ù„Û• پێرستی بژاردەی بەکارهێنەران نیشان بدە + display_name: ناوی پیشاندان + email: ناونیشانی ئیمەیڵ + expires_in: بەسەردەچێت پاش + fields: مێتاداتای Ù¾Ø±Û†ÙØ§ÛŒÙ„ + header: سەرپەڕە + inbox_url: بەستەری سندوقی گواستنەوەی + irreversible: ÙØ±ÛŽØ¯Ø§Ù† لەجیاتی شاردنەوە + locale: زمانی Ù¾Û•Ú•Û•ÛŒ بەکارهێنەر + locked: داخستنی هەژمارە + max_uses: زۆرترین ژمارەی بەکاربەرەکان + new_password: تێپەروشەی نوێ + note: دەربارەی ئیوە + otp_attempt: کۆدی دووقۆناغی هاتنەژوور + password: تێپەڕوشە + phrase: وشەکلیل یان دەستەواژە + setting_advanced_layout: چالاککردنی ڕووکاری وێبی پێشکەوتوو + setting_aggregate_reblogs: گرووپی توتەکان یەکبخە + setting_auto_play_gif: خۆکاربەخشکردنی GIFــەکان + setting_boost_modal: پیشاندانی دیالۆگی دووپاتکردنەوە Ù¾ÛŽØ´ دوبارە توتاندن + setting_crop_images: Ù„Û• تووتی نەکراوە،وینەکان Ù„Û• ئەندازی ۱٦×۹ ببڕە + setting_default_language: زمانی نووسراوەکانتان + setting_default_privacy: چوارچێوەی تایبەتێتی ئێوە + setting_default_sensitive: هەمیشە نیشانکردنی میدیا ÙˆÛ•Ú© هەستیار + setting_delete_modal: نیساندانی پەیامی پەسەند کردن پاش سڕینەوە + setting_disable_swiping: جوڵەی سڕینەوە Ù„Û• کاربخە + setting_display_media: پیشاندانی میدیا + setting_display_media_default: بنەڕەت + setting_display_media_hide_all: شاردنەوەی هەموو + setting_display_media_show_all: هەموو نیشان بدە + setting_expand_spoilers: هەمیشە ئەو توتانەی Ú©Û• بە ئاگادارکردنەوەکانی ناوەڕۆکەوە نیشانەکراون، پیسان بدە + setting_hide_network: شاردنەوەی تۆڕەکەت + setting_noindex: داوا Ù„Û• مەکینەی گەڕان بۆ پیشاننەدان Ù„Û• دەئەنجامی گەڕانەکان + setting_reduce_motion: کەمکردنەوەی جوڵە Ù„Û• ئەنیمەکان + setting_show_application: ئاشکراکردنی ئەپەکان بۆ ناردنی توتەکان + setting_system_font_ui: Ùۆنتی بنەڕەتی سیستەم بەکاربهێنە + setting_theme: ڕووکاری ماڵپەڕ + setting_trends: پیشاندانی نووسراوە بەرچاوکراوەی ئەمڕۆ + setting_unfollow_modal: پیشاندانی پەیامی پەسەندکردن Ù¾ÛŽØ´ شوێن‌نەکەوتنی کەسێک + setting_use_blurhash: بەجیاتی وینەی داشاراوە، سێبەری ڕەنگاوڕەنگ نیشان بدە + setting_use_pending_items: دۆخی خاو + severity: ئاستی گرنگی + sign_in_token_attempt: کۆدی پاراستن + type: جۆری هاوردەکردن + username: ناوی بەکارهێنەر + username_or_email: ناوی بەکاهێنەر یان ئیمەیڵ + whole_word: هەموو وشەکە + email_domain_block: + with_dns_records: لەخۆگرتنی تۆمارەکانی MX Ùˆ ئای پییەکانی دۆمەین + featured_tag: + name: هەشتاگ + interactions: + must_be_follower: قەپاتکردنی ئاگانامەکان بێجگە Ù„Û• شوێنکەوتووان + must_be_following: بەئاگانامەکان بلۆک بکە Ù„Û• خەڵکێک Ú©Û• پەیڕەویان ناکەیت + must_be_following_dm: پەیامەکانی ڕاستەوخۆ بلۆک بکە Ù„Û•Ùˆ کەسانەی Ú©Û•ØŒ پەیڕەوی ناکەن + invite: + comment: بۆچوون + invite_request: + text: بۆچی دەتەوێت بەشدار بیت? + ip_block: + comment: بۆچوون + ip: IP + severities: + no_access: بلۆککردنی ده‌ستپێگه‌یشتن + sign_up_requires_approval: سنووردارکردنی چوونەناو + severity: یاسا + notification_emails: + digest: کورتکردنی ئاگادارییکەن لەیەک ئیمەیل + favourite: کەسێک دۆخی تۆی بەدڵ بوو + follow: کەسێک دوای تۆ کەوت + follow_request: کەسێک داوای کردووە Ú©Û• بەدوات بکەوێت + mention: کەسێک باسی کردووی + pending_account: هەژمارەی نوێ پێویستی بە پێداچوونەوەهەیە + reblog: کاتێک کەسێک نووسراوەی ئێوە دووبارە توت دەکاتەوە + report: گوزارشتی نوێ Ù¾ÛŽØ´Ú©Û•Ø´ کراوە + trending_tag: کاتێک هاشتاگێکی پێدانەچوو هۆگری ÙØ±Û• بوو، ئیمەیلێک بنێرە + tag: + listable: ڕیگەبدە ئەم هاشتاگە Ù„Û• پێرستی هەڵبژاردەی بەکارهێنەران Ùˆ Ù¾Û•Ú•Û•ÛŒ گەڕان نیشان بدرێت + name: هەشتاگ + trendable: ڕێگەبدە ئەم هەشتاگە Ù„Û• نووسراوەی بەرچاوکراو نیسان بدرێت + usable: ڕێگەبدە بە توتەکان بۆ بەکارهێنانی ئەم هەشتاگە + 'no': Ù†Û• + recommended: پێشنیارکراوە + required: + mark: "*" + text: پێویستە + title: + sessions: + webauthn: یەکێک Ù„Û• کلیلەکانی پاراستن بەکاربهێنە بۆ چوونە ژوورەوە + 'yes': بەڵێ diff --git a/config/locales/simple_form.ml.yml b/config/locales/simple_form.ml.yml index df04a15e85ae23f2b6589ed992bc5e71baf889df..c60cd96998866e9d07a3a9857e7910ece13cdc1b 100644 --- a/config/locales/simple_form.ml.yml +++ b/config/locales/simple_form.ml.yml @@ -14,3 +14,7 @@ ml: acct: പഴയ à´…à´‚à´—à´¤àµà´µà´¤àµà´¤à´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ പിടി account_migration: acct: à´ªàµà´¤à´¿à´¯ à´…à´‚à´—à´¤àµà´µà´¤àµà´¤à´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ പിടി + defaults: + email: à´‡-മെയിൽ വിലാസം + notification_emails: + follow: ആരോ നിങàµà´™à´³àµ† പിനàµà´¤àµà´Ÿàµ¼à´¨àµà´¨àµ diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 3f4bd9b9e68e112d9544e0c143ee5feebcd564cf..8abc9448cdd3f912708d18c12631f468c6c90e38 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -65,6 +65,10 @@ nl: data: CSV-bestand dat op een andere Mastodonserver werd geëxporteerd invite_request: text: Dit helpt ons om jouw aanvraag te beoordelen + ip_block: + comment: Optioneel. Vergeet niet te onthouden waarom je deze regel hebt toegevoegd. + severities: + sign_up_requires_approval: Nieuwe registraties vereisen jouw goedkeuring sessions: otp: 'Voer de tweestaps-aanmeldcode vanaf jouw mobiele telefoon in of gebruik een van jouw herstelcodes:' tag: @@ -89,9 +93,10 @@ nl: text: Aangepaste waarschuwing type: Actie types: - disable: Inloggen uitschakelen - none: Niets doen - silence: Negeren + disable: Bevriezen + none: Waarschuwing sturen + sensitive: Gevoelig + silence: Beperken suspend: Opschorten en onomkeerbaar accountgegevens verwijderen warning_preset_id: Gebruik een voorinstelling van een waarschuwing announcement: @@ -116,6 +121,7 @@ nl: expires_in: Vervalt na fields: Metadata profiel header: Omslagfoto + honeypot: "%{label} (niet invullen)" inbox_url: Inbox-URL van de relayserver irreversible: Verwijderen in plaats van verbergen locale: Taal van de gebruikersomgeving @@ -135,6 +141,7 @@ nl: setting_default_privacy: Standaardzichtbaarheid van jouw toots setting_default_sensitive: Media altijd als gevoelig markeren setting_delete_modal: Vraag voor het verwijderen van een toot een bevestiging + setting_disable_swiping: Swipebewegingen uitschakelen setting_display_media: Mediaweergave setting_display_media_default: Standaard setting_display_media_hide_all: Alles verbergen @@ -167,7 +174,14 @@ nl: invite: comment: Opmerking invite_request: - text: Waarom wil jij je aanmelden? + text: Waarom wil je je hier registreren? + ip_block: + comment: Opmerking + ip: IP + severities: + no_access: Toegang blokkeren + sign_up_requires_approval: Registraties beperken + severity: Regel notification_emails: digest: Periodiek e-mails met een samenvatting versturen favourite: Wanneer iemand jouw toot aan hun favorieten heeft toegevoegd @@ -188,4 +202,7 @@ nl: required: mark: "*" text: vereist + title: + sessions: + webauthn: Gebruik een van uw beveiligingssleutels om in te loggen 'yes': Ja diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index 54a5ecf01061ad0d733ef07410abf77143816adb..f4a62ac078d0c640f4d15398b8fffab29f18c613 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -3,27 +3,27 @@ nn: simple_form: hints: account_alias: - acct: Spesifiser brukernavn@domene til brukeren du vil flytte fra + acct: Spesifiser brukarnamn@domenet til brukaren du vil flytja frÃ¥ account_migration: - acct: Spesifiser brukernavn@domene til brukeren du vil flytte til + acct: Spesifiser brukarnamn@domenet til brukaren du vil flytja til account_warning_preset: - text: Du kan bruke tut syntaks, f.eks. URLer, emneknagger og nevnelser - title: Valgfritt. Ikke synlig for mottaker + text: Du kan bruka tut-syntaks, som t. d. URL-ar, emneknaggar og nemningar + title: Valfritt. Ikkje synleg for mottakar admin_account_action: - include_statuses: Brukeren vil se hvilke tuter som forÃ¥rsaket moderator-handlingen eller -advarselen - send_email_notification: Brukeren vil motta en forklaring pÃ¥ hva som har skjedd med deres bruker - text_html: Valgfritt. Du kan bruke tut syntaks. Du kan <a href="%{path}">legge til advarsels-forhÃ¥ndsinnstillinger</a> for Ã¥ spare tid - type_html: Velg hva du vil gjøre med <strong>%{acct}</strong> + include_statuses: Brukaren fÃ¥r sjÃ¥ kva tut som gjorde moderatorhandllinga eller -Ã¥tvaringa + send_email_notification: Brukaren fÃ¥r ei forklÃ¥ring av kva som har hendt med kontoen sin + text_html: Valfritt. Du kan bruka tut-syntaks. Du kan <a href="%{path}">leggja til Ã¥tvaringsførehandsinnstillingar</a> for Ã¥ spara tid + type_html: Vel det du vil gjera med <strong>%{acct}</strong> warning_preset_id: Valfritt. Du kan leggja inn eigen tekst pÃ¥ enden av føreoppsettet announcement: - all_day: Hvis noen av dem er valgt, vil kun datoene av tidsrammen bli vist - ends_at: Valgfritt. Kunngjøring vil bli automatisk avpublisert pÃ¥ dette tidspunktet - scheduled_at: La stÃ¥ tomt for Ã¥ publisere kunngjøringen umiddelbart - starts_at: Valgfritt. I tilfellet din kunngjøring er bundet til en spesifikk tidsramme - text: Du kan bruke tut syntaks. Vennligst vær oppmerksom pÃ¥ plassen som kunngjøringen vil ta opp pÃ¥ brukeren sin skjerm + all_day: NÃ¥r merka, vil berre datoane til tidsramma synast + ends_at: Valfritt. Lysinga vert teken ned av seg sjølv pÃ¥ dette tidspunktet + scheduled_at: Lat stÃ¥ blankt for Ã¥ gjeva ut lysinga med ein gong + starts_at: Valfritt. Om lysinga di er bunden til eit tidspunkt + text: Du kan bruka tut-syntaks. Ver merksam pÃ¥ plassen lysinga tek pÃ¥ brukaren sin skjerm defaults: - autofollow: Folk som lager en konto gjennom invitasjonen, vil automatisk følge deg - avatar: PNG, GIF eller JPG. Maksimalt %{size}. Vil bli nedskalert til %{dimensions}px + autofollow: Folk som lagar ein konto gjennom innbydinga fylgjer deg automatisk + avatar: PNG, GIF eller JPG. Maksimalt %{size}. Minkast til %{dimensions}px bot: Denne kontoen utfører i hovedsak automatiserte handlinger og blir kanskje ikke holdt øye med context: En eller flere sammenhenger der filteret skal gjelde current_password: For sikkerhetsgrunner, vennligst oppgi passordet til den nÃ¥værende bruker @@ -32,59 +32,62 @@ nn: discoverable: Profilmappen er en annen mÃ¥te for kontoen din Ã¥ nÃ¥ et bredere publikum pÃ¥ email: Du fÃ¥r snart ein stadfestings-e-post fields: Du kan ha opptil 4 gjenstander vist som en tabell pÃ¥ profilsiden din - header: PNG, GIF eller JPG. Maksimalt %{size}. Vil bli nedskalert til %{dimensions}px + header: PNG, GIF eller JPG. Maksimalt %{size}. Minkast til %{dimensions}px inbox_url: Kopier URLen fra forsiden til overgangen du vil bruke - irreversible: Filtrerte tuter vil ugjenkallelig forsvinne, selv om filteret senere blir fjernet - locale: SprÃ¥ket til brukergrensesnittet, e-mailer og push-varsler - locked: Krever at du manuelt godkjenner følgere + irreversible: Filtrerte tut vil verta borte for evig, sjølv om filteret vert fjerna seinare + locale: SprÃ¥ket til brukargrensesnittet, e-postar og push-varsel + locked: Krev at du manuelt godkjenner fylgjarar password: Nytt minst 8 teikn phrase: Vil bli samsvart med, uansett bruk av store/smÃ¥ bokstaver eller innholdsadvarselen til en tut - scopes: Hvilke API-er programmet vil bli gitt tilgang til. Dersom du velger et toppnivÃ¥omfang, trenger du ikke Ã¥ velge individuelle API-er. - setting_aggregate_reblogs: Ikke vis nye fremhevinger for tuter som nylig har blitt fremhever (PÃ¥virker kun nylige fremhevinger) - setting_default_sensitive: Sensitivt media blir skjult som standard og kan bli vist med et klikk - setting_display_media_default: Skjul media som er merket som sensitivt + scopes: API-ane som programmet vil fÃ¥ tilgjenge til. Ettersom du vel eit toppnivÃ¥omfang tarv du ikkje velja einskilde API-ar. + setting_aggregate_reblogs: Ikkje vis nye framhevingar for tut som nyleg har vorte heva fram (PÃ¥verkar berre nylege framhevingar) + setting_default_sensitive: Nærtakande media vert gøymd som standard og kan synast med eit klikk + setting_display_media_default: Gøym media som er merka som nærtakande setting_display_media_hide_all: Alltid skjul alt media - setting_display_media_show_all: Alltid vis media som er merket som sensitivt + setting_display_media_show_all: Vis alltid media setting_hide_network: Kven du fylgjer og kven som fylgjer deg vert ikkje vist pÃ¥ profilen din - setting_noindex: PÃ¥virker din offentlige profil og statussider - setting_show_application: Appen du brukte til Ã¥ tute vil bli vist i den detaljerte visningen til tutene dine - setting_use_blurhash: Gradientene er basert pÃ¥ fargene til de skjulte visualitetene, men gjør alle detaljer uklare - setting_use_pending_items: Skjul tidslinjeoppdateringer bak et klikk, i stedet for Ã¥ automatisk la strømmen skrolle + setting_noindex: PÃ¥verkar den offentlege profilen og statussidene dine + setting_show_application: Programmet du brukar for Ã¥ tuta synast i den detaljerte visninga av tuta dine + setting_use_blurhash: Overgangar er bygt pÃ¥ dei løynde sine leter, men gjer detaljar utydelege + setting_use_pending_items: Gøym tidslineoppdateringar ved eit klikk, i staden for Ã¥ bla ned hendestraumen automatisk username: Brukarnamnet ditt vert unikt pÃ¥ %{domain} - whole_word: NÃ¥r søkeordet eller setningen bare er alfanumerisk, aktiveres det bare hvis det samsvarer med hele ordet + whole_word: NÃ¥r søkjeordet eller setninga berre er alfanumerisk, nyttast det berre om det samsvarar med heile ordet domain_allow: - domain: Dette domenet vil være i stand til Ã¥ hente data fra denne serveren og dets innkommende data vil bli prosessert og lagret + domain: Dette domenet er i stand til Ã¥ henta data frÃ¥ denne tenaren og innkomande data vert handsama og lagra email_domain_block: - domain: Det kan være domenenavnet som vises i e-postadressen, MX-posten, som domenet bestemmer til, eller IP-en til serveren som MX-posten løser etter. De vil bli sjekket ved brukerregistrering og registrering vil bli avvist. - with_dns_records: Et forsøk pÃ¥ Ã¥ løse det gitte domenets DNS-poster vil bli gjort, og resultatene vil ogsÃ¥ bli svartelistet + domain: Dette kan vera domenenamnet som synest i e-postaddressa, MX-recorden som domenet løyser til eller IP-adressa til tenaren som MX-record løyser til. Dei sjekkast ved brukarregistrering og registretinga vert avvist. + with_dns_records: Eit forsøk pÃ¥ Ã¥ løysa gjeve domene som DNS-data vil vera gjord og resultata vert svartelista featured_tag: name: 'Kanskje du vil nytta ein av desse:' form_challenge: - current_password: Du gÃ¥r inn i et sikkert omrÃ¥de + current_password: Du gÃ¥r inn i eit trygt omrÃ¥de imports: data: CSV-fil eksportert frÃ¥ ein annan Mastodon-tenar invite_request: text: Dette kjem til Ã¥ hjelpa oss med Ã¥ gÃ¥ gjennom søknaden din + ip_block: + severities: + no_access: Blokker tilgang til alle ressurser sessions: otp: Angi tofaktorkoden fra din telefon eller bruk en av dine gjenopprettingskoder. tag: - name: Du kan bare forandre bruken av store/smÃ¥ bokstaver, f.eks. for Ã¥ gjøre det mer lesbart + name: Du kan berre endra bruken av store/smÃ¥ bokstavar, t. d. for Ã¥ gjera det meir leseleg user: - chosen_languages: Hvis noen av dem er valgt, vil kun tuter i de valgte sprÃ¥kene bli vist i de offentlige tidslinjene + chosen_languages: NÃ¥r merka vil berre tuta pÃ¥ dei valde sprÃ¥ka synast pÃ¥ offentlege tidsliner labels: account: fields: name: Merkelapp value: Innhald account_alias: - acct: Brukernavnet til den gamle brukeren + acct: Brukarnamnet pÃ¥ den gamle kontoen account_migration: - acct: Brukernavnet til den nye brukeren + acct: Brukarnamnet pÃ¥ den nye kontoen account_warning_preset: text: FøreÃ¥tstekst title: Tittel admin_account_action: - include_statuses: Inkluder rapporterte tuter i e-mailen + include_statuses: Ha med rapporterte tut i e-posten send_email_notification: Varsl brukaren med e-post text: Eigen Ã¥tvaring type: Handling @@ -95,11 +98,11 @@ nn: suspend: Utvis og slett kontodata for godt warning_preset_id: Bruk Ã¥tvaringsoppsett announcement: - all_day: Heldagshendelse - ends_at: Slutten av hendelsen + all_day: Heildagshending + ends_at: Hendinga er ferdig scheduled_at: Planlegg publisering - starts_at: Begynnelse av hendelsen - text: Kunngjøring + starts_at: Byrjing av hendinga + text: Lysing defaults: autofollow: Bed om Ã¥ fylgja kontoen din avatar: Bilete @@ -110,14 +113,14 @@ nn: context: Filtrer kontekstar current_password: Noverande passord data: Data - discoverable: Før opp denne kontoen i mappen + discoverable: Før denne kontoen opp i mappa display_name: Synleg namn email: E-post-adresse expires_in: Vert ugyldig etter fields: Profilmetadata header: Overskrift - inbox_url: URL til overgangsinnboksen - irreversible: Forkast i stedet for Ã¥ skjule + inbox_url: URL-addressen til overgangsinnboksen + irreversible: Forkast i staden for Ã¥ gøyma locale: SprÃ¥k locked: LÃ¥s konto max_uses: Grense pÃ¥ brukartal @@ -126,47 +129,56 @@ nn: otp_attempt: Tostegskode password: Passord phrase: Nykelord eller frase - setting_advanced_layout: Skru pÃ¥ det avanserte nettgrensesnittet - setting_aggregate_reblogs: Gruppefremhevinger i tidslinjer + setting_advanced_layout: Skruv pÃ¥ det avanserte nettgrensesnittet + setting_aggregate_reblogs: Gruppeframhevingar pÃ¥ tidsliner setting_auto_play_gif: Spel av animerte GIF-ar automatisk - setting_boost_modal: Vis bekreftelse før fremheving - setting_crop_images: Klipp bilder i ikke-utvidede tuter til 16:9 + setting_boost_modal: Vis stadfesting før framheving + setting_crop_images: Skjer bilete i ikkje-utvida tut til 16x9 setting_default_language: SprÃ¥k pÃ¥ innlegg setting_default_privacy: Privatliv - setting_default_sensitive: Marker alltid media som sensitivt - setting_delete_modal: Vis bekreftelse før du sletter en tut + setting_default_sensitive: Merk alltid media som nærtakande + setting_delete_modal: Vis stadfesting før du slettar eit tut + setting_disable_swiping: Skru av sveipebevegelser setting_display_media: Medievisning setting_display_media_default: Standard setting_display_media_hide_all: Gøym alle setting_display_media_show_all: Vis alle - setting_expand_spoilers: Utvid alltid tuter som er merket med innholdsadvarsler - setting_hide_network: Skjul nettverket ditt - setting_noindex: Avmeld fra søkemotorindeksering - setting_reduce_motion: Reduser bevegelser i animasjoner - setting_show_application: Skryt av appen som ble brukt til Ã¥ sende tuter + setting_expand_spoilers: Vid alltid ut tut som er merka med innhaldsÃ¥tvaringar + setting_hide_network: Gøym nettverket ditt + setting_noindex: Vel bort søkjemotorregistrering + setting_reduce_motion: Minsk rørsle i animasjonar + setting_show_application: Avdekk programmet bruka for Ã¥ senda tut setting_system_font_ui: Bruk standardskrifttypen pÃ¥ systemet setting_theme: Sidetema setting_trends: Vis kva som er populært i dag - setting_unfollow_modal: Vis bekreftelse før du slutter Ã¥ følge noen - setting_use_blurhash: Vis fargerike gradienter for skjulte media + setting_unfollow_modal: Vis stadfesting før du sluttar Ã¥ fylgja nokon + setting_use_blurhash: Vis fargerike overgangar for gøymt media setting_use_pending_items: Saktemodus severity: Alvorsgrad + sign_in_token_attempt: Trygdenykel type: Importtype username: Brukarnamn - username_or_email: Brukarnman eller E-post + username_or_email: Brukarnamn eller E-post whole_word: Heilt ord email_domain_block: - with_dns_records: Inkluder MX-poster og IP-adresser for domenet + with_dns_records: Ha med MX-recordar og IP-ar til domenet featured_tag: name: Emneknagg interactions: - must_be_follower: Blokker varslinger fra ikke-følgere - must_be_following: Blokker varslinger fra personer du ikke følger - must_be_following_dm: Blokker direkte meldinger fra personer du ikke følger + must_be_follower: Gøym varslingar frÃ¥ folk som ikkje fylgjer deg + must_be_following: Gøym varslingar frÃ¥ folk du ikkje fylgjer + must_be_following_dm: Gøym direktemeldinger frÃ¥ folk du ikkje fylgjer invite: comment: Kommentar invite_request: text: Kvifor vil du verta med? + ip_block: + comment: Kommentere + ip: IP + severities: + no_access: Blokker tilgang + sign_up_requires_approval: Begrens pÃ¥meldinger + severity: Oppføring notification_emails: digest: Send samandrag pÃ¥ e-post favourite: Send e-post nÃ¥r nokon merkjer statusen din som favoritt @@ -176,15 +188,18 @@ nn: pending_account: Send e-post nÃ¥r ein ny konto treng gjennomgang reblog: Send e-post nÃ¥r nokon framhevar statusen din report: Send e-post nÃ¥r nokon rapporterer noko - trending_tag: En ugjennomgÃ¥tt emneknagg trender + trending_tag: Ein emneknagg som ikkje er sett igjennom er pÃ¥ veg opp tag: - listable: Tillat denne emneknaggen Ã¥ vises i søk og pÃ¥ profilmappen + listable: Tillat denne emneknaggen Ã¥ synast i søk og i profilmappa name: Emneknagg - trendable: Tillat denne emneknaggen til Ã¥ vises under trender + trendable: Tillat denne emneknaggen til Ã¥ synast under trendar usable: Gje tut lov til Ã¥ nytta denne emneknaggen 'no': Nei recommended: TilrÃ¥dt required: mark: "*" text: obligatorisk + title: + sessions: + webauthn: Bruk en av sikkerhetsnøklene dine til Ã¥ logge pÃ¥ 'yes': Ja diff --git a/config/locales/simple_form.no.yml b/config/locales/simple_form.no.yml index 0210e5a6e8d184f072eb2869405c3526c7c64799..cdf3d61e8433ec7023acc21c7fb62ae8f869a949 100644 --- a/config/locales/simple_form.no.yml +++ b/config/locales/simple_form.no.yml @@ -65,6 +65,9 @@ data: CSV-fil eksportert fra en annen Mastodon-instans invite_request: text: Dette vil hjelpe oss med Ã¥ gjennomgÃ¥ din søknad + ip_block: + severities: + no_access: Blokker tilgang til alle ressurser sessions: otp: Angi tofaktorkoden fra din telefon eller bruk en av dine gjenopprettingskoder. tag: @@ -135,6 +138,7 @@ setting_default_privacy: Postintegritet setting_default_sensitive: Marker alltid media som sensitivt setting_delete_modal: Vis bekreftelse før du sletter en tut + setting_disable_swiping: Skru av sveipebevegelser setting_display_media: Mediavisning setting_display_media_default: Standard setting_display_media_hide_all: Skjul alle @@ -151,6 +155,7 @@ setting_use_blurhash: Vis fargerike gradienter for skjulte media setting_use_pending_items: Saktemodus severity: Alvorlighetsgrad + sign_in_token_attempt: Sikkerhetskode type: Importeringstype username: Brukernavn username_or_email: Brukernavn eller E-post @@ -167,6 +172,13 @@ comment: Kommentar invite_request: text: Hvorfor vil du bli med? + ip_block: + comment: Kommentere + ip: IP + severities: + no_access: Blokker tilgang + sign_up_requires_approval: Begrens pÃ¥meldinger + severity: Oppføring notification_emails: digest: Send sammendrag pÃ¥ e-post favourite: Send e-post nÃ¥r noen setter din status som favoritt @@ -187,4 +199,7 @@ required: mark: "*" text: obligatorisk + title: + sessions: + webauthn: Bruk en av sikkerhetsnøklene dine til Ã¥ logge pÃ¥ 'yes': Ja diff --git a/config/locales/simple_form.oc.yml b/config/locales/simple_form.oc.yml index 16bde88ce03c63cb41fecd16aebc49436ad27448..79c621ee2429ffd10125477ae60d8d6c9e5ed5a8 100644 --- a/config/locales/simple_form.oc.yml +++ b/config/locales/simple_form.oc.yml @@ -22,9 +22,9 @@ oc: starts_at: Opcional. Se per cas vòstra anóncia es ligada a un interval de temps especific text: Podètz utilizar la sintaxi dels tuts. Gardatz al cap qu’aquesta anóncia ocuparà la fenèstra de l’utilizaire defaults: - autofollow: Lo monde que se marcan grà cia a l’invitacion vos segrà n automaticament + autofollow: Lo mond que se marcan grà cia a l’invitacion vos segrà n automaticament avatar: PNG, GIF o JPG. Maximum %{size}. Serà retalhat en %{dimensions}px - bot: Avisar lo monde qu’aqueste compte es pas d’una persona + bot: Avisar lo mond qu’aqueste compte es pas d’una persona context: Un o mai de contèxtes ont lo filtre deuriá s’aplicar current_password: Per de rasons de seguretat volgatz picar lo senhal del compte actual current_username: Per confirmar, volgatz picar lo nom d’utilizaire del compte actual @@ -45,7 +45,7 @@ oc: setting_display_media_default: Rescondre los mèdias marcats coma sensibles setting_display_media_hide_all: Totjorn rescondre los mèdias setting_display_media_show_all: Totjorn mostrar los mèdias marcats coma sensibles - setting_hide_network: Vòstre perfil mostrarà pas los que vos sègon e lo monde que seguètz + setting_hide_network: Vòstre perfil mostrarà pas los que vos sègon e lo mond que seguètz setting_noindex: Aquò es destinat a vòstre perfil public e vòstra pagina d’estatuts setting_show_application: Lo nom de l’aplicacion qu’utilizatz per publicar serà mostrat dins la vista detalhada de vòstres tuts setting_use_blurhash: Los degradats venon de las colors de l’imatge rescondut en enfoscar los detalhs @@ -65,8 +65,17 @@ oc: data: Fichièr CSV exportat d’un autre servidor Mastodon invite_request: text: Aquò nos ajudarà per validar vòstra demanda + ip_block: + comment: Opcional. Remembratz-vos perque ajustèretz aquesta règla. + expires_in: Las adreças IP son una ressorsa finida, son de còps partejadas e cà mbian sovent de mans. Per aquesta rason, los blocatges d’IP sens fin son pas recomandats. + ip: Dintratz una adreça IPv4 o IPv6. Podètz blocar de plajas entièras en utilizant la sintaxi CIDR. Agachatz de pas vos blocar defòra ! + severities: + no_access: Blocar l’accès a totas las ressorsas + sign_up_requires_approval: Las inscripcions novèlas requerirà n vòstra validacion + severity: Causissètz que far amb las requèstas d’aquesta IP sessions: otp: 'Picatz lo còdi d’autentificacion en dos temps (Two factor code) de vòstra aplicacion mobil o utilizatz un de vòstres còdis de recuperacion :' + webauthn: S’es una clau USB asseguratz-vos de l’inserir, e se cal de la picanhejar. tag: name: Podètz pas que cambiar la talha de las letras, per exemple, per que sián de melhor legir user: @@ -91,6 +100,7 @@ oc: types: disable: Desactivar none: Far pas res + sensitive: Sensible silence: Metre en silence suspend: Suspendre e escafar per de bon las donadas del compte warning_preset_id: Utilizar un avertiment predefinit @@ -116,6 +126,7 @@ oc: expires_in: Expira aprèp fields: Metadonada del perfil header: Bandièra + honeypot: "%{label} (emplenar pas)" inbox_url: URL de la bóstia de recepcion del relai irreversible: Suprimir allòc de rescondre locale: Lenga de l’interfà cia @@ -135,6 +146,7 @@ oc: setting_default_privacy: Confidencialitat dels tuts setting_default_sensitive: Totjorn marcar los mèdias coma sensibles setting_delete_modal: Mostrar una fenèstra de confirmacion abans de suprimir un estatut + setting_disable_swiping: Desactivar las accions en lisant setting_display_media: Afichatge dels mèdias setting_display_media_default: Defaut setting_display_media_hide_all: O rescondre tot @@ -163,11 +175,18 @@ oc: interactions: must_be_follower: Blocar las notificacions del mond que vos sègon pas must_be_following: Blocar las notificacions del mond que seguètz pas - must_be_following_dm: Blocar los messatges del monde que seguètz pas + must_be_following_dm: Blocar los messatges del mond que seguètz pas invite: comment: Comentari invite_request: text: Perqué volètz vos marcar ? + ip_block: + comment: Comentari + ip: IP + severities: + no_access: Blocar l’accès + sign_up_requires_approval: Limitar las inscripcions + severity: Règla notification_emails: digest: Enviar un corrièl recapitulatiu favourite: Enviar un corrièl quand qualqu’un plaça vòstre estatut en favorit @@ -188,4 +207,7 @@ oc: required: mark: "*" text: requesit + title: + sessions: + webauthn: Utilizatz una de vòstras clau de seguretat per vos identificar 'yes': Ã’c diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index d2a1e9386ef47e8a30453f7cc4ddc86fcc8abf24..6fc33ab08ae2a3b29d5bdc90a9cd5752422e8919 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -65,8 +65,17 @@ pl: data: Plik CSV wyeksportowany z innego serwera Mastodona invite_request: text: To pomoże nam w recenzji Twojej aplikacji + ip_block: + comment: Niewymagane. PamiÄ™taj, dlaczego dodaÅ‚eÅ› tÄ™ regułę. + expires_in: Adresy IP to ograniczony zasób, czasami sÄ… współdzielone i czÄ™sto zmieniajÄ… wÅ‚aÅ›ciciela. Z tego powodu blokady adresów IP nie sÄ… zalecane. + ip: Wprowadź adres IPv4 lub IPv6. Możesz zablokować caÅ‚e zakresy za pomocÄ… skÅ‚adni CIDR. Uważaj, aby siÄ™ nie zablokować! + severities: + no_access: Zablokuj dostÄ™p do wszystkich zasobów + sign_up_requires_approval: Nowe rejestracje bÄ™dÄ… wymagać twojej zgody + severity: Wybierz co ma siÄ™ stać z żadaniami z tego adresu IP sessions: otp: 'Wprowadź kod weryfikacji dwuetapowej z telefonu lub wykorzystaj jeden z kodów zapasowych:' + webauthn: Jeżeli jest to klucz USB, upewnij siÄ™, że go wÅ‚ożyÅ‚eÅ› i, jeÅ›li to konieczne, naciÅ›nij go. tag: name: Możesz zmieniać tylko wielkość liter, np. aby byÅ‚y bardziej widoczne user: @@ -91,6 +100,7 @@ pl: types: disable: Wyłącz none: Nie rób niczego + sensitive: Wrażliwe silence: Wycisz suspend: ZawieÅ› i nieodwracalnie usuÅ„ dane konta warning_preset_id: Użyj szablonu ostrzeżenia @@ -116,6 +126,7 @@ pl: expires_in: WygaÅ›nie po fields: Metadane profilu header: Nagłówek + honeypot: "%{label} (nie wypeÅ‚niaj)" inbox_url: Adres skrzynki przekaźnika irreversible: Usuwaj zamiast ukrywać locale: JÄ™zyk interfejsu @@ -135,6 +146,7 @@ pl: setting_default_privacy: Widoczność wpisów setting_default_sensitive: Zawsze oznaczaj zawartość multimedialnÄ… jako wrażliwÄ… setting_delete_modal: Pytaj o potwierdzenie przed usuniÄ™ciem wpisu + setting_disable_swiping: Wyłącz ruchy przesuwania setting_display_media: WyÅ›wietlanie zawartoÅ›ci multimedialnej setting_display_media_default: DomyÅ›lne setting_display_media_hide_all: Ukryj wszystko @@ -168,6 +180,13 @@ pl: comment: Komentarz invite_request: text: Czemu chcesz dołączyć? + ip_block: + comment: Skomentuj + ip: Adres IP + severities: + no_access: Zablokuj dostÄ™p + sign_up_requires_approval: Ogranicz rejestracje + severity: ReguÅ‚a notification_emails: digest: WysyÅ‚aj podsumowania e-mailem favourite: Powiadamiaj mnie e-mailem, gdy ktoÅ› polubi mój wpis @@ -188,4 +207,7 @@ pl: required: mark: "*" text: pole wymagane + title: + sessions: + webauthn: Użyj jednego ze swoich kluczy bezpieczeÅ„stwa, aby siÄ™ zalogować 'yes': Tak diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index c112ad4bc65445f75552bf7419c0852cb4bfe27c..574a3e3dc9cc4e5561bc55edae37cf0a6186c7ad 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -55,7 +55,7 @@ pt-BR: domain_allow: domain: Este domÃnio poderá obter dados deste servidor e os dados recebidos dele serão processados e armazenados email_domain_block: - domain: Este pode ser o nome de domÃnio que aparece no endereço de e-mail, o registro MX para o qual o domÃnio resolve, ou o IP do servidor para o qual o registro MX resolve. Esses vão ser verificados no momento da cadastro do usuário e o cadastro será rejeitado. + domain: Este pode ser o nome de domÃnio que aparece no endereço de e-mail, o registro MX para o qual o domÃnio resolve, ou o IP do servidor para o qual o registro MX resolve. Esses vão ser verificados no momento de registro do usuário e o registro será rejeitado. with_dns_records: Será feita uma tentativa de resolver os registros DNS do domÃnio em questão e os resultados também serão colocados na lista negra featured_tag: name: 'Você pode querer usar um destes:' @@ -64,9 +64,18 @@ pt-BR: imports: data: Arquivo CSV exportado de outra instância Mastodon invite_request: - text: Isso nos ajudará a revisar seu aplicativo + text: Isso vai nos ajudar a revisar sua aplicação + ip_block: + comment: Opcional. Lembrar de por que você adicionou esta regra. + expires_in: Endereços IP são um recurso limitado, algumas vezes são compartilhados e muitas vezes mudam de mãos. Por esse motivo, blocos de IP indefinidos não são recomendados. + ip: Digite um endereço IPv4 ou IPv6. Você pode bloquear intervalos inteiros usando a sintaxe CIDR. Tenha cuidado para não bloquear a si mesmo! + severities: + no_access: Bloquear o acesso a todos os recursos + sign_up_requires_approval: Novos registros exigirão sua aprovação + severity: Escolha o que acontecerá com as solicitações deste IP sessions: otp: 'Digite o código de dois fatores gerado pelo aplicativo no seu celular ou use um dos códigos de recuperação:' + webauthn: Se for uma chave USB tenha certeza de inseri-la e, se necessário, tocar nela. tag: name: Você pode mudar a capitalização das letras, por exemplo, para torná-la mais legÃvel user: @@ -89,8 +98,9 @@ pt-BR: text: Aviso personalizado type: Ação types: - disable: Bloquear conta + disable: Congelar none: Não fazer nada + sensitive: SensÃvel silence: Silenciar suspend: Banir e excluir irreversivelmente dados da conta warning_preset_id: Usar um aviso pré-definido @@ -116,6 +126,7 @@ pt-BR: expires_in: Expira em fields: Metadados do perfil header: Cabeçalho + honeypot: "%{label} (não preencher)" inbox_url: Link da caixa de entrada do repetidor irreversible: Ignorar ao invés de ocultar locale: Idioma da interface @@ -135,6 +146,7 @@ pt-BR: setting_default_privacy: Privacidade dos toots setting_default_sensitive: Sempre marcar mÃdia como sensÃvel setting_delete_modal: Solicitar confirmação antes de excluir toot + setting_disable_swiping: Desabilitar movimentos deslizantes setting_display_media: Exibição das mÃdias setting_display_media_default: Padrão setting_display_media_hide_all: Ocultar tudo @@ -168,6 +180,13 @@ pt-BR: comment: Comentário invite_request: text: Por que você deseja criar uma conta aqui? + ip_block: + comment: Comentário + ip: IP + severities: + no_access: Bloquear acesso + sign_up_requires_approval: Limitar registros + severity: Regra notification_emails: digest: Enviar e-mails de resumo favourite: Enviar e-mail quando alguém favoritar seus toots @@ -188,4 +207,7 @@ pt-BR: required: mark: "*" text: obrigatório + title: + sessions: + webauthn: Utilize uma das suas chaves de segurança para entrar 'yes': Sim diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index d3cf5911afae9592684111482d73a18d983df7ad..869ecaddcc118fef8c7fd9d5c3c64cfeb454927e 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -65,8 +65,17 @@ pt-PT: data: Arquivo CSV exportado de outra instância do Mastodon invite_request: text: Isto vai ajudar-nos a rever o seu pedido + ip_block: + comment: Opcional. Relembre-se por que adicionou esta regra. + expires_in: Endereços IP são um recurso limitado, algumas vezes são compartilhados e muitas vezes mudam de mãos. Por essa razão, bloqueios de IP indefinidos não são recomendados. + ip: Introduza um endereço IPv4 ou IPv6. Pode bloquear intervalos inteiros usando a sintaxe CIDR. Tenha cuidado para não se bloquear a sà mesmo! + severities: + no_access: Bloquear o acesso a todos os recursos + sign_up_requires_approval: Novas inscrições requererão a sua aprovação + severity: Escolha o que acontecerá com as solicitações deste IP sessions: otp: 'Insere o código de autenticação em dois passos gerado pelo teu telemóvel ou usa um dos teus códigos de recuperação:' + webauthn: Se for uma chave USB tenha certeza de inseri-la e, se necessário, toque nela. tag: name: Só pode alterar a capitalização das letras, por exemplo, para torná-las mais legÃveis user: @@ -91,6 +100,7 @@ pt-PT: types: disable: Desactivar none: Não fazer algo + sensitive: SensÃvel silence: Silenciar suspend: Suspender e apagar irreversivelmente os dados da conta warning_preset_id: Usar um aviso pré-definido @@ -116,6 +126,7 @@ pt-PT: expires_in: Expira em fields: Meta-dados de perfil header: Cabeçalho + honeypot: "%{label} (não preencher)" inbox_url: URL da caixa de entrada do repetidor irreversible: Expandir em vez de esconder locale: Idioma @@ -135,6 +146,7 @@ pt-PT: setting_default_privacy: Privacidade da publicação setting_default_sensitive: Sempre marcar media como sensÃvel setting_delete_modal: Solicitar confirmação antes de eliminar uma publicação + setting_disable_swiping: Desactivar os movimentos de deslize setting_display_media: Visualização de media setting_display_media_default: Pré-definição setting_display_media_hide_all: Esconder todos @@ -168,6 +180,13 @@ pt-PT: comment: Comentário invite_request: text: Porque se quer juntar a nós? + ip_block: + comment: Comentário + ip: IP + severities: + no_access: Bloquear acesso + sign_up_requires_approval: Limitar inscrições + severity: Regra notification_emails: digest: Enviar e-mails de resumo favourite: Enviar e-mail quando alguém adiciona uma publicação tua aos favoritos @@ -188,4 +207,7 @@ pt-PT: required: mark: "*" text: obrigatório + title: + sessions: + webauthn: Utilize uma das suas chaves de segurança para entrar 'yes': Sim diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index 6cc565228fcd1e4d07118551d2ae76863c207482..5baa9d46e8a17c862084e85b148585b921f78d60 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -65,8 +65,17 @@ ru: data: Файл CSV, ÑкÑпортированный Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ узла Mastodon. invite_request: text: Ðто поможет нам раÑÑмотреть вашу заÑвку + ip_block: + comment: ÐеобÑзательно. Заметка на будущее, почему вы добавили Ñто правило. + expires_in: IP адреÑа — веÑьма ограниченный реÑурÑ, иногда они разделÑÑŽÑ‚ÑÑ Ð¼ÐµÐ¶Ð´Ñƒ абонентами и чаÑто менÑÑŽÑ‚ владельца. По Ñтой причине блокировки на неопределённые Ñроки не рекомендуютÑÑ. + ip: Введите IPv4 или IPv6 адреÑ. Ð’Ñ‹ можете блокировать целые диапазоны, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ÑинтакÑÐ¸Ñ CIDR. Будьте оÑторожны, не заблокируйте Ñамого ÑебÑ! + severities: + no_access: Заблокировать доÑтуп ко вÑем реÑурÑам + sign_up_requires_approval: Ðовые региÑтрации потребуют вашего Ð¾Ð´Ð¾Ð±Ñ€ÐµÐ½Ð¸Ñ + severity: Выберите, что будет проиÑходить Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñами Ñ Ñтого IP sessions: otp: 'Введите код двухфакторной аутентификации, Ñгенерированный в мобильном приложении, или иÑпользуйте один из ваших кодов воÑÑтановлениÑ:' + webauthn: ЕÑли Ñто ключ USB, не забудьте его вÑтавить и, при необходимоÑти, нажмите на него. tag: name: Ð’Ñ‹ можете изменить только региÑтр букв чтобы, например, Ñделать тег более читаемым user: @@ -91,6 +100,7 @@ ru: types: disable: Заморозить none: Ðичего не делать + sensitive: Деликатный silence: Скрыть suspend: Заблокировать и безвозвратно удалить вÑе данные учётной запиÑи warning_preset_id: ИÑпользовать шаблон @@ -116,6 +126,7 @@ ru: expires_in: ИÑтекает через fields: Метаданные Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ header: Шапка + honeypot: "%{label} (не заполнÑть)" inbox_url: URL Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñщих от ретранÑлÑторов irreversible: УдалÑть, а не Ñкрывать locale: Язык интерфейÑа @@ -135,6 +146,7 @@ ru: setting_default_privacy: ВидимоÑть поÑтов setting_default_sensitive: Ð’Ñегда отмечать медиафайлы как деликатные setting_delete_modal: Ð’Ñегда Ñпрашивать перед удалении поÑта + setting_disable_swiping: Отключить анимацию ÑÐ¼Ð°Ñ…Ð¸Ð²Ð°Ð½Ð¸Ñ setting_display_media: Отображение медиафайлов setting_display_media_default: По умолчанию setting_display_media_hide_all: Скрывать вÑе @@ -168,6 +180,13 @@ ru: comment: Комментарий invite_request: text: Почему вы хотите приÑоединитьÑÑ Ðº нам? + ip_block: + comment: Комментарий + ip: IP + severities: + no_access: Блокировать доÑтуп + sign_up_requires_approval: Ограничить региÑтрации + severity: Правило notification_emails: digest: ПриÑылать дайджеÑÑ‚ по e-mail favourite: Ваш поÑÑ‚ добавили в избранное @@ -188,4 +207,7 @@ ru: required: mark: "*" text: обÑзательно + title: + sessions: + webauthn: ИÑпользуйте один из ваших ключей безопаÑноÑти Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему 'yes': Да diff --git a/config/locales/simple_form.sa.yml b/config/locales/simple_form.sa.yml new file mode 100644 index 0000000000000000000000000000000000000000..07ea4372a3a109674214ba80f2070c9f99fb872d --- /dev/null +++ b/config/locales/simple_form.sa.yml @@ -0,0 +1 @@ +sa: diff --git a/config/locales/simple_form.sc.yml b/config/locales/simple_form.sc.yml index 91bd6d92f04580bfea64f85ac0291ed4a4c1fb7c..99d5ab4294bd66743fc22d91369c339790ac0efa 100644 --- a/config/locales/simple_form.sc.yml +++ b/config/locales/simple_form.sc.yml @@ -1 +1,213 @@ +--- sc: + simple_form: + hints: + account_alias: + acct: Dislinda su nòmineutente@domìniu de su contu dae su cale ti boles mòere + account_migration: + acct: Dislinda su nòmineutente@domìniu de su contu cara a su cale ti boles mòere + account_warning_preset: + text: Podes impreare sa sintassi de is tuts, che a is URL, is etichetas e is mentovos + title: Optzionale. Invisìbile a s'à tera persone + admin_account_action: + include_statuses: S'utente at a bìdere is tuts chi ant causadu s'atzione o s'avisu de moderatzione + send_email_notification: S'utente at a retzire un'ispiegatzione de su chi siat sutzèdidu in su contu suo + text_html: Optzionale. Podes impreare sa sintassi de is tuts. Podes <a href="%{path}">agiùnghere avisos pre-impostados</a> pro risparmiare tempus + type_html: Sèbera ite fà ghere cun <strong>%{acct}</strong> + warning_preset_id: Optzionale. Podes ancora agiùnghere testu personalizadu a s'acabu de cussu predefinidu + announcement: + all_day: Si est marcadu, ant a èssere ammustradas isceti is datas de s'intervallu de tempus + ends_at: Optzionale. S'annùntziu at a acabbare de abarrare publicadu in custu momentu + scheduled_at: Lassa bòidu pro publicare s'annùntziu immediatamente + starts_at: Optzionale. S'in casu chi s'annùntziu tuo siat ligadu a un'intervallu de tempus ispetzìficu + text: Podes impreare sa sintassi de is tuts. Dae cara a su tretu chi s'annùntziu at a pigare in s'ischermu de s'utente + defaults: + autofollow: Is persones chi s'ant a registrare pro mèdiu de s'invitu t'ant a sighire in manera automà tica + avatar: PNG, GIF o JPG. Mà ssimu %{size}. Ant a èssere iscaladas a %{dimensions}px + bot: Custu contu faghet pro su prus atziones automatizadas e diat pòdere no èssere monitoradu + context: Unu o prus cuntestos in ue su filtru si diat dèpere aplicare + current_password: Pro chistiones de seguresa inserta sa crae de intrada de su contu atuale + current_username: Pro cunfirmare inserta su nòmine utente de su contu atuale + digest: Imbiadu isceti a pustis de unu perìodu longu de inatividade, e isceti si as retzidu carchi messà giu personale cando non bi fias + discoverable: Sa cartella de is profilos est un'à tera manera pro fà ghere otènnere unu pùblicu prus mannu a su contu tuo + email: T'amus a mandare unu messà giu eletrònicu de cunfirma + fields: Podes tènnere finas a 4 elementos ammustrados in una tabella in su profilu tuo + header: PNG, GIF o JPG. Mà ssimu %{size}. Ant a èssere iscaladas a %{dimensions}px + inbox_url: Còpia s'URL dae sa pà gina printzipale de su ripetidore chi boles impreare + irreversible: Is tuts filtrados ant a isparèssere in manera irreversìbile, fintzas si prus a tardu s'at a bogare su filtru + locale: Sa limba de s'interfache de s'utente, de is lìteras de posta eletrònica e de is notìficas push + locked: Tenet bisòngiu chi aproves a manu is sighiduras + password: Imprea a su mancu 8 carà teres + phrase: Su cunfrontu s'at a fà ghere chena pigare in cunsideru si su testu de sa publicatzione est minùsculu o majùsculu o si tenet un'avisu de cuntenutu + scopes: A ite API s'aplicatzione at a pòdere atzèdere. Si seletziones un'à mbitu de livellu artu no tenes bisòngiu de nde seletzionare de sìngulos. + setting_aggregate_reblogs: No ammustres cumpartziduras noas pro tuts chi sunt istados cumpartzidos dae pagu (tenet efetu isceti pro is cumpartziduras retzidas noas) + setting_default_sensitive: Is elementos multimediales sensìbiles benint cuados dae is cunfiguratziones predefinidas e si podent rivelare cun un'incarcu + setting_display_media_default: Cua elementos multimediales marcados comente sensìbiles + setting_display_media_hide_all: Cua semper is elementos multimediales + setting_display_media_show_all: Ammustra semper is elementos multimediales + setting_hide_network: Sa gente chi sighis o chi ti sighit no at a èssere ammustrada in su profilu tuo + setting_noindex: Tenet efetu in su profilu pùblicu tuo e in is pà ginas de is istados + setting_show_application: S'aplicatzione chi impreas pro publicare tuts at a èssere ammustrada in sa visualizatzione de detà lliu de is tuts + setting_use_blurhash: Is gradientes sunt basados in subra de is colores de is immà gines cuadas ma imbelant totu is minujas + setting_use_pending_items: Cua is atualizatziones in segus de un'incarcu imbetzes de iscùrrere in automà ticu su flussu de publicatziones + username: Su nòmine de utente tuo at a èssere ùnicu in %{domain} + whole_word: Cando sa parà ula o sa frà sia crae est alfanumèrica ebbia s'at a aplicare isceti si currispondet a sa parà ula intrea + domain_allow: + domain: Custu domìniu at a pòdere recuperare datos dae custu serbidore e is datos in intrada dae cue ant a èssere protzessados e archiviados + email_domain_block: + domain: Custu podet èssere su nòmine de domìniu chi benit ammustradu in s'indiritzu de posta eletrònica, in su registru MX in ue si risolvet su domìniu o s'IP de su serbidore in ue si risolvet su registru MX. Custos ant a èssere verificados a pustis de sa registratzione e sa registratzione at a èssere refudada. + with_dns_records: S'at a fà ghere unu tentativu de risòlvere is registros DNS de su domìniu e fintzas is risultados ant a èssere blocados + featured_tag: + name: 'Forsis boles impreare unu de custos:' + form_challenge: + current_password: Ses intrende in un'à rea segura + imports: + data: Archìviu CSV esportadu dae un'à teru serbidore de Mastodon + invite_request: + text: Custu si at a agiudare a revisionare sa dimanda tua + ip_block: + comment: Optzionale. Regorda pro ite as agiuntu custa règula. + expires_in: Is indiritzos IP sunt una risursa limitada, fatu-fatu benint cumpartzidos e podent mudare de mere. Pro custa resone is blocos indefinidos de indiritzos IP non sunt racumandados. + ip: Inserta un'indiritzu IPv4 o IPv6. Podes blocare intervallos intreos impreende sa sintassi CIDR. Dae cara e non ti bloches a sa sola! + severities: + no_access: Bloca s'atzessu a totu is resursas + sign_up_requires_approval: As a dèpere aprovare is iscritziones noas + severity: Sèbera ite at a sutzèdere cun is rechestas de custa IP + sessions: + otp: 'Inserta su còdighe de atzessu in duos passos generadu dae s''aplicatzione mòbile tua o imprea unu de custos còdighes de recùperu:' + webauthn: Si est una crae USB assegura·ti de l'insertare e, si serbit, de la tocare. + tag: + name: Podes isceti cambiare su minùsculu/maiùsculu de is lìteras, a esèmpiu, pro fà ghere in manera chi siant prus fà tziles de lèghere + user: + chosen_languages: Cando est incarcadu, isceti is tuts in is limbas ischertadas ant a èssere ammustrados in is lìnias de tempus pùblicas + labels: + account: + fields: + name: Eticheta + value: Cuntenutu + account_alias: + acct: Nòmine utente de su contu betzu + account_migration: + acct: Nòmine utente de su contu nou + account_warning_preset: + text: Testu predefinidu + title: Tìtulu + admin_account_action: + include_statuses: Include is tuts sinnalados in sa lìtera eletrònica + send_email_notification: Notìfica s'utente pro mèdiu de posta eletrònica + text: Avisu personalizadu + type: Atzione + types: + disable: Disativa + none: Imbia un'avisu + sensitive: Sensìbile + silence: A sa muda + suspend: Suspende + warning_preset_id: Imprea un'avisu predefinidu + announcement: + all_day: Eventu de totu sa die + ends_at: Fine de s'eventu + scheduled_at: Programma sa publicatzione + starts_at: Cumintzu de s'eventu + text: Annùntziu + defaults: + autofollow: Invita a sighire su contu tuo + avatar: Immà gine de profilu + bot: Custu contu est unu bot + chosen_languages: Filtra limbas + confirm_new_password: Cunfirma sa crae noa + confirm_password: Cunfirma sa crae + context: Filtra cuntestos + current_password: Crae atuale + data: Data + discoverable: Ammustra custu contu in su diretòriu + display_name: Nòmine visìbile + email: Indiritzu de posta eletrònica + expires_in: Iscadit a pustis de + fields: Metadatos de su profilu + header: Intestatzione + honeypot: "%{label} (non compiles)" + inbox_url: URL de sa cartella de intrada de su ripetidore + irreversible: Cantzella imbetzes de cuare + locale: Limba de s'interfache + locked: Bloca su contu + max_uses: Nùmeru mà ssimu de impreos + new_password: Crae noa + note: Biografia + otp_attempt: Còdighe in duos fatores + password: Crae + phrase: Parà ula o frà sia crae + setting_advanced_layout: Abìlita s'interfache web avantzada + setting_aggregate_reblogs: Agrupa is cumpartziduras in is lìnias de tempus + setting_auto_play_gif: Riprodui is GIFs animadas in manera automà tica + setting_boost_modal: Ammustra una ventanedda de dià logu de cunfirma in antis de cumpartzire + setting_crop_images: Retà llia is immà gines in is tuts no ismanniados a 16x9 + setting_default_language: Limba de publicatzione + setting_default_privacy: Riservadesa de publicatzione + setting_default_sensitive: Marca semper is elementos multimediales comente sensìbiles + setting_delete_modal: Ammustra una ventanedda de dià logu de cunfirma in antis de cantzellare unu tut + setting_disable_swiping: Disabìlita is movimentos de trisinadura + setting_display_media: Visualizatzione de is elementos multimediales + setting_display_media_default: Predefinida + setting_display_media_hide_all: Cua totu + setting_display_media_show_all: Ammustra totu + setting_expand_spoilers: Ismà nnia semper is tuts marcados cun avisos de cuntenutu + setting_hide_network: Cua sa retza tua + setting_noindex: Pedi de non ti fà ghere inditzizare dae is motores de chirca + setting_reduce_motion: Mìnima su movimentu in is animatziones + setting_show_application: Rivela s'aplicatzione impreada pro imbiare tuts + setting_system_font_ui: Imprea su carà tere predefinidu de su sistema + setting_theme: Tema de su situ + setting_trends: Ammustra is tendèntzias de oe + setting_unfollow_modal: Ammustra una ventanedda de dià logu de cunfirma in antis de acabbare de sighire a calicunu + setting_use_blurhash: Ammustra gradientes colorados pro is elementos multimediales cuados + setting_use_pending_items: Modalidade lenta + severity: Severidade + sign_in_token_attempt: Còdighe de seguresa + type: Casta de importatzione + username: Nòmine utente + username_or_email: Nòmine utente o indiritzu de posta eletrònica + whole_word: Parà ula intrea + email_domain_block: + with_dns_records: Include registros MX e indiritzos IP de su domìniu + featured_tag: + name: Eticheta + interactions: + must_be_follower: Bloca is notìficas dae chie non ti sighit + must_be_following: Bloca is notìficas dae persones chi non sighis + must_be_following_dm: Bloca is messà gios diretos dae persones chi non sighis + invite: + comment: Cummenta + invite_request: + text: Proite ti cheres iscrìere? + ip_block: + comment: Cummentu + ip: IP + severities: + no_access: Bloca s'atzessu + sign_up_requires_approval: Lìmita is registratziones + severity: Règula + notification_emails: + digest: Imbia lìteras eletrònicas de resumu + favourite: Calicunu at postu s'istadu tuo in is preferidos suos + follow: Calicunu at incumentzadu a ti sighire + follow_request: Calicunu at pedidu de ti sighire + mention: Calicunu t'at mentovadu + pending_account: Unu contu nou bisòngiat de una revisione + reblog: Calicunu at cumpartzidu s'istadu tuo + report: Est istadu imbiadu unu raportu nou + trending_tag: Un'eticheta non revisionada est in tendèntzia + tag: + listable: Permite a cust'eticheta de apà rrere in is chircas e in sa cartella de is profilos + name: Eticheta + trendable: Permite a cust'eticheta de apà rrere in is tendèntzias + usable: Permite a is tuts de impreare cust'eticheta + 'no': Nono + recommended: Racumandadu + required: + mark: "*" + text: netzessà riu + title: + sessions: + webauthn: Imprea una de is craes de seguresa tuas pro intrare + 'yes': Eja diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index 0093edde28c36b4c70b9cc6386f779800fd8062e..18211e69ea0d6713aa9c69b000dd5e6a44c9a7f6 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -65,8 +65,17 @@ sq: data: Kartelë CSV të eksportuar nga një tjetër shërbyes Mastodon invite_request: text: Kjo do të na ndihmojë të shqyrtojmë aplikimin tuaj + ip_block: + comment: Opsionale. Mbani mend pse e shtuat këtë rregull. + expires_in: Adresat IP janë një burim i kufizuar, shpesh janë të përbashkëta dh ndryshojnë zot shpesh. Për këtë arsye, nuk rekomandohem blloqe IP të pafund. + ip: Jepni një adresë IPv4 ose IPv6. Duke përdorur sintaksën CIDR, mund të bllokoni intervale të tëra. Hapni sytë mos lini veten jashtë! + severities: + no_access: Blloko hyrje në krejt burimet + sign_up_requires_approval: Regjistrime të reja do të duan miratimin tuaj + severity: Zgjidhni ç’do të ndodhë me kërkesa nga kjo IP sessions: otp: 'Jepni kodin dyfaktorësh të prodhuar nga aplikacioni i telefonit tuaj ose përdorni një nga kodet tuaj të rikthimeve:' + webauthn: Nëse është një diskth USB, sigurohuni se e keni futur dhe, në qoftë e nevojshme, prekeni. tag: name: Mund të ndryshoni shkronjat vetëm nga të mëdha në të vogla ose anasjelltas, për shembull, për t’i bërë më të lexueshme user: @@ -91,6 +100,7 @@ sq: types: disable: Çaktivizo hyrjen none: Mos bëj gjë + sensitive: Rezervat silence: Heshtje suspend: Pezulloje dhe fshi në mënyrë të pakthyeshme të dhënat e llogarisë warning_preset_id: Përdor një sinjalizim të paracaktuar @@ -116,6 +126,7 @@ sq: expires_in: Skadon pas fields: Tejtëdhëna profili header: Krye + honeypot: "%{label} (mos plotësoni gjë këtu)" inbox_url: URL e Të marrëve të relesë irreversible: Heqje, në vend se fshehje locale: Gjuhë ndërfaqeje @@ -135,6 +146,7 @@ sq: setting_default_privacy: Privatësi postimi setting_default_sensitive: Mediave vëru përherë shenjë si rezervat setting_delete_modal: Shfaq dialog ripohimi përpara fshirjes së një mesazhi + setting_disable_swiping: Çaktivizo lëvizje me fërkim setting_display_media: Shfaqje mediash setting_display_media_default: Parazgjedhje setting_display_media_hide_all: Fshihi krejt @@ -168,6 +180,13 @@ sq: comment: Komentoni invite_request: text: Pse doni të bëheni pjesë? + ip_block: + comment: Koment + ip: IP + severities: + no_access: Bllokoji hyrjen + sign_up_requires_approval: Kufizo regjistrime + severity: Rregull notification_emails: digest: Dërgo email-e përmbledhës favourite: Dikush parapëlqeu gjendjen tuaj @@ -188,4 +207,7 @@ sq: required: mark: "*" text: e domosdoshme + title: + sessions: + webauthn: Që të bëhet hyrja, përdorni një nga kyçet tuaj të sigurisë 'yes': Po diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index 80b699c28581fe0f250d99d3ad402743108b834d..8500f109eccf712f26e6a1e6b1b6d5f0bbd5284a 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -15,6 +15,10 @@ sv: text_html: Extra. Du kan använda toot syntax. Du kan <a href="%{path}">lägga till förvalda varningar</a> för att spara tid type_html: Välj vad du vill göra med <strong>%{acct}</strong> warning_preset_id: Extra. Du kan lägga till valfri text i slutet av förinställningen + announcement: + all_day: När det är markerat visas endast datum för tidsintervallet + ends_at: Frivillig. Meddelandet kommer automatiskt att publiceras just nu + scheduled_at: Lämna tomt för att publicera meddelandet omedelbart defaults: autofollow: Användarkonton som skapas genom din inbjudan kommer automatiskt följa dig avatar: PNG, GIF eller JPG. Högst %{size}. Kommer att skalas ner till %{dimensions}px @@ -49,20 +53,27 @@ sv: account_warning_preset: title: Rubrik admin_account_action: + text: Anpassad varning types: + disable: Inaktivera inloggning none: Gör ingenting + silence: Tysta defaults: autofollow: Bjud in till att följa ditt konto bot: Detta är ett botkonto chosen_languages: Filtrera sprÃ¥k confirm_new_password: Bekräfta nytt lösenord confirm_password: Bekräfta lösenord + context: Filter sammanhang current_password: Nuvarande lösenord + data: Data + discoverable: Lista detta konto i katalogen display_name: Visningsnamn email: E-postadress expires_in: Förfaller efter fields: Profil-metadata header: Bakgrundsbild + honeypot: "%{label} (fyll inte i)" locale: SprÃ¥k locked: LÃ¥s konto max_uses: Högst antal användningar @@ -78,7 +89,9 @@ sv: setting_default_privacy: Postintegritet setting_default_sensitive: Markera alltid media som känsligt setting_delete_modal: Visa bekräftelsedialog innan du raderar en toot + setting_disable_swiping: Inaktivera svepande rörelser setting_display_media: Mediavisning + setting_display_media_default: Standard setting_display_media_hide_all: Dölj alla setting_display_media_show_all: Visa alla setting_hide_network: Göm ditt nätverk diff --git a/config/locales/simple_form.ta.yml b/config/locales/simple_form.ta.yml index 74c64190127a13728fad4d9e4e73cc991151c31c..e306ce64d32ec6e4678d1d3a97d452bd7d80d47a 100644 --- a/config/locales/simple_form.ta.yml +++ b/config/locales/simple_form.ta.yml @@ -64,6 +64,7 @@ ta: note: சà¯à®¯à®šà®°à®¿à®¤à¯ˆ password: கடவà¯à®šà¯à®šà¯Šà®²à¯ setting_use_pending_items: மெதà¯à®µà®¾à®© பயனà¯à®®à¯à®±à¯ˆ + sign_in_token_attempt: பாதà¯à®•ாபà¯à®ªà¯à®•௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯ username: பயனரà¯à®ªà¯†à®¯à®°à¯ username_or_email: பயனர௠பெயர௠அலà¯à®²à®¤à¯ மினà¯à®©à®žà¯à®šà®²à¯ email_domain_block: diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index ee1476b9eb5a1df9e3c6fe6e9225bd2ff8937903..23add1d45599d2a14dc59d381eafc7edfbdc2512 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -53,9 +53,9 @@ th: username: ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸‚à¸à¸‡à¸„ุณจะไม่ซ้ำà¸à¸±à¸™à¹ƒà¸™ %{domain} whole_word: เมื่à¸à¸„ำสำคัà¸à¸«à¸£à¸·à¸à¸§à¸¥à¸µà¹€à¸›à¹‡à¸™à¸•ัวà¸à¸±à¸à¸©à¸£à¹à¸¥à¸°à¸•ัวเลขเท่านั้น จะนำไปใช้à¸à¸±à¸šà¸„ำสำคัà¸à¸«à¸£à¸·à¸à¸§à¸¥à¸µà¸«à¸²à¸à¸•รงà¸à¸±à¸™à¸—ั้งคำเท่านั้น domain_allow: - domain: โดเมนนี้จะสามารถดึงข้à¸à¸¡à¸¹à¸¥à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸™à¸µà¹‰à¹à¸¥à¸°à¸‚้à¸à¸¡à¸¹à¸¥à¸‚าเข้าจาà¸à¹‚ดเมนจะได้รับà¸à¸²à¸£à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¹à¸¥à¸°à¸ˆà¸±à¸”เà¸à¹‡à¸š + domain: โดเมนนี้จะสามารถดึงข้à¸à¸¡à¸¹à¸¥à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸™à¸µà¹‰à¹à¸¥à¸°à¸ˆà¸°à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¹à¸¥à¸°à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸‚้à¸à¸¡à¸¹à¸¥à¸‚าเข้าจาà¸à¹‚ดเมน email_domain_block: - with_dns_records: จะทำà¸à¸²à¸£à¸žà¸¢à¸²à¸¢à¸²à¸¡à¹à¸›à¸¥à¸‡à¸—ี่à¸à¸¢à¸¹à¹ˆà¸£à¸°à¹€à¸šà¸µà¸¢à¸™ DNS ขà¸à¸‡à¹‚ดเมนที่à¸à¸³à¸«à¸™à¸”à¹à¸¥à¸°à¸ˆà¸°à¸‚ึ้นบัà¸à¸Šà¸µà¸”ำผลลัพธ์เช่นà¸à¸±à¸™ + with_dns_records: จะทำà¸à¸²à¸£à¸žà¸¢à¸²à¸¢à¸²à¸¡à¹à¸›à¸¥à¸‡à¸—ี่à¸à¸¢à¸¹à¹ˆà¸£à¸°à¹€à¸šà¸µà¸¢à¸™ DNS ขà¸à¸‡à¹‚ดเมนที่à¸à¸³à¸«à¸™à¸”à¹à¸¥à¸°à¸ˆà¸°à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¸œà¸¥à¸¥à¸±à¸žà¸˜à¹Œà¹€à¸Šà¹ˆà¸™à¸à¸±à¸™ featured_tag: name: 'คุณà¸à¸²à¸ˆà¸•้à¸à¸‡à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸«à¸™à¸¶à¹ˆà¸‡à¹ƒà¸™à¸™à¸µà¹‰:' form_challenge: @@ -64,6 +64,9 @@ th: data: ไฟล์ CSV ที่ส่งà¸à¸à¸à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ Mastodon à¸à¸·à¹ˆà¸™ invite_request: text: นี่จะช่วยให้เราตรวจทานใบสมัครขà¸à¸‡à¸„ุณ + ip_block: + severities: + no_access: ปิดà¸à¸±à¹‰à¸™à¸à¸²à¸£à¹€à¸‚้าถึงทรัพยาà¸à¸£à¸—ั้งหมด sessions: otp: 'ป้à¸à¸™à¸£à¸«à¸±à¸ªà¸ªà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸—ี่สร้างโดยà¹à¸à¸›à¹ƒà¸™à¹‚ทรศัพท์ขà¸à¸‡à¸„ุณหรืà¸à¹ƒà¸Šà¹‰à¸«à¸™à¸¶à¹ˆà¸‡à¹ƒà¸™à¸£à¸«à¸±à¸ªà¸à¸¹à¹‰à¸„ืนขà¸à¸‡à¸„ุณ:' tag: @@ -88,10 +91,11 @@ th: text: คำเตืà¸à¸™à¸—ี่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ type: à¸à¸²à¸£à¸à¸£à¸°à¸—ำ types: - disable: ปิดใช้งานà¸à¸²à¸£à¹€à¸‚้าสู่ระบบ - none: ไม่ทำสิ่งใด - silence: ทำให้เงียบ - suspend: ระงับà¹à¸¥à¸°à¸¥à¸šà¸‚้à¸à¸¡à¸¹à¸¥à¸šà¸±à¸à¸Šà¸µà¸à¸¢à¹ˆà¸²à¸‡à¸–าวร + disable: à¸à¸²à¸¢à¸±à¸” + none: ส่งคำเตืà¸à¸™ + sensitive: ละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™ + silence: จำà¸à¸±à¸” + suspend: ระงับ warning_preset_id: ใช้คำเตืà¸à¸™à¸—ี่ตั้งไว้ล่วงหน้า announcement: all_day: เหตุà¸à¸²à¸£à¸“์ตลà¸à¸”ทั้งวัน @@ -134,6 +138,7 @@ th: setting_default_privacy: ความเป็นส่วนตัวขà¸à¸‡à¸à¸²à¸£à¹‚พสต์ setting_default_sensitive: ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸§à¹ˆà¸²à¸¥à¸°à¹€à¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™à¹€à¸ªà¸¡à¸ setting_delete_modal: à¹à¸ªà¸”งà¸à¸¥à¹ˆà¸à¸‡à¹‚ต้ตà¸à¸šà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¹ˆà¸à¸™à¸¥à¸šà¹‚พสต์ + setting_disable_swiping: ปิดใช้งานà¸à¸²à¸£à¹€à¸„ลื่à¸à¸™à¹„หวในà¸à¸²à¸£à¸›à¸±à¸” setting_display_media: à¸à¸²à¸£à¹à¸ªà¸”งสื่ภsetting_display_media_default: ค่าเริ่มต้น setting_display_media_hide_all: ซ่à¸à¸™à¸—ั้งหมด @@ -167,6 +172,13 @@ th: comment: ความคิดเห็น invite_request: text: ทำไมคุณจึงต้à¸à¸‡à¸à¸²à¸£à¹€à¸‚้าร่วม? + ip_block: + comment: ความคิดเห็น + ip: IP + severities: + no_access: ปิดà¸à¸±à¹‰à¸™à¸à¸²à¸£à¹€à¸‚้าถึง + sign_up_requires_approval: จำà¸à¸±à¸”à¸à¸²à¸£à¸¥à¸‡à¸—ะเบียน + severity: à¸à¸Ž notification_emails: digest: ส่งà¸à¸µà¹€à¸¡à¸¥à¸ªà¸£à¸¸à¸› favourite: ใครสัà¸à¸„นได้ชื่นชà¸à¸šà¸ªà¸–านะขà¸à¸‡à¸„ุณ diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index ea913048d8b30ecacd60f7183414bc848d97be72..39ae58dc2e04024f30e4d3481ae398f82b5caffb 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -3,15 +3,15 @@ tr: simple_form: hints: account_alias: - acct: Taşımak istediÄŸiniz hesabın kullanıcı-adı@alan-adını belirtin + acct: Taşımak istediÄŸiniz hesabın kullanıcıadı@alanadını belirtin account_migration: - acct: Taşınmak istediÄŸiniz hesabın kullanıcı-adı@alan-adını belirtin + acct: Taşımak istediÄŸiniz hesabın kullanıcıadı@alanadını belirtin account_warning_preset: - text: URL'ler, etiketler ve bahsetmeler gibi toot sözdizimleri kullanabilirsiniz - title: İsteÄŸe baÄŸlı. Alıcı tarafından görülemez + text: URL'ler, etiketler ve bahsedenler gibi toot sözdizimini kullanabilirsiniz + title: İsteÄŸe baÄŸlı. Alıcıya görünmez admin_account_action: include_statuses: Kullanıcı hangi tootların denetleme eylemi ya da uyarısına neden olduÄŸunu görecektir - send_email_notification: Kullanıcı, hesabına ne olduÄŸu hakkında bir bildirim alacak + send_email_notification: Kullanıcı, hesabına ne olduÄŸuna dair bir açıklama alacak text_html: İsteÄŸe baÄŸlı. Toot sözdizimleri kullanabilirsiniz. Zamandan kazanmak için <a href="%{path}">uyarı ön-ayarları ekleyebilirsiniz</a> type_html: "<strong>%{acct}</strong> ile ne yapılacağını seçin" warning_preset_id: İsteÄŸe baÄŸlı. Hazır ayarın sonuna hala özel metin ekleyebilirsiniz @@ -28,11 +28,11 @@ tr: context: Filtrenin geçerli olması gereken bir veya daha fazla içerik current_password: Güvenlik nedeniyle lütfen ÅŸu anki hesabın parolasını girin current_username: Onaylamak için lütfen ÅŸu anki hesabın kullanıcı adını girin - digest: Yalnızca uzun süre kullanılmadığında ve yalnızca yokluÄŸunda kiÅŸisel mesajlar aldıysanız gönderilir + digest: Sadece uzun bir süre hareketsiz kaldıktan sonra ve yalnızca yokluÄŸunuzda herhangi bir kiÅŸisel mesaj aldıysanız gönderilir discoverable: Profil dizini, hesabınızın daha geniÅŸ bir kitleye ulaÅŸmasının baÅŸka bir yoludur email: Onay e-postası gönderilecek fields: Profilinizde tablo olarak görüntülenen en fazla 4 ögeye sahip olabilirsiniz - header: En fazla %{size} olacak ÅŸekilde PNG, GIF veya JPG formatında yükleyiniz. %{dimensions}px büyüklüğüne indirgenecektir. + header: PNG, GIF ya da JPG. En fazla %{size}. %{dimensions}px boyutuna küçültülecek inbox_url: Kullanmak istediÄŸiniz aktarıcının ön sayfasından URL'yi kopyalayın irreversible: Filtre uygulanmış tootlar, filtre daha sonra çıkartılsa bile geri dönüşümsüz biçimde kaybolur locale: Kullanıcı arayüzünün dili, e-postalar ve push bildirimleri @@ -40,20 +40,23 @@ tr: password: En az 8 karakter kullanın phrase: Metnin büyük/küçük harf durumundan veya tootun içerik uyarısından bağımsız olarak eÅŸleÅŸtirilecek scopes: Uygulamanın eriÅŸmesine izin verilen API'ler. Üst seviye bir kapsam seçtiyseniz, bireysel kapsam seçmenize gerek yoktur. - setting_aggregate_reblogs: Yakın zamanda yinelenmiÅŸ tootlar için yeni yinelemeler gösterme (yalnızca yeni alınan yinelemeleri etkiler) - setting_default_sensitive: Hassas medya varsayılan olarak gizlenir ve bir tıklama ile görüntülenebilir + setting_aggregate_reblogs: Yakın zamanda boostlanmış tootlar için yeni boostları göstermeyin (yalnızca yeni alınan boostları etkiler) + setting_default_sensitive: Hassas medya varsayılan olarak gizlidir ve bir tıklama ile gösterilebilir setting_display_media_default: Hassas olarak iÅŸaretlenmiÅŸ medyayı gizle - setting_display_media_hide_all: Tüm medyayı gizle - setting_display_media_show_all: Hassas olarak iÅŸaretlenmiÅŸ medyayı göster - setting_hide_network: Takip edilenler ve takipçiler profilinizde gösterilmeyecek + setting_display_media_hide_all: Medyayı her zaman gizle + setting_display_media_show_all: Medyayı her zaman göster + setting_hide_network: Takip ettiÄŸiniz ve sizi takip eden kiÅŸiler profilinizde gösterilmeyecek setting_noindex: Herkese açık profilinizi ve durum sayfalarınızı etkiler setting_show_application: Tootlamak için kullandığınız uygulama, tootlarınızın detaylı görünümünde gösterilecektir setting_use_blurhash: Gradyenler gizli görsellerin renklerine dayanır, ancak detayları gizler - setting_use_pending_items: Zaman çizelgesi güncellemelerini, akışı otomatik olarak kaydırmak yerine bir tıklamanın arkasına gizleyin + setting_use_pending_items: Akışı otomatik olarak kaydırmak yerine, zaman çizelgesi güncellemelerini tek bir tıklamayla gizleyin username: Kullanıcı adınız %{domain} alanında benzersiz olacak whole_word: Anahtar kelime veya kelime öbeÄŸi yalnızca alfasayısal olduÄŸunda, yalnızca tüm sözcükle eÅŸleÅŸirse uygulanır domain_allow: domain: Bu alan adı, bu sunucudan veri alabilecek ve ondan gelen veri iÅŸlenecek ve saklanacaktır + email_domain_block: + domain: Bu, e-posta adresinde görünen etki alanı adı, etki alanının çözümlediÄŸi MX kaydı veya MX kaydının çözümlediÄŸi sunucunun IP'si olabilir. Bunlar kullanıcı kaydı ile kontrol edilecek ve kayıt reddedilecektir. + with_dns_records: Belirli bir alanın DNS kayıtlarını çözmeyi deneyecek ve sonuçlar kara listeye eklenecek featured_tag: name: 'Bunlardan birini kullanmak isteyebilirsiniz:' form_challenge: @@ -62,8 +65,17 @@ tr: data: DiÄŸer Mastodon sunucusundan dışarı aktardığınız CSV dosyası invite_request: text: Bu, baÅŸvurunuzu gözden geçirmemize yardımcı olacaktır + ip_block: + comment: İsteÄŸe baÄŸlı. Bu kuralı neden eklediÄŸinizi hatırlayın. + expires_in: IP adresleri sınırlı bir kaynaktır, bazen paylaşılırlar ve sıklıkla el deÄŸiÅŸtirirler. Bu nedenle, belirsiz IP blokları önerilmez. + ip: Bir IPv4 veya IPv6 adresi girin. CIDR sözdizimini kullanarak tüm aralıkları engelleyebilirsiniz. Kendinizi dışarıda bırakmamaya dikkat edin! + severities: + no_access: Tüm kaynaklara eriÅŸimi engelle + sign_up_requires_approval: Yeni kayıt onayınızı gerektirir + severity: Bu IP'den gelen isteklere ne olacağını seçin sessions: otp: Telefonunuzdaki two-factor kodunuzu giriniz veya kurtarma kodlarınızdan birini giriniz. + webauthn: Bir USB anahtarıysa, taktığınızdan ve gerekirse üzerine tıkladığınızdan emin olun. tag: name: Harflerin, örneÄŸin daha okunabilir yapmak için, sadece büyük/küçük harf durumlarını deÄŸiÅŸtirebilirsiniz user: @@ -78,111 +90,124 @@ tr: account_migration: acct: Yeni hesabın tanıtıcısı account_warning_preset: - text: Ön-ayar metni + text: Ön ayarlı metin title: BaÅŸlık admin_account_action: - include_statuses: Birdirilen tootları e-postaya dahil et - send_email_notification: E-postayla kullanıcıyı bilgilendir + include_statuses: Bildirilen tootları e-postaya dahil et + send_email_notification: Kullanıcıyı e-posta ile bilgilendir text: Özel uyarı type: Eylem types: - disable: Devre dışı + disable: Dondur none: Hiç birÅŸey - silence: Sessiz + sensitive: Hassas + silence: Limit suspend: Hesap verilerini askıya alın ve geri alınamaz ÅŸekilde silin - warning_preset_id: Bir uyarı ön-ayarı kullan + warning_preset_id: Bir uyarı ön ayarı kullan announcement: all_day: Tüm gün etkinliÄŸi - ends_at: Etkinlik sonu + ends_at: EtkinliÄŸin sonu scheduled_at: Yayınlamayı zamanla - starts_at: Etkinlik baÅŸlangıcı + starts_at: EtkinliÄŸin baÅŸlangıcı text: Duyuru defaults: autofollow: Hesabınızı takip etmeye davet edin avatar: Profil resmi bot: Bu bir bot hesabı chosen_languages: Dilleri filtrele - confirm_new_password: Yeni parolanız (tekrar) - confirm_password: Parolanız (tekrar) + confirm_new_password: Yeni ÅŸifreyi onayla + confirm_password: Åžifreyi onayla context: İçeriÄŸi filtrele - current_password: Mevcut parolanız - data: Dosya + current_password: Geçerli ÅŸifre + data: Veri discoverable: Bu hesabı dizinde listele - display_name: Görünen adınız - email: E-posta adresiniz + display_name: Görünen isim + email: E-posta adresi expires_in: BitiÅŸ tarihi - fields: Profil Metaverisi + fields: Profil meta verisi header: Kapak resmi + honeypot: "%{label} (doldurmayın)" inbox_url: Aktarıcı gelen kutusunun URL'si irreversible: Gizlemek yerine bırak - locale: Dil - locked: Hesabımı kilitle + locale: Arayüz dili + locked: Hesabı kilitle max_uses: Maksimum kullanım sayısı - new_password: Yeni parolanız + new_password: Yeni ÅŸifre note: KiÅŸisel bilgiler - otp_attempt: İki-faktörlü kod - password: Parolanız + otp_attempt: İki adımlı doÄŸrulama kodu + password: Åžifre phrase: Anahtar kelime veya kelime öbeÄŸi setting_advanced_layout: GeliÅŸmiÅŸ web arayüzünü etkinleÅŸtir - setting_aggregate_reblogs: Zaman çizelgesindeki grup yinelemeleri - setting_auto_play_gif: GIF'leri otomatik oynatt - setting_boost_modal: Boost etmeden önce onay diyaloÄŸu göster + setting_aggregate_reblogs: Zaman çizelgesinde grup boostları + setting_auto_play_gif: Hareketli GIF'leri otomatik oynat + setting_boost_modal: Boostlamadan önce onay iletiÅŸim kutusu göster setting_crop_images: GeniÅŸletilmemiÅŸ tootlardaki resimleri 16x9 olarak kırp setting_default_language: Gönderi dili setting_default_privacy: Gönderi gizliliÄŸi - setting_default_sensitive: Her zaman hassas medya olarak iÅŸaretle - setting_delete_modal: Bir tootu silmeden önce onay iletiÅŸim kutusunu göster - setting_display_media: Medya görünümü + setting_default_sensitive: Medyayı her zaman hassas olarak iÅŸaretle + setting_delete_modal: Bir tootu silmeden önce onay iletiÅŸim kutusu göster + setting_disable_swiping: Kaydırma hareketlerini devre dışı bırak + setting_display_media: Medya görüntüleme setting_display_media_default: Varsayılan setting_display_media_hide_all: Tümünü gizle setting_display_media_show_all: Tümünü göster setting_expand_spoilers: İçerik uyarılarıyla iÅŸaretli tootları her zaman geniÅŸlet - setting_hide_network: Ağını gizle - setting_noindex: Arama motoru endekslemesini iptal et + setting_hide_network: Ağınızı gizleyin + setting_noindex: Arama motoru dizinine eklemeyi iptal et setting_reduce_motion: Animasyonlarda hareketi azalt - setting_show_application: Toot göndermek için kullanılan uygulamayı belirt + setting_show_application: Tootları göndermek için kullanılan uygulamayı belirt setting_system_font_ui: Sistemin varsayılan yazı tipini kullan setting_theme: Site teması - setting_trends: Bugünün trendlerini göster - setting_unfollow_modal: Birini takip etmeden önce onay iletiÅŸim kutusunu göster - setting_use_blurhash: Gizli ortamlar için renkli gradyen göster + setting_trends: Bugünün gündemini göster + setting_unfollow_modal: Birini takip etmeden önce onay iletiÅŸim kutusu göster + setting_use_blurhash: Gizli medya için renkli gradyanlar göster setting_use_pending_items: YavaÅŸ mod - severity: Zorluk + severity: Önem derecesi sign_in_token_attempt: Güvenlik kodu - type: Dosya türü - username: Kullanıcı adınız - username_or_email: Kullanıcı adı ya da email - whole_word: Tüm dünya + type: İçeri aktarma türü + username: Kullanıcı adı + username_or_email: Kullanıcı adı ya da e-posta + whole_word: Tam sözcük email_domain_block: with_dns_records: Alan adının MX kayıtlarını ve IP'lerini ekleyin featured_tag: - name: Hashtag + name: Etiket interactions: must_be_follower: Takipçim olmayan kiÅŸilerden gelen bildirimleri engelle must_be_following: Takip etmediÄŸim kiÅŸilerden gelen bildirimleri engelle - must_be_following_dm: Takip etmediÄŸiniz kiÅŸilerin doÄŸrudan ileti göndermesini engelle + must_be_following_dm: Takip etmediÄŸiniz kiÅŸilerden gelen direkt mesajları engelle invite: comment: Yorum invite_request: text: Neden katılmak istiyorsun? + ip_block: + comment: Yorum + ip: IP + severities: + no_access: EriÅŸimi engelle + sign_up_requires_approval: Kayıtları sınırla + severity: Kural notification_emails: digest: Özet e-postaları gönder - favourite: Biri durumumu favorilerine eklediginde bana e-posta gönder - follow: Biri beni takip ettiÄŸinde bana e-posta gönder - follow_request: Biri bana takip isteÄŸi gönderdiÄŸinde, bana e-posta gönder - mention: Biri benden bahsettiÄŸinde, bana e-posta gönder - pending_account: Yeni bir hesap incelemesi gerektiÄŸinde e-posta gönder - reblog: Biri durumumu paylaÅŸtığında, bana e-posta gönder - report: Yeni bir rapor gönderildiÄŸinde e-posta gönder - trending_tag: İncelenmemiÅŸ bir hashtag trend olduÄŸunda e-posta gönder + favourite: Birisi durumunuzu beÄŸendi + follow: Biri seni takip etti + follow_request: Biri seni takip etmek istedi + mention: Biri senden bahsetti + pending_account: Yeni hesabın incelenmesi gerekiyor + reblog: Biri durumunuzu boostladı + report: Yeni rapor gönderildi + trending_tag: İncelenmemiÅŸ bir etiket gündem oluyor tag: listable: Bu etiketin aramalarda ve profil dizininde görünmesine izin ver - name: Hashtag - trendable: Bu etiketin trendlerin altında görünmesine izin ver + name: Etiket + trendable: Bu etiketin gündem altında görünmesine izin ver usable: Tootların bu etiketi kullanmasına izin ver 'no': Hayır recommended: Önerilen required: mark: "*" text: gerekli + title: + sessions: + webauthn: Oturum açmak için güvenlik anahtarlarınızdan birini kullanın 'yes': Evet diff --git a/config/locales/simple_form.tt.yml b/config/locales/simple_form.tt.yml new file mode 100644 index 0000000000000000000000000000000000000000..5eab4abff95e2119202e91e8d75bd785c9ccbdc9 --- /dev/null +++ b/config/locales/simple_form.tt.yml @@ -0,0 +1 @@ +tt: diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index a490efed555048ee1c2cb899bf0b067a9dabe129..adfc07a0958d872a7057aa1828a2b59907f6298c 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -55,6 +55,7 @@ uk: domain_allow: domain: Цей домен зможе отримувати дані з цього Ñерверу. Вхідні дані будуть оброблені та збережені email_domain_block: + domain: Це може бути домен, що відображаєтьÑÑ Ñƒ поштовій адреÑÑ–, Ð·Ð°Ð¿Ð¸Ñ MX Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ чи IP адреÑи Ñервера. Вони будуть перевірені при реєÑтрації кориÑтувача, Ñ– реєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ відхилена. with_dns_records: Спроба Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ DNS-запиÑів заданого домену буде здійÑнена, а результати також будуть занеÑені до чорного ÑпиÑку featured_tag: name: 'Можливо, ви захочете викориÑтовувати один з цих:' @@ -66,6 +67,7 @@ uk: text: Це допоможе нам розглÑнути вашу заÑву sessions: otp: Введите код двухфакторной аутентификации или иÑпользуйте один из Ваших кодов воÑÑтановлениÑ. + webauthn: Якщо це USB ключ, вÑтавте його Ñ–, Ñкщо необхідно, натиÑніть на нього. tag: name: Тут ви можете лише змінювати регіÑтр літер, щоб підвищити читабельніÑть user: @@ -187,4 +189,7 @@ uk: required: mark: "*" text: обов'Ñзкове + title: + sessions: + webauthn: ВикориÑтайте один із ваших ключів безпеки Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ 'yes': Так diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index 5251ab114fbbc123361572da997aa6dcdf2f7285..dfe1ae36e513864894e74a9f63b4b96ec7fc3896 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -3,97 +3,107 @@ vi: simple_form: hints: account_alias: - acct: Chá»n tên_ngưá»i_dùng@máy chá»§ cá»§a tà i khoản lúc trước + acct: Nháºp tên_ngưá»i_dùng@máy chá»§ cá»§a tà i khoản cÅ© account_migration: - acct: Chá»n tênngưá»idùng@máy chá»§ cá»§a tà i khoản bạn muốn dá»i sang + acct: Nháºp tên_ngưá»i_dùng@máy chá»§ cá»§a tà i khoản bạn muốn dá»i sang account_warning_preset: - text: Bạn có thể sá» dụng URL, hashtag và nhắc đến + text: Bạn có thể dùng URL, hashtag và nhắc đến title: Tùy chá»n. Không cho ngưá»i nháºn xem admin_account_action: - include_statuses: Ngưá»i dùng sẽ thấy các tút bị kiểm duyệt hoặc cảnh cáo + include_statuses: Ngưá»i dùng sẽ thấy các tút nà o cá»§a há» bị kiểm duyệt send_email_notification: Ngưá»i dùng sẽ nháºn được lá»i giải thÃch vá» những gì xảy ra vá»›i tà i khoản cá»§a há» - text_html: Tùy chá»n. Bạn có thể sá» dụng <a href="%{path}">cảnh cáo cà i sẵn</a> để tiết kiệm thá»i gian + text_html: Tùy chá»n. Bạn nên dùng <a href="%{path}">cảnh cáo cà i sẵn</a> để tiết kiệm thá»i gian type_html: Chá»n là m gì vá»›i <strong>%{acct}</strong> - warning_preset_id: Tùy chá»n. Bạn vẫn có thể thêm văn bản tùy chỉnh và o cuối cảnh cáo cà i sẵn + warning_preset_id: Tùy chá»n. Bạn vẫn có thể thêm ghi chú riêng announcement: all_day: Chỉ có khoảng thá»i gian được đánh dấu má»›i hiển thị ends_at: Tùy chá»n. Thông báo sẽ tá»± động há»§y và o lúc nà y scheduled_at: Äể trống nếu muốn đăng thông báo ngay láºp tức starts_at: Tùy chá»n. Trong trưá»ng hợp thông báo cá»§a bạn đăng và o má»™t khoảng thá»i gian cụ thể - text: Bạn có thể sá» dụng tút dạng cú pháp. Cố gắng ngắn gá»n bởi vì thông báo sẽ xuất hiện trên mà n hình Ä‘iện thoại cá»§a ngưá»i dùng + text: Bạn có thể dùng URL, hashtag và nhắc đến. Cố gắng ngắn gá»n bởi vì thông báo sẽ xuất hiện trên mà n hình Ä‘iện thoại cá»§a ngưá»i dùng defaults: - autofollow: Những ngưá»i đăng ký thông qua lá»i má»i sẽ tá»± động theo dõi bạn + autofollow: Những ngưá»i đăng ký sẽ tá»± động theo dõi bạn avatar: PNG, GIF hoặc JPG. KÃch cỡ tối Ä‘a %{size}. Sẽ bị nén xuống %{dimensions}px bot: Tà i khoản nà y tá»± động thá»±c hiện các hà nh động và không cần thiết theo dõi - context: Má»™t hoặc nhiá»u bối cảnh nÆ¡i bá»™ lá»c nên áp dụng + context: Chá»n má»™t hoặc nhiá»u nÆ¡i mà bá»™ lá»c sẽ áp dụng current_password: Vì mục Ä‘Ãch bảo máºt, vui lòng nháºp máºt khẩu cá»§a tà i khoản hiện tại current_username: Äể xác nháºn, vui lòng nháºp tên ngưá»i dùng cá»§a tà i khoản hiện tại - digest: Chỉ được gá»i sau má»™t thá»i gian dà i không hoạt động và chỉ khi bạn đã nháºn được bất kỳ tin nhắn cá nhân nà o khi bạn vắng mặt - discoverable: Danh sách thà nh viên là má»™t cách hay để bạn tìm kiếm ngưá»i bạn muốn theo dõi + digest: Chỉ gá»i sau má»™t thá»i gian dà i không hoạt động hoặc khi bạn nháºn được tin nhắn (trong thá»i gian vắng mặt) + discoverable: Má»i ngưá»i sẽ có thể tìm thấy bạn dá»… dà ng hÆ¡n email: Bạn sẽ được gá»i má»™t email xác nháºn - fields: Bạn có thể tạo tối Ä‘a 4 mục được hiển thị dưới dạng bảng trên hồ sÆ¡ cá»§a bạn + fields: ÄÆ°á»£c phép tạo tối Ä‘a 4 mục trên trang cá nhân cá»§a bạn header: PNG, GIF hoặc JPG. KÃch cỡ tối Ä‘a %{size}. Sẽ bị nén xuống %{dimensions}px - inbox_url: Sao chép URL cá»§a relay mà bạn muốn sá» dụng - irreversible: Các tút đã lá»c sẽ không thể phục hồi, kể cả khi bá»™ lá»c có bị xóa + inbox_url: Sao chép URL cá»§a máy chá»§ mà bạn muốn dùng + irreversible: Các tút đã lá»c sẽ không thể phục hồi, kể cả sau khi xóa bá»™ lá»c locale: Ngôn ngữ cá»§a giao diện, email và thông báo đẩy - locked: Yêu cầu bạn chấp thuáºn thá»§ công ngưá»i theo dõi - password: Sá» dụng Ãt nhất 8 ký tá»± + locked: Tá»± bạn sẽ phê duyệt ngưá»i theo dõi + password: Dùng Ãt nhất 8 ký tá»± phrase: Sẽ được hiện thị trong văn bản hoặc cảnh báo ná»™i dung cá»§a má»™t tút - scopes: API nà o ứng dụng sẽ được phép truy cáºp. Nếu bạn chá»n phạm vi cấp cao nhất, bạn không cần chá»n từng phạm vi. - setting_aggregate_reblogs: Äừng hiện những chia sẻ má»›i cho những tút đã chia sẻ gần đây (chỉ ảnh hưởng đến các chia sẻ má»›i) - setting_default_sensitive: Ảnh/video/âm thanh nhạy cảm được ẩn theo mặc định và chỉ hiển thị nếu nhấp chuá»™t - setting_display_media_default: Ẩn ảnh hoặc video được đánh dấu là nhạy cảm - setting_display_media_hide_all: Luôn ẩn ảnh và video - setting_display_media_show_all: Luôn hiện ảnh và video - setting_hide_network: Bạn theo dõi ai và ai theo dõi bạn sẽ không được hiển thị trên hồ sÆ¡ cá»§a bạn + scopes: API nà o ứng dụng sẽ được phép truy cáºp. Nếu bạn chá»n quyá»n hạn cấp cao nhất, bạn không cần chá»n từng phạm vi. + setting_aggregate_reblogs: Nếu má»™t tút đã được chia sẻ thì những lượt chia sẻ sau sẽ không hiển thị trên bảng tin nữa + setting_default_sensitive: Ná»™i dung nhạy cảm mặc định là ẩn và chỉ hiển thị nếu nhấn và o + setting_display_media_default: Là m má» những thứ được đánh dấu là nhạy cảm + setting_display_media_hide_all: Không hiển thị + setting_display_media_show_all: Luôn luôn hiển thị + setting_hide_network: Ẩn những ngưá»i bạn theo dõi và những ngưá»i theo dõi bạn trên trang cá nhân setting_noindex: Ảnh hưởng đến trang cá nhân và tút cá»§a bạn - setting_show_application: Tên ứng dụng bạn sá» dụng để đăng tút sẽ được hiển thị trong chi tiết bà i đăng - setting_use_blurhash: Hình ảnh má» dá»±a trên mà u sắc cá»§a hình ảnh nhạy cảm nhưng sẽ che hết chi tiết - setting_use_pending_items: Ẩn cáºp nháºt bảng tin bằng má»™t cái nhấp chuá»™t thay vì phải cuá»™n toà n bá»™ + setting_show_application: Tên ứng dụng bạn dùng để đăng tút sẽ hiện trong chi tiết bà i đăng + setting_use_blurhash: Lá»›p phá»§ má» dá»±a trên mà u sắc cá»§a hình ảnh nhạy cảm + setting_use_pending_items: Dồn lại toà n bá»™ tút má»›i và chỉ hiển thị khi nà o nhấp chuá»™t và o username: Tên ngưá»i dùng cá»§a bạn sẽ là duy nhất trên %{domain} - whole_word: Khi từ khóa hoặc cụm từ chỉ là chữ và số, nó sẽ chỉ hiện ra những từ chÃnh xác như váºy + whole_word: Khi từ khóa hoặc cụm từ là chữ và số, nó sẽ chỉ hiện ra những từ chÃnh xác như váºy domain_allow: domain: Máy chá»§ nà y sẽ tiếp nháºn dữ liệu, rồi sau đó xá» lý và lưu trữ email_domain_block: - domain: Äây có thể là tên máy chá»§ cá»§a địa chỉ email. Nếu máy chá»§ đó có vấn Ä‘á», đăng ký sẽ bị từ chối. + domain: Äây có thể là tên miá»n hoặc IP cá»§a dịch vụ email. Ngưá»i dùng cá»§a những dịch vụ email nà y sẽ bị từ chối khi đăng ký. with_dns_records: Nếu DNS có vấn Ä‘á», nó sẽ bị đưa và o danh sách cấm featured_tag: - name: 'Những hashtag khuyến nghị bạn sá» dụng:' + name: 'Những hashtag gợi ý cho bạn:' form_challenge: current_password: Biểu mẫu nà y an toà n imports: data: Tệp CSV được xuất từ máy chá»§ Mastodon khác invite_request: - text: Äiá»u nà y sẽ giúp chúng tôi xem xét lá»i má»i cá»§a bạn + text: Äiá»u nà y sẽ giúp chúng tôi phê duyệt đăng ký cá»§a bạn + ip_block: + comment: Tùy chá»n. Hãy cho biết lý do bạn chặn IP nà y. + expires_in: Có thể sẽ có nhiá»u ngưá»i khác nhau dùng chung má»™t địa chỉ IP. Vì váºy, bạn nên cân nhắc không nên chặn IP nà o đó vÄ©nh viá»…n. + ip: Nháºp má»™t địa chỉ IPv4 hoặc IPv6. Bạn cÅ©ng có thể chặn toà n bá»™ dãy IP bằng cú pháp CIDR. Hãy cẩn tháºn đừng chặn nhầm toà n bá»™! + severities: + no_access: Chặn truy cáºp từ tất cả IP nà y + sign_up_requires_approval: Bạn sẽ phê duyệt những đăng ký má»›i từ IP nà y + severity: Chá»n hà nh động nếu nháºn được yêu cầu từ IP nà y sessions: - otp: 'Nháºp mã xác thá»±c hai yếu tố được tạo bởi ứng dụng Ä‘iện thoại cá»§a bạn hoặc sá» dụng má»™t trong các mã khôi phục cá»§a bạn:' + otp: 'Nháºp mã xác thá»±c hai bước được tạo bởi ứng dụng Ä‘iện thoại cá»§a bạn hoặc dùng má»™t trong các mã khôi phục cá»§a bạn:' + webauthn: Nếu đây là USB key, hãy cắm và o và thá» xoay chiá»u. tag: name: Bạn có thể thay đổi cách viết hoa các chữ cái để giúp nó dá»… Ä‘á»c hÆ¡n user: - chosen_languages: Chỉ những tút viết bằng các ngôn ngữ được chá»n sẽ được hiển thị trên bảng tin + chosen_languages: Chỉ những tút viết bằng các ngôn ngữ được chá»n sẽ hiển thị trên bảng tin labels: account: fields: name: Nhãn value: Ná»™i dung account_alias: - acct: Xá» lý tà i khoản cÅ© + acct: Tà i khoản cÅ© account_migration: - acct: Xá» lý tà i khoản má»›i + acct: Tà i khoản má»›i account_warning_preset: text: Văn bản cà i sẵn title: Tá»±a đỠadmin_account_action: - include_statuses: ÄÃnh kèm những tút bị báo xấu trong e-mail - send_email_notification: Thông báo cho ngưá»i dùng má»—i email - text: Tùy chỉnh cảnh báo - type: Hoạt động + include_statuses: ÄÃnh kèm những tút bị báo cáo trong e-mail + send_email_notification: Thông báo cho ngưá»i nà y qua email + text: Ghi chú riêng + type: Hà nh động types: - disable: Vô hiệu hóa đăng nháºp - none: Không là m gì cả - silence: Im lặng - suspend: Äình chỉ và xóa dữ liệu tà i khoản - warning_preset_id: Sá» dụng cảnh báo cà i đặt trước + disable: Tạm khóa + none: Cấm upload + sensitive: Nhạy cảm + silence: Tạm ẩn + suspend: Vô hiệu hóa + warning_preset_id: Dùng cảnh cáo cà i sẵn announcement: all_day: Sá»± kiện diá»…n ra hằng ngà y ends_at: Kết thúc sá»± kiện @@ -103,56 +113,58 @@ vi: defaults: autofollow: Má»i theo dõi tà i khoản cá»§a bạn avatar: Ảnh đại diện - bot: Äây là tà i khoản bot + bot: Äây là tà i khoản Bot chosen_languages: Chá»n ngôn ngữ confirm_new_password: Xác nháºn máºt khẩu má»›i confirm_password: Xác nháºn máºt khẩu - context: Bá»™ lá»c bối cảnh + context: Ãp dụng current_password: Máºt khẩu hiện tại data: Dữ liệu - discoverable: Liệt kê tà i khoản nà y trên danh sách thà nh viên + discoverable: Liệt kê tà i khoản trên danh sách thà nh viên display_name: Tên hiển thị email: ÄiÌ£a chỉ email expires_in: Hết hạn sau - fields: Hồ sÆ¡ metadata + fields: Metadata header: Ảnh bìa - inbox_url: URL cá»§a há»™p thư relay - irreversible: Kéo xuống thay vì ẩn + honeypot: "%{label} (đừng Ä‘iá»n và o)" + inbox_url: Há»™p thư relay + irreversible: Xóa bá» vÄ©nh viá»…n locale: Ngôn ngữ - locked: Khóa tà i khoản - max_uses: Số lần sá» dụng tối Ä‘a + locked: Äây là tà i khoản riêng tư + max_uses: Số lần dùng tối Ä‘a new_password: Máºt khẩu má»›i note: Tiểu sá» otp_attempt: Xác thá»±c hai bước password: Máºt khẩu phrase: Từ khóa hoặc cụm từ - setting_advanced_layout: KÃch hoạt giao diện web nâng cao - setting_aggregate_reblogs: Hiện tút nhóm trong bảng tin - setting_auto_play_gif: Tá»± động phát GIF + setting_advanced_layout: KÃch hoạt giao diện nhiá»u cá»™t + setting_aggregate_reblogs: Không hiện lượt chia sẻ trùng + setting_auto_play_gif: Tá»± động phát ảnh GIF setting_boost_modal: Yêu cầu xác nháºn trước khi chia sẻ tút setting_crop_images: Hiển thị ảnh theo tỉ lệ 16x9 setting_default_language: Ngôn ngữ đăng setting_default_privacy: Kiểu đăng - setting_default_sensitive: Luôn đánh dấu ảnh/video là nhạy cảm + setting_default_sensitive: Luôn đánh dấu ảnh/video là ná»™i dung nhạy cảm setting_delete_modal: Yêu cầu xác nháºn trước khi xóa tút - setting_display_media: Hiện ảnh/video + setting_disable_swiping: Vô hiệu hóa vuốt mà n hình + setting_display_media: Ná»™i dung nhạy cảm setting_display_media_default: Mặc định setting_display_media_hide_all: Ẩn toà n bá»™ setting_display_media_show_all: Hiện toà n bá»™ - setting_expand_spoilers: Luôn hiện trước các tút đánh dấu là spoil - setting_hide_network: Ẩn máy chá»§ cá»§a bạn + setting_expand_spoilers: Luôn hiển thị đầy đủ ná»™i dung tút + setting_hide_network: Ẩn kết nối cá»§a bạn setting_noindex: Không xuất hiện trong công cụ tìm kiếm setting_reduce_motion: Giảm chuyển động ảnh GIF - setting_show_application: Hiện ứng dụng được sá» dụng để đăng tút - setting_system_font_ui: Sá» dụng phông chữ mặc định cá»§a hệ thống - setting_theme: Giao diện trang web + setting_show_application: Hiện ứng dụng đã dùng để đăng tút + setting_system_font_ui: Dùng phông chữ mặc định cá»§a hệ thống + setting_theme: Giao diện setting_trends: Hiển thị xu hướng hôm nay setting_unfollow_modal: Yêu cầu xác nháºn trước khi há»§y theo dõi ai đó setting_use_blurhash: Là m má» trước ảnh/video nhạy cảm setting_use_pending_items: Không tá»± động cáºp nháºt bảng tin severity: Mức độ nghiêm trá»ng sign_in_token_attempt: Mã an toà n - type: Nháºp loại + type: Kiểu nháºp username: Tên ngưá»i dùng username_or_email: Tên ngưá»i dùng hoặc email whole_word: Cả từ @@ -168,24 +180,34 @@ vi: comment: Bình luáºn invite_request: text: Tại sao bạn muốn tham gia? + ip_block: + comment: Mô tả + ip: IP + severities: + no_access: Chặn truy cáºp + sign_up_requires_approval: Giá»›i hạn đăng ký + severity: Mức độ notification_emails: digest: Gá»i email định kỳ - favourite: Ai đó tâm đắc tút cá»§a bạn + favourite: Ai đó thÃch tút cá»§a bạn follow: Ai đó theo dõi bạn follow_request: Ai đó yêu cầu theo dõi bạn mention: Ai đó nhắc đến bạn - pending_account: Có tà i khoản má»›i cần phê duyệt + pending_account: Tà i khoản má»›i cần phê duyệt reblog: Ai đó chia sẻ tút cá»§a bạn - report: Ai đó gá»i báo cáo xấu + report: Ai đó gá»i báo cáo kiểm duyệt trending_tag: Má»™t hashtag chưa được phê duyệt Ä‘ang là xu hướng tag: - listable: Cho phép hashtag nà y xuất hiện trong tìm kiếm và trên danh sách thà nh viên + listable: Cho phép hashtag nà y xuất hiện trong tìm kiếm và trên tiểu sá» cá nhân name: Hashtag trendable: Cho phép hashtag nà y xuất hiện trong xu hướng - usable: Cho phép các tút sá» dụng hashtag nà y - 'no': Không + usable: Cho phép dùng hashtag nà y trong tút + 'no': Tắt recommended: Khuyến nghị required: mark: "*" text: yêu cầu - 'yes': Äúng + title: + sessions: + webauthn: Dùng má»™t trong những khóa bảo máºt cá»§a bạn để đăng nháºp + 'yes': Báºt diff --git a/config/locales/simple_form.zgh.yml b/config/locales/simple_form.zgh.yml new file mode 100644 index 0000000000000000000000000000000000000000..ed9ea90f8212a2d6fc08d44c9287a1508d3a579a --- /dev/null +++ b/config/locales/simple_form.zgh.yml @@ -0,0 +1,41 @@ +--- +zgh: + simple_form: + hints: + defaults: + setting_display_media_hide_all: âµ™âµâµœâµ ⵉⵙâµâµ–ⵎⵉⵙⵠⴰⴱⴷⴰ + setting_display_media_show_all: ⵙⵎⴰⵠⵉⵙâµâµ–ⵎⵉⵙⵠⴰⴱⴷⴰ + labels: + account_warning_preset: + title: ⴰⵣⵡⵠ+ admin_account_action: + type: ⵜⵉⴳⴰⵡⵜ + defaults: + bot: ⵡⴰⴷ ⴰⵎⵉⴹⴰⵠⵠⵓⴱⵓⵜ + chosen_languages: ⵙⵜⵢ ⵜⵓⵜâµâ´°âµ¢âµ‰âµ + confirm_new_password: âµ™âµâµœâµŽ ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢâµâµ“ⵜ + confirm_password: âµ™âµâµœâµŽ ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ + data: ⵉⴼⵙⴽⴰ + email: ⵜⴰâµâµ™â´° ⵉⵎⴰⵢⵠ+ locale: ⵜⵓⵜâµâ´°âµ¢âµœ ⵠⵓâµâ´³âµ”ⵓⴷⵎ + locked: ⵔⴳⵠⴰⵎⵉⴹⴰⵠ+ new_password: ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢâµâµ“ⵜ + note: ⵜⴰⵔⵉⴷⵉⵔⵜ + password: ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ + setting_hide_network: ⴼⴼⵔ ⴰⵥⵟⵟⴰ âµâµâ´½ + setting_theme: ⴰⵙⴳⵓⵎ ⵠⵡⴰⵙⵉⵜ + username: ⵉⵙⵎ ⵠⵓâµâµ™âµ™âµŽâµ”âµ™ + username_or_email: ⵉⵙⵎ ⵠⵓâµâµ™âµ™âµŽâµ”âµ™ âµâµ– ⵉⵎⴰⵢⵠ+ featured_tag: + name: ⵀⴰⵛⵟⴰⴳ + invite: + comment: ⴰⵖⴼⴰⵡⴰⵠ+ ip_block: + comment: ⵖⴼⴰⵡⵠ+ ip: ⵜⴰâµâµ™â´° IP + tag: + name: ⵀⴰⵛⵟⴰⴳ + 'no': ⵓⵀⵓ + required: + mark: "*" + 'yes': ⵢⴰⵀ diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 6bb1053a8e11647bf93d9cf0cc27403f4ddd4250..35222c076d2cdee75e085bf4e34f3d3a5b4d888e 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -65,8 +65,17 @@ zh-CN: data: 从其他 Mastodon æœåŠ¡å™¨å¯¼å‡ºçš„ CSV 文件 invite_request: text: 这会有助于我们处ç†ä½ 的申请 + ip_block: + comment: å¯é€‰ã€‚请记ä½ä¸ºä»€ä¹ˆæ‚¨æ·»åŠ äº†æ¤è§„则。 + expires_in: IP åœ°å€æ˜¯ä¸€ç§æœ‰é™çš„资æºï¼Œå®ƒä»¬æœ‰æ—¶æ˜¯å…±äº«çš„,并且常常å˜åŒ–ã€‚å› æ¤ï¼Œä¸æŽ¨èæ— é™æœŸçš„ IP å°ç¦ã€‚ + ip: 输入 IPv4 或 IPv6 地å€ã€‚您å¯ä»¥ä½¿ç”¨ CIDR è¯æ³•å±è”½æ•´ä¸ªèŒƒå›´ã€‚å°å¿ƒä¸è¦å±è”½è‡ªå·±ï¼ + severities: + no_access: 阻æ¢è®¿é—®æ‰€æœ‰èµ„æº + sign_up_requires_approval: æ–°çš„æ³¨å†Œéœ€è¦æ‚¨çš„æ‰¹å‡† + severity: é€‰æ‹©å¦‚ä½•å¤„ç†æ¥è‡ªæ¤ IP 的请求。 sessions: otp: è¾“å…¥ä½ æ‰‹æœºåº”ç”¨ä¸Šç”Ÿæˆçš„åŒé‡è®¤è¯ç ,或者任æ„一个æ¢å¤ä»£ç : + webauthn: 如果是 USB 密钥,请确ä¿å°†å…¶æ’入,如有必è¦ï¼Œè¯·ç‚¹å‡»å®ƒã€‚ tag: name: 您åªèƒ½æ”¹å˜å—æ¯çš„大å°å†™ï¼Œè®©å®ƒæ›´æ˜“读 user: @@ -91,6 +100,7 @@ zh-CN: types: disable: ç¦ç”¨ none: 忽略 + sensitive: æ•æ„Ÿå†…容 silence: é™éŸ³ suspend: åœç”¨å¹¶æ°¸ä¹…åˆ é™¤è´¦å·æ•°æ® warning_preset_id: 使用预置è¦å‘Š @@ -116,6 +126,7 @@ zh-CN: expires_in: 失效时间 fields: ä¸ªäººèµ„æ–™é™„åŠ ä¿¡æ¯ header: 个人资料页横幅图片 + honeypot: "%{label} (请勿填写)" inbox_url: ä¸ç»§ç«™æ”¶ä»¶ç®±çš„ URL irreversible: 丢弃而éžéšè— locale: 界é¢è¯è¨€ @@ -135,6 +146,7 @@ zh-CN: setting_default_privacy: 嘟文默认å¯è§èŒƒå›´ setting_default_sensitive: 总是将我å‘é€çš„åª’ä½“æ–‡ä»¶æ ‡è®°ä¸ºæ•æ„Ÿå†…容 setting_delete_modal: åœ¨åˆ é™¤å˜Ÿæ–‡å‰è¯¢é—®æˆ‘ + setting_disable_swiping: ç¦ç”¨æ»‘动动作 setting_display_media: 媒体展示 setting_display_media_default: 默认 setting_display_media_hide_all: éšè—全部 @@ -168,6 +180,13 @@ zh-CN: comment: 评论 invite_request: text: ä½ ä¸ºä»€ä¹ˆæƒ³è¦åŠ å…¥ï¼Ÿ + ip_block: + comment: 备注 + ip: IP åœ°å€ + severities: + no_access: 阻æ¢è®¿é—® + sign_up_requires_approval: é™åˆ¶æ³¨å†Œ + severity: 规则 notification_emails: digest: å‘逿‘˜è¦é‚®ä»¶ favourite: 当有用户喜欢了我的嘟文时,å‘é€ç”µå邮件æé†’我 @@ -188,4 +207,7 @@ zh-CN: required: mark: "*" text: å¿…å¡« + title: + sessions: + webauthn: 使用您的安全密钥登录 'yes': 是 diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml index fd192fbbcb47eefb0bf38cf74e17af2c2ad5aa43..eaed6e32b99ff665ee16eee72adff1a44db58028 100644 --- a/config/locales/simple_form.zh-HK.yml +++ b/config/locales/simple_form.zh-HK.yml @@ -3,59 +3,81 @@ zh-HK: simple_form: hints: account_alias: - acct: 指定欲移動之帳戶的 使用者å稱@ç«™å° + acct: 指定欲移動之帳戶的「使用者å稱@域å〠account_migration: - acct: 指定欲移動至之帳戶的 使用者å稱@ç«™å° + acct: 指定欲移動至之帳戶的「使用者å稱@域å〠account_warning_preset: - text: 您å¯ä½¿ç”¨å˜Ÿæ–‡èªžæ³•,例如網å€ã€ã€Œ#ã€æ¨™ç±¤å’ŒæåŠåŠŸèƒ½ + text: ä½ å¯ä½¿ç”¨ toot æ ¼å¼ï¼Œä¾‹å¦‚ç¶²å€ã€ã€Œ#ã€æ¨™ç±¤å’ŒæåŠåŠŸèƒ½ + title: å¯é¸ï¼ŒæŽ¥æ”¶è€…䏿œƒè¦‹åˆ° admin_account_action: + include_statuses: ä½¿ç”¨è€…å°‡æœƒçœ‹åˆ°å“ªäº›æ–‡ç« å°Žè‡´æª¢èˆ‰æˆ–è¦å‘Š send_email_notification: 使用者將收到帳戶發生之事情的解釋 - text_html: é¸ç”¨ã€‚æ‚¨èƒ½ä½¿ç”¨å˜Ÿæ–‡èªžæ³•ã€‚æ‚¨å¯ <a href="%{path}">新增è¦å‘Šé è¨</a> ä¾†ç¯€çœæ™‚é–“ + text_html: é¸ç”¨ã€‚ä½ èƒ½ä½¿ç”¨ toot èªžæ³•ã€‚ä½ å¯ <a href="%{path}">新增è¦å‘Šé è¨</a> ä¾†ç¯€çœæ™‚é–“ type_html: è¨å®šè¦ä½¿ç”¨ <strong>%{acct}</strong> åšçš„事 - warning_preset_id: é¸ç”¨ã€‚您ä»å¯åœ¨é è¨çš„çµå°¾æ–°å¢žè‡ªè¨‚æ–‡å— + warning_preset_id: é¸ç”¨ã€‚ä½ ä»å¯åœ¨é è¨è¨Šæ¯çš„çµå°¾åŠ å…¥è‡ªè¨‚æ–‡å— announcement: - all_day: æ ¸å–å¾Œï¼Œåªæœƒé¡¯ç¤ºå‡ºæ™‚間範åœä¸çš„æ—¥æœŸéƒ¨åˆ† - scheduled_at: 空白則立å³ç™¼å¸ƒå…¬å‘Š + all_day: 勾é¸å¾Œï¼Œåªæœƒé¡¯ç¤ºå‡ºæ™‚間範åœä¸çš„æ—¥æœŸéƒ¨åˆ† + ends_at: å¯é¸ï¼Œå…¬å‘Šæœƒåœ¨è©²æ™‚é–“é»žè‡ªå‹•å–æ¶ˆç™¼å¸ƒ + scheduled_at: 留空æ¤é …以立å³ç™¼å¸ƒå…¬å‘Š + starts_at: å¯é¸ï¼Œä½ å¯ä»¥è®“公告在指定時間範åœå…§é¡¯ç¤º + text: ä½ å¯ä»¥ä½¿ç”¨æ–‡ç« æ ¼å¼ï¼Œä½†è«‹å°å¿ƒåˆ¥è®“公告佔據太大的使用者畫é¢ç©ºé–“。 defaults: autofollow: 通éŽé‚€è«‹ç¶²å€è¨»å†Šçš„ç”¨æˆ¶å°‡æœƒè‡ªå‹•é—œæ³¨ä½ avatar: æ”¯æ´ PNG, GIF 或 JPG 圖片,檔案最大為 %{size}ï¼Œæœƒç¸®è£æˆ %{dimensions}px - bot: æé†’用戶本帳號是機械人 - context: æ‡‰è©²å¥—ç”¨éŽæ¿¾å™¨çš„ä¸€é …æˆ–å¤šé …å…§å®¹ - current_password: å› å®‰å…¨å› ç´ ï¼Œè«‹è¼¸å…¥ç›®å‰å¸³æˆ¶çš„密碼 + bot: 這個帳號是機械人,所åšçš„事情å¯èƒ½æ²’有經人為監察 + context: éŽæ¿¾å™¨æ‡‰è©²å¥—ç”¨çš„ä¸€é …æˆ–å¤šé …æ¢ä»¶ + current_password: 基於ä¿å®‰ç·£æ•…,請輸入目å‰å¸³è™Ÿçš„密碼 current_username: 請輸入目å‰å¸³æˆ¶çš„使用者åç¨±ä»¥ç¢ºèª digest: åƒ…åœ¨ä½ é•·æ™‚é–“æœªç™»éŒ„ï¼Œä¸”æ”¶åˆ°äº†ç§ä¿¡æ™‚ç™¼é€ - email: 您將收到一å°ç¢ºèªé›»å郵件 + discoverable: 個人資料目錄å¯ä»¥è®“ä½ çš„å¸³è™Ÿæ›´å»£ç‚ºäººçŸ¥ + email: ä½ å°‡æ”¶åˆ°ä¸€å°ç¢ºèªé›»éƒµ fields: 個人資料é å¯é¡¯ç¤ºå¤šè‡³ 4 å€‹é …ç›® header: æ”¯æ´ PNG, GIF 或 JPG 圖片,檔案最大為 %{size}ï¼Œæœƒç¸®è£æˆ %{dimensions}px - inbox_url: 從您想è¦ä½¿ç”¨çš„ä¸ç¹¼é¦–é è¤‡è£½ç¶²å€ - irreversible: å·²éŽæ¿¾çš„嘟文將會ä¸å¯é€†çš„æ¶ˆå¤±ï¼Œå³ä¾¿éŽæ¿¾å™¨ç§»é™¤ä¹‹å¾Œä¹Ÿä¸€æ¨£ + inbox_url: åœ¨ä½ æƒ³è¦ä½¿ç”¨çš„ä¸ç¹¼ç«™é¦–é ï¼Œè¤‡è£½å®ƒçš„ç¶²å€ + irreversible: æ–‡ç« éŽæ¿¾æ˜¯ä¸å¯é‚„原的,å³ä½¿æ—¥å¾ŒéŽæ¿¾å™¨è¢«ç§»é™¤ï¼Œä¹Ÿç„¡æ³•釿–°çœ‹åˆ°è¢«å®ƒæ¿¾èµ°çš„æ–‡ç« locale: 使用者介é¢ã€é›»éƒµå’Œé€šçŸ¥çš„語言 - locked: ä½ å¿…é ˆäººæ‰‹æ ¸å‡†æ¯å€‹ç”¨æˆ¶å°ä½ çš„é—œæ³¨è«‹æ±‚ï¼Œè€Œä½ çš„æ–‡ç« ç§éš±æœƒè¢«é è¨ç‚ºã€Œåªæœ‰é—œæ³¨ä½ 的人能看〠+ locked: ä½ å¿…é ˆæ‰‹å‹•å¯©æ ¸æ¯å€‹äººå°ä½ 的關注請求 password: 使用至少 8 個å—å…ƒ - phrase: 無論是嘟文的本文或是內容è¦å‘Šéƒ½æœƒè¢«éŽæ¿¾ - scopes: å…許讓應用程å¼å˜å–çš„ API。 è‹¥æ‚¨é¸æ“‡æœ€é«˜éšŽç¯„åœï¼Œå‰‡ç„¡é ˆé¸æ“‡å€‹åˆ¥é …目。 - setting_aggregate_reblogs: 請勿顯示最近已被轉嘟之嘟文的最新轉嘟(åªå½±éŸ¿æœ€æ–°æ”¶åˆ°çš„嘟文) + phrase: éŽæ¿¾å™¨æœƒé–±è®€æ–‡ç« 和內容è¦å‘Šæ¨™èªžçš„å—çœ¼ï¼Œç„¶å¾Œæ±ºå®šéŽæ¿¾èˆ‡å¦ + scopes: 鏿“‡æ‡‰ç”¨ç¨‹å¼å¯ä»¥å˜å–çš„ API。 è‹¥ä½ é¸æ“‡æœ€é«˜éšŽçš„æ¬Šé™ç¯„åœï¼Œå‰‡ç„¡é ˆé¸æ“‡å€‹åˆ¥é …目。 + setting_aggregate_reblogs: è«‹å‹¿é¡¯ç¤ºæ–°è¿‘è¢«è½‰æŽ¨çš„æ–‡ç« ï¼ˆåªå½±éŸ¿æœ€æ–°è¢«æŽ¨çš„æ–‡ç« ) setting_default_sensitive: æ•æ„Ÿåª’é«”é è¨éš±è—,且按一下å³å¯é‡æ–°é¡¯ç¤º setting_display_media_default: éš±è—æ¨™ç‚ºæ•感的媒體 setting_display_media_hide_all: ç¸½æ˜¯éš±è—æ‰€æœ‰åª’é«” setting_display_media_show_all: ç¸½æ˜¯é¡¯ç¤ºæ¨™ç‚ºæ•æ„Ÿçš„媒體 - setting_hide_network: ä½ é—œæ³¨çš„äººå’Œé—œæ³¨ä½ çš„äººå°‡ä¸æœƒåœ¨ä½ 的個人資料é 上顯示 + setting_hide_network: ä½ æ‰€é—œæ³¨çš„äººï¼Œå’Œé—œæ³¨ä½ çš„äººï¼Œå°‡ä¸æœƒåœ¨ä½ 的個人資料é 上顯示 setting_noindex: æ¤è¨å®šæœƒå½±éŸ¿åˆ°ä½ çš„å…¬é–‹å€‹äººè³‡æ–™ä»¥åŠæ–‡ç« é é¢ - setting_show_application: 您用來發嘟文的應用程å¼å°‡æœƒåœ¨æ‚¨å˜Ÿæ–‡çš„詳細檢視顯示 - username: 您的使用者å稱將在 %{domain} 是ç¨ä¸€ç„¡äºŒçš„ + setting_show_application: ä½ ç”¨ä¾†ç™¼è¡¨æ–‡ç« çš„æ‡‰ç”¨ç¨‹å¼ï¼Œå°‡æœƒé¡¯ç¤ºåœ¨ä½ æ–‡ç« çš„è©³ç´°æª¢è¦–ä¸ + setting_use_blurhash: 漸變圖樣會基於隱è—媒體內容產生,但所有細節會變得模糊 + setting_use_pending_items: 關閉自動滾動更新,時間軸會在點擊後更新 + username: ä½ çš„ä½¿ç”¨è€…å稱在 %{domain} 將是ç¨ä¸€ç„¡äºŒçš„ whole_word: 如果關éµå—æˆ–è©žçµ„åƒ…æœ‰å—æ¯èˆ‡æ•¸å—,則其將åªåœ¨ç¬¦åˆæ•´å€‹å–®å—çš„æ™‚å€™æ‰æœƒå¥—用 + domain_allow: + domain: æ¤ç¶²åŸŸå°‡èƒ½å¾žæ¤ç«™ç²å–資料,而æ¤ç«™ç™¼å‡ºçš„æ•¸æ“šä¹Ÿæœƒè¢«è™•ç†å’Œå˜å„²ã€‚ + email_domain_block: + domain: 這裡å¯ä»¥æ˜¯é›»éƒµåœ°å€ä¸çš„域åã€åŸŸåè§£æžåˆ°çš„MXè¨˜éŒ„ã€æˆ–MX紀錄解æžåˆ°çš„æœå‹™å™¨IP。如果上述資料被å°ç¦ï¼Œé‚£éº¼è¨»å†Šå°‡è¢«æ‹’絕。 + with_dns_records: Mastodon æœƒå˜—è©¦è§£æžæ‰€çµ¦åŸŸåçš„ DNS 記錄,然後與解æžçµæžœä¸€ä½µå°ç¦ featured_tag: - name: 您å¯èƒ½æƒ³ä½¿ç”¨å…¶ä¸ä¸€å€‹ï¼š + name: ä½ å¯èƒ½æƒ³ä½¿ç”¨å…¶ä¸ä¸€å€‹ï¼š form_challenge: - current_password: 您æ£è¦é€²å…¥å®‰å…¨å€åŸŸ + current_password: ä½ æ£è¦é€²å…¥å®‰å…¨å€åŸŸ imports: data: 自其他æœå‹™ç«™åŒ¯å‡ºçš„ CSV 檔案 invite_request: - text: 這會å”åŠ©æˆ‘å€‘å¯©æ ¸æ‚¨çš„æ‡‰ç”¨ç¨‹å¼ + text: é€™å°‡æœ‰åŠ©æˆ‘å€‘å¯©æ ¸ä½ çš„æ‡‰ç”¨ç¨‹å¼ + ip_block: + comment: å¯é¸ï¼Œä½†è«‹è¨˜å¾—è‡ªå·±ç‚ºç”šéº¼æ·»åŠ äº†é€™å€‹è¦å‰‡ã€‚ + expires_in: å› ç‚º IP ä½å€æ˜¯ç¶“常被分享或轉手的有é™è³‡æºï¼Œæ‰€ä»¥æˆ‘們ä¸å»ºè°ä½ ç„¡é™æœŸåœ°å°éŽ– IP ä½å€ã€‚ + ip: 請輸入 IPv4 或 IPv6 ä½å€ï¼Œä½ 亦å¯ä»¥ç”¨ CIDR 語法來å°éŽ–æ•´å€‹ IP 倿®µã€‚è«‹å°å¿ƒä½¿ç”¨ï¼Œä¸è¦æŠŠè‡ªå·±çµ¦ä¸€ä½µå°éŽ–ï¼ + severities: + no_access: å°éŽ–æ‰€æœ‰è³‡æºå˜å– + sign_up_requires_approval: 新登記申請æ£ç‰å€™ä½ 審批 + severity: è«‹è¨å®šä¼ºæœå™¨å°‡å¦‚何處ç†ä¾†è‡ªé€™å€‹ IP ä½å€çš„請求 sessions: otp: è¼¸å…¥ä½ æ‰‹æ©Ÿä¸Šç”Ÿæˆçš„é›™é‡èªè‰ç¢¼ï¼Œæˆ–者任æ„一個æ¢å¾©ä»£ç¢¼ï¼š + webauthn: 如果它是 USB 安全鑰匙的話,請先æ’入電腦。如鑰匙è¨è¨ˆæœ‰éœ€è¦ï¼Œè«‹æŒ‰éµå•Ÿç”¨ã€‚ tag: - name: 您åªèƒ½è®Šæ›´å¤§å°å¯«ï¼Œä¾‹å¦‚,以使其更易讀。 + name: ä½ åªèƒ½è®Šæ›´å¤§å°å¯«ï¼ˆä»¥ä½¿å…¶æ›´æ˜“讀)。 user: chosen_languages: åªæœ‰è¢«é¸æ“‡çš„語言會在公開時間軸內顯示 labels: @@ -63,20 +85,25 @@ zh-HK: fields: name: 標籤 value: 內容 + account_alias: + acct: 舊帳號å稱 + account_migration: + acct: 新帳號å稱 account_warning_preset: text: é è¨æ–‡å— title: 標題 admin_account_action: - include_statuses: 在電å郵件ä¸åŠ å…¥æª¢èˆ‰çš„å˜Ÿæ–‡ + include_statuses: 在電郵ä¸åŠ å…¥è¢«æª¢èˆ‰çš„æ–‡ç« send_email_notification: é€éŽé›»å信件通知使用者 text: 自訂è¦å‘Š - type: 動作 + type: æ“作 types: disable: åœç”¨ - none: 什麼也ä¸åš - silence: å®‰éœ - suspend: åœæ¬Šä¸¦ä¸å¯é€†çš„刪除帳戶資料 - warning_preset_id: 使用è¦å‘Šé è¨ + none: 發é€è¦å‘Š + sensitive: æ•æ„Ÿå†…容 + silence: é™åˆ¶ + suspend: åœæ¬Š + warning_preset_id: 使用é è¨è¦å‘Š announcement: all_day: 全天活動 ends_at: æ´»å‹•çµæŸæ™‚é–“ @@ -84,25 +111,26 @@ zh-HK: starts_at: 活動開始時間 text: 公告 defaults: - autofollow: é‚€è«‹åˆ¥äººé—œæ³¨ä½ çš„è³¬è™Ÿ + autofollow: é‚€è«‹åˆ¥äººé—œæ³¨ä½ çš„å¸³è™Ÿ avatar: 個人é åƒ bot: 這帳號是機械人 - chosen_languages: èªžè¨€éŽæ¿¾ + chosen_languages: æ‰€éŽæ¿¾èªžè¨€ confirm_new_password: ç¢ºèªæ–°å¯†ç¢¼ confirm_password: 確èªå¯†ç¢¼ - context: éŽæ¿¾æƒ…境 + context: æ‰€éŽæ¿¾æƒ…境 current_password: ç›®å‰å¯†ç¢¼ data: 資料 - discoverable: 在目錄列出æ¤å¸³æˆ¶ + discoverable: 在目錄列出æ¤å¸³è™Ÿ display_name: 顯示å稱 email: é›»éƒµåœ°å€ expires_in: 失效時間 fields: 資料 header: 個人é é¢é ‚部 + honeypot: "%{label} (è«‹ä¸è¦å¡«å¯«)" inbox_url: ä¸ç¹¼æ”¶ä»¶åŒ£çš„ URL - irreversible: 放棄而éžéš±è— + irreversible: 丟棄而éžéš±è— locale: 介é¢èªžè¨€ - locked: 將用戶轉為「ç§äººã€ + locked: 將帳號轉為「ç§äººã€ max_uses: 最大使用次數 new_password: 新密碼 note: 簡介 @@ -110,59 +138,76 @@ zh-HK: password: 密碼 phrase: é—œéµå—或片語 setting_advanced_layout: 啟用進階網é ä»‹é¢ - setting_aggregate_reblogs: 時間軸ä¸çš„群組轉嘟 + setting_aggregate_reblogs: 時間軸ä¸çš„群組轉推 setting_auto_play_gif: è‡ªå‹•æ’æ”¾ GIF setting_boost_modal: 在轉推å‰è©¢å•我 + setting_crop_images: å°‡æœªå±•é–‹æ–‡ç« ä¸çš„圖片è£å‰ªåˆ° 16x9 setting_default_language: æ–‡ç« èªžè¨€ setting_default_privacy: æ–‡ç« é è¨ç‚º setting_default_sensitive: é è¨æˆ‘çš„å…§å®¹ç‚ºæ•æ„Ÿå…§å®¹ - setting_delete_modal: 刪推å‰è©¢å•我 + setting_delete_modal: åˆªé™¤æ–‡ç« å‰ï¼Œè«‹è¦æ±‚æˆ‘ç¢ºèª + setting_disable_swiping: åœç”¨æ»‘動手勢 setting_display_media: 媒體顯示 setting_display_media_default: é è¨ setting_display_media_hide_all: å…¨éƒ¨éš±è— setting_display_media_show_all: 全部顯示 - setting_expand_spoilers: æ°¸é 展開標有內容è¦å‘Šçš„嘟文 + setting_expand_spoilers: æ°¸é 展開標有內容è¦å‘Šçš„æ–‡ç« setting_hide_network: éš±è—ä½ çš„ç¤¾äº¤ç¶²çµ¡ - setting_noindex: é˜»æ¢æœå°‹å¼•擎檢索 - setting_reduce_motion: 減低動畫效果 - setting_show_application: 顯示用來傳é€å˜Ÿæ–‡çš„æ‡‰ç”¨ç¨‹å¼ + setting_noindex: è²æ˜Žæœ¬ç«™ä¸å¸Œæœ›æœå°‹å™¨è®“外界æœå°‹ + setting_reduce_motion: 減少動畫效果 + setting_show_application: é¡¯ç¤ºç”¨ä¾†ç™¼è¡¨æ–‡ç« çš„æ‡‰ç”¨ç¨‹å¼ setting_system_font_ui: 使用系統é è¨å—åž‹ setting_theme: 網站主題 - setting_trends: 顯示本日趨勢 - setting_unfollow_modal: å–æ¶ˆé—œæ³¨å‰è·³å‡ºè©¢å•我 + setting_trends: 顯示今天熱門主題 + setting_unfollow_modal: å–æ¶ˆé—œæ³¨å‰è«‹è®“我確定 + setting_use_blurhash: 將隱è—媒體以彩色漸變圖樣表示 setting_use_pending_items: é™é€Ÿæ¨¡å¼ severity: ç‰ç´š + sign_in_token_attempt: 安全碼 type: 匯入資料類型 - username: 用戶å稱 - username_or_email: 用戶å稱或電郵 + username: 使用者å稱 + username_or_email: 使用者å稱或電郵 whole_word: 整個詞彙 + email_domain_block: + with_dns_records: 包括域åçš„ MX 記錄和 IP ä½å€ featured_tag: - name: "「#ã€æ¨™ç±¤" + name: 主題標籤 (Hashtag) interactions: - must_be_follower: éš±è—æ²’æœ‰é—œæ³¨ä½ çš„ç”¨æˆ¶çš„é€šçŸ¥ - must_be_following: éš±è—ä½ ä¸é—œæ³¨çš„用戶的通知 - must_be_following_dm: éš±è—ä½ ä¸é—œæ³¨çš„用戶的ç§ä¿¡ + must_be_follower: éš±è—ä½ é—œæ³¨è€…ä»¥å¤–çš„äººçš„é€šçŸ¥ + must_be_following: éš±è—ä½ ä¸é—œæ³¨çš„人的通知 + must_be_following_dm: éš±è—ä½ ä¸é—œæ³¨çš„人的ç§ä¿¡ invite: comment: 備註 invite_request: text: åŠ å…¥çš„åŽŸå› + ip_block: + comment: 備註 + ip: IP ä½å€ + severities: + no_access: å°éŽ– + sign_up_requires_approval: é™åˆ¶è¨»å†Š + severity: è¦å‰‡ notification_emails: digest: å®šæœŸé›»éƒµæ‘˜è¦ - favourite: 當有用戶喜æ¡ä½ çš„æ–‡ç« æ™‚ï¼Œç™¼é›»éƒµé€šçŸ¥ - follow: ç•¶æœ‰ç”¨æˆ¶é—œæ³¨ä½ æ™‚ï¼Œç™¼é›»éƒµé€šçŸ¥ - follow_request: ç•¶æœ‰ç”¨æˆ¶è¦æ±‚é—œæ³¨ä½ æ™‚ï¼Œç™¼é›»éƒµé€šçŸ¥ - mention: ç•¶æœ‰ç”¨æˆ¶åœ¨æ–‡ç« æåŠä½ 時,發電郵通知 - pending_account: 需è¦å¯©æ ¸çš„æ–°å¸³æˆ¶ - reblog: ç•¶æœ‰ç”¨æˆ¶è½‰æŽ¨ä½ çš„æ–‡ç« æ™‚ï¼Œç™¼é›»éƒµé€šçŸ¥ - report: ç•¶æäº¤æ–°æª¢èˆ‰æ™‚傳é€é›»å郵件 + favourite: 有人喜æ¡ä½ çš„æ–‡ç« + follow: ç•¶æœ‰äººé—œæ³¨ä½ æ™‚ + follow_request: ç•¶æœ‰äººè¦æ±‚é—œæ³¨ä½ æ™‚ + mention: ç•¶æœ‰äººåœ¨æ–‡ç« æåŠä½ 時 + pending_account: 有新帳號需è¦å¯©æ ¸æ™‚ + reblog: ç•¶æœ‰äººè½‰æŽ¨ä½ çš„æ–‡ç« æ™‚ + report: 收到新檢舉時 + trending_tag: ç•¶æœªå¯©æ ¸çš„æ¨™ç±¤æˆç‚ºç•¶å‰ç†±é–€æ™‚ tag: listable: å…許æ¤ä¸»é¡Œæ¨™ç±¤åœ¨æœå°‹åŠå€‹äººæª”案目錄ä¸é¡¯ç¤º name: 主題標籤 trendable: å…許æ¤ä¸»é¡Œæ¨™ç±¤åœ¨è¶¨å‹¢ä¸‹é¡¯ç¤º - usable: å…許嘟文使用æ¤ä¸»é¡Œæ¨™ç±¤ + usable: å…è¨±æ–‡ç« ä½¿ç”¨æ¤ä¸»é¡Œæ¨™ç±¤ 'no': å¦ recommended: å»ºè° required: mark: "*" text: å¿…é ˆå¡«å¯« + title: + sessions: + webauthn: ä½¿ç”¨ä½ çš„å®‰å…¨å¯†é‘°è£ç½®ä¾†ç™»å…¥ 'yes': 是 diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index a09c9945d7a1ee5a73ab6676be3ea6d951fbfa14..000ec529b003e910264b8fd65ba8ae487d4171b9 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -24,6 +24,7 @@ zh-TW: current_password: å› å®‰å…¨å› ç´ ï¼Œè«‹è¼¸å…¥ç›®å‰å¸³æˆ¶çš„密碼 current_username: 請輸入目å‰å¸³æˆ¶çš„使用者åç¨±ä»¥ç¢ºèª digest: åƒ…åœ¨ä½ é•·æ™‚é–“æœªç™»å…¥ä¸”åœ¨æœªç™»å…¥æœŸé–“æ”¶åˆ°ç§è¨Šæ™‚å‚³é€ + discoverable: åŠ å…¥å€‹äººè³‡æ–™ç›®éŒ„èƒ½æŽ¥è§¸æ›´å¤šé–±è½çœ¾ email: 您將收到一å°ç¢ºèªé›»å郵件 fields: 您å¯åœ¨å€‹äººè³‡æ–™ä¸Šæœ‰è‡³å¤š 4 å€‹ä»¥è¡¨æ ¼å½¢å¼é¡¯ç¤ºçš„é …ç›® header: æ”¯æ´ PNG, GIF 或 JPG 圖片,檔案最大為 %{size}ï¼ŒæœƒæŒ‰æ¯”ä¾‹ç¸®å°æˆ %{dimensions} åƒç´ @@ -74,6 +75,7 @@ zh-TW: types: disable: åœç”¨ none: 什麼也ä¸åš + sensitive: 有雷å°å¿ƒ silence: å®‰éœ suspend: åœæ¬Šä¸¦ä¸å¯é€†çš„刪除帳戶資料 warning_preset_id: 使用è¦å‘Šé è¨ @@ -146,6 +148,13 @@ zh-TW: comment: 備註 invite_request: text: åŠ å…¥çš„åŽŸå› + ip_block: + comment: 備註 + ip: IP ä½å€ + severities: + no_access: å°éŽ– + sign_up_requires_approval: é™åˆ¶è¨»å†Š + severity: è¦å‰‡ notification_emails: digest: 傳逿‘˜è¦ä¿¡ä»¶ favourite: 當有使用者喜æ¡ä½ 的嘟文時,傳é€é›»å信件通知 @@ -165,4 +174,7 @@ zh-TW: required: mark: "*" text: å¿…é ˆå¡«å¯« + title: + sessions: + webauthn: 使用您的安全金鑰來登入 'yes': 是 diff --git a/config/locales/sk.yml b/config/locales/sk.yml index e11fb3e691b812f4f8cf93410a95f40961d25bf7..bc214a4444fef2008754d331f7881ec4bf1a9deb 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -42,7 +42,9 @@ sk: domain: Server reason: 'Dôvod:' rejecting_media: 'Mediálne súbory z týchto serverov nebudú spracované, alebo ukladané, a nebudú z nich zobrazované žiadne náhľady, vyžadujúc ruÄné prekliknutie priamo až k pôvodnému súboru:' + rejecting_media_title: Triedené médiá silenced: 'PrÃspevky z týchto serverov budú skryté z verejných osà a z konverzáciÃ, a nebudú vytvorené žiadné oboznámena ohľadom aktivity ich užÃvateľov, pokiaľ ich nenásledujeÅ¡:' + silenced_title: UtÃÅ¡ené servery unavailable_content_html: Vo vÅ¡eobecnosti, Mastodon ti dovoľuje vidieÅ¥ obsah, a komunikovaÅ¥ s užÃvateľmi akéhokoľvek iného serveru v rámci fediversa. Toto sú výnimky, ktoré boli vytvorené na tomto konkrétnom serveri. user_count_after: few: užÃvateľov @@ -1159,26 +1161,22 @@ sk: formats: default: "%b %d, %R, %H:%M" two_factor_authentication: - code_hint: Pre potvrdenie teraz zadaj kód vygenerovaný pomocou tvojej overovacej aplikácie - description_html: Ak povolÃÅ¡ <strong> dvojfázové overovanie</strong>, na prihlásenie potom budeÅ¡ potrebovaÅ¥ svoj telefón, ktorý vygeneruje prÃstupové kódy, Äo musÃÅ¡ zadaÅ¥. disable: Zakáž - enable: Povoľ enabled: Dvojfázové overovanie je povolené enabled_success: Dvojfázové overovanie úspeÅ¡ne povolené generate_recovery_codes: Vygeneruj zálohové kódy - instructions_html: "<strong>Naskenuj tento QR kód do Google Autentikátora, alebo do podobnej TOTP aplikácie pomocou svojho telefónu.</strong> Od tejto chvÃle bude táto aplikácia pre teba generovaÅ¥ kódy ktoré musÃÅ¡ zadaÅ¥ aby si sa prihlásil/a." lost_recovery_codes: Zálohové kódy ti umožnia dostaÅ¥ sa k svojmu úÄtu ak stratÃÅ¡ telefón. Pokiaľ si stratila svoje zálohové kódy, môžeÅ¡ si ich tu znovu vygenerovaÅ¥. Tvoje staré zálohové kódy budú zneplatnené. - manual_instructions: 'Pokiaľ nemôžeÅ¡ oskenovaÅ¥ daný QR kód, a potrebujeÅ¡ ho zadaÅ¥ ruÄne, tu je tajomstvo v textovom formáte:' recovery_codes: Zálohuj kódy pre obnovu recovery_codes_regenerated: Zálohové kódy boli úspeÅ¡ne zvova vygenerované recovery_instructions_html: KeÄ hocikedy stratÃÅ¡ prÃstup k svojmu telefónu, môžeÅ¡ použiÅ¥ jeden z prÃstupových kódov nižšie pre obnovenie prÃstupu k svojmu úÄtu. <strong>Skladuj tieto prÃstupové kódy na bezpeÄnom mieste</strong>. NaprÃklad ich môžeÅ¡ vytlaÄiÅ¥ a uložiÅ¥ ich spolu s inými dôležitými dokumentami. - setup: Nastav - wrong_code: Zadaný kód bol neplatný! Je serverový Äas a Äas na zariadenà správny? user_mailer: backup_ready: explanation: Vyžiadal/a si si úplnú zálohu svojho Mastodon úÄtu. Táto záloha je teraz pripravená na stiahnutie! subject: Tvoj archÃv je pripravený na stiahnutie title: Odber archÃvu + sign_in_token: + subject: ProsÃm potvrÄ pokus o prihlásenie + title: Pokus o prihlásenie warning: explanation: disable: Pokiaľ je tvoj úÄet zamrazený, tvoje dáta zostávajú nedoknuté, ale nemôžeÅ¡ v rámci neho niÄ robiÅ¥, až kým nebude odomknutý. diff --git a/config/locales/sl.yml b/config/locales/sl.yml index a7cf869a4060f7f41539e638ce097a52a0b5f1b7..91466c9c249d6287b0dafea722ded866fd4f7d7f 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1024,21 +1024,14 @@ sl: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Za potrditev vnesite kodo, ki jo je ustvarila aplikacija za preverjanje pristnosti - description_html: ÄŒe omogoÄite <strong>dvofaktorsko preverjanje pristnosti</strong>, boste za prijavo morali imeti svoj telefon, s katerim boste ustvarili žetone za vstop. disable: OnemogoÄi - enable: OmogoÄi enabled: Dvofaktorsko preverjanje pristnosti je omogoÄeno enabled_success: Dvofaktorsko preverjanje pristnosti je uspeÅ¡no omogoÄeno generate_recovery_codes: Ustvari kode za obnovitev - instructions_html: "<strong>Skenirajte QR kodo z Google Authenticator ali s podobno aplikacijo TOTP</strong>. Od zdaj naprej bo ta aplikacija ustvarjala žetone, ki jih boste morali vnesti ob prijavi." lost_recovery_codes: Obnovitvene kode vam omogoÄajo, da ponovno pridobite dostop do svojega raÄuna, Äe izgubite telefon. ÄŒe ste izgubili obnovitvene kode, jih lahko obnovite tukaj. VaÅ¡e stare obnovitvene kode bodo neveljavne. - manual_instructions: 'ÄŒe ne morete skenirati QR kode in jo morate vnesti roÄno, je tu skrivnost v tekstovni obliki:' recovery_codes: Varnostna kopija obnovitvenih kod recovery_codes_regenerated: Obnovitvene kode so bile uspeÅ¡no regenerirane recovery_instructions_html: ÄŒe kdaj izgubite dostop do telefona, lahko uporabite eno od spodnjih obnovitvenih kod, da ponovno pridobite dostop do svojega raÄuna. <strong>Shranite obnovitvene kode</strong>. Lahko jih natisnete in shranite z drugimi pomembnimi dokumenti. - setup: Nastavi - wrong_code: Vnesena koda je bila neveljavna! Ali sta Äas strežnika in Äas naprave pravilna? user_mailer: backup_ready: explanation: Zahtevali ste popolno varnostno kopijo raÄuna Mastodon. Zdaj je pripravljen za prenos! diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 33718f1a8e1cec91a0727495bf8e45237d394546..e841ab690599ec148277c4aa202840ede0c94103 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -60,6 +60,7 @@ sq: one: Ndjekës other: Ndjekës following: Ndjekje + instance_actor_flash: Kjo llogari është një aktor virtual, i përdorur për të përfaqësuar vetë shërbyesin dhe jo ndonjë përdorues individual. Përdoret për qëllime federimi dhe s’duhet pezulluar. joined: U bë pjesë më %{date} last_active: aktiv së fundi link_verified_on: Pronësia e kësaj lidhjeje qe kontrolluar më %{date} @@ -98,6 +99,7 @@ sq: add_email_domain_block: Vëre përkatësinë email në listë bllokimesh approve: Miratojeni approve_all: Miratojini krejt + approved_msg: U miratua me sukses aplikimi për regjistrim të %{username} are_you_sure: Jeni i sigurt? avatar: Avatar by_domain: Përkatësi @@ -111,8 +113,10 @@ sq: confirm: Ripohojeni confirmed: U ripohua confirming: Po ripohohet + delete: Fshiji të dhënat deleted: U fshi demote: Zhgradoje + destroyed_msg: Të dhënat e %{username} tani janë vënë në radhë për fshirje të menjëhershme disable: Çaktivizoje disable_two_factor_authentication: Çaktivizoni 2FA-në disabled: E çaktivizuar @@ -123,10 +127,12 @@ sq: email_status: Gjendje email-i enable: Aktivizoje enabled: E aktivizuar + enabled_msg: U hoq me sukses ngrirja për llogarinë e %{username} followers: Ndjekës follows: Ndjekje header: Krye inbox_url: URL Mesazhesh të Marrë + invite_request_text: Arsye për pjesëmarrje invited_by: Ftuar nga ip: IP joined: U bë pjesë @@ -138,6 +144,8 @@ sq: login_status: Gjendje hyrjeje media_attachments: Bashkëngjitje media memorialize: Shndërroje në përkujtimore + memorialized: U shndërrua në përkujtimore + memorialized_msg: "%{username} u kthye me sukses në një llogari përkujtimore" moderation: active: Aktiv all: Krejt @@ -158,10 +166,14 @@ sq: public: Publike push_subscription_expires: Pajtimi PuSH skadon më redownload: Rifresko profilin + redownloaded_msg: Profili i %{username} u rifreskua me sukses prej origjinës reject: Hidhe tej reject_all: Hidhi krejt tej + rejected_msg: Aplikimi për regjistrim i %{username} u hodh poshtë me sukses remove_avatar: Hiqe avatarin remove_header: Hiqe kryen + removed_avatar_msg: U hoq me sukses figura e avatarit të %{username} + removed_header_msg: U hoq me sukses figura e kreut për %{username} resend_confirmation: already_confirmed: Ky përdorues është i ripohuar tashmë send: Ridërgo email ripohimi @@ -178,6 +190,8 @@ sq: search: Kërkoni search_same_email_domain: Të tjerë përdorues me të njëjtën përkatësi email-i search_same_ip: Të tjerë përdorues me të njëjtën IP + sensitive: Rezervat + sensitized: iu vu shenjë si rezervat shared_inbox_url: URL kutie të përbashkët mesazhesh show: created_reports: Ka bërë raportime @@ -187,13 +201,19 @@ sq: statuses: Gjendje subscribe: Pajtomë suspended: Të pezulluara + suspension_irreversible: Të dhënat e kësaj llogarie janë fshirë në mënyrë të pakthyeshme. Mund ta shpezulloni llogarinë, për ta bërë të përdorshme, por kjo s’do të kthejë ndonjë të dhënë që kihej më parë. + suspension_reversible_hint_html: Llogaria është pezulluar, dhe të dhënat do të hiqen plotësisht më %{date}. Deri atëherë, llogaria mund të rikthehet pa ndonjë zarar. Nëse doni të hiqen menjëherë krejt të dhënat e llogarisë, këtë mund ta bëni më poshtë. time_in_queue: Pritje në radhë %{time} title: Llogari unconfirmed_email: Email i paripohuar + undo_sensitized: Hiqja shenjën si rezervat undo_silenced: Zhbëje heshtjen undo_suspension: Zhbëje pezullimin + unsilenced_msg: U hoqën me sukses kufizimet për llogarinë e %{username} unsubscribe: Shpajtohuni + unsuspended_msg: U hoq me sukses pezullimi për llogarinë e %{username} username: Emër përdoruesi + view_domain: Shihni përmbledhjen për përkatësinë warn: Sinjalizoje web: Web whitelisted: Lejuar për federim @@ -208,12 +228,14 @@ sq: create_domain_allow: Krijo Lejim Përkatësie create_domain_block: Krijo Bllokim Përkatësie create_email_domain_block: Krijo Bllokim Përkatësie Email-esh + create_ip_block: Krijoni Rregull IP demote_user: Zhgradoje Përdoruesin destroy_announcement: Fshije Lajmërimin destroy_custom_emoji: Fshi Emotikon Vetjak destroy_domain_allow: Fshi Lejim Përkatësie destroy_domain_block: Fshi Bllokim Përkatësie destroy_email_domain_block: Fshi bllokim përkatësie email-esh + destroy_ip_block: Fshini Rregull IP destroy_status: Fshi Gjendje disable_2fa_user: Çaktivizo 2FA-në disable_custom_emoji: Çaktivizo Emotikon Vetjak @@ -226,13 +248,16 @@ sq: reopen_report: Rihape Raportimin reset_password_user: Ricaktoni Fjalëkalimin resolve_report: Zgjidhe Raportimin + sensitive_account: I vini shenjë si rezervat medias në llogarinë tuaj silence_account: Heshtoje Llogarinë suspend_account: Pezulloje Llogarinë unassigned_report: Hiqe Caktimin e Raportimit + unsensitive_account: Hiqjani shenjën si rezervat medias në llogarinë tuaj unsilence_account: Hiqe Heshtimin e Llogarisë unsuspend_account: Hiqe Pezullimin e Llogarisë update_announcement: Përditëso Lajmërimin update_custom_emoji: Përditëso Emotikon Vetjak + update_domain_block: Përditëso Bllok Përkatësish update_status: Përditëso Gjendjen actions: assigned_to_self_report: "%{name} ia kaloi raportimin %{target} në ngarkim vetvetes" @@ -244,12 +269,14 @@ sq: create_domain_allow: "%{name} kaloi në listë lejimesh përkatësinë %{target}" create_domain_block: "%{name} bllokoi përkatësinë %{target}" create_email_domain_block: "%{name} shtoi në listë bllokimesh përkatësinë %{target}" + create_ip_block: "%{name} krijoi rregull për IP-në %{target}" demote_user: "%{name} zhgradoi përdoruesin %{target}" destroy_announcement: "%{name} fshiu lajmërimin për %{target}" destroy_custom_emoji: "%{name} asgjësoi emotikonin %{target}" destroy_domain_allow: "%{name} hoqi përkatësinë %{target} nga listë lejimesh" destroy_domain_block: "%{name} zhbllokoi përkatësinë %{target}" destroy_email_domain_block: "%{name} e shtoi në listë lejimesh përkatësinë %{target}" + destroy_ip_block: "%{name} fshiu rregull për IP-në %{target}" destroy_status: "%{name} hoqi gjendje nga %{target}" disable_2fa_user: "%{name} çaktivizoi domosdoshmëritë për dyfaktorësh për përdoruesin %{target}" disable_custom_emoji: "%{name} çaktivizoi emotikonin %{target}" @@ -262,13 +289,16 @@ sq: reopen_report: "%{name} rihapi raportimin %{target}" reset_password_user: "%{name} ricaktoi fjalëkalimi për përdoruesin %{target}" resolve_report: "%{name} zgjidhi raportimin %{target}" + sensitive_account: "%{name} i vuri shenjë si rezervat medias në %{target}" silence_account: "%{name} heshtoi llogarinë e %{target}" suspend_account: "%{name} pezulloi llogarinë e %{target}" unassigned_report: "%{name} rihapi raportimin %{target}" + unsensitive_account: "%{name} ia hoqi shenjën si rezervat medias në %{target}" unsilence_account: "%{name} hoqi heshtimin për llogarinë %{target}" unsuspend_account: "%{name} hoqi pezullimin për llogarinë e %{target}" update_announcement: "%{name} përditësoi lajmërimin %{target}" update_custom_emoji: "%{name} përditësoi emotikonin %{target}" + update_domain_block: "%{name} përditësoi bllok përkatësish për %{target}" update_status: "%{name} përditësoi gjendjen me %{target}" deleted_status: "(fshiu gjendjen)" empty: S’u gjetën regjistra. @@ -372,6 +402,8 @@ sq: silence: Heshtoji suspend: Pezulloje title: Bllokim i ri përkatësie + obfuscate: Errësoje emrin e përkatësisë + obfuscate_hint: Errësoje pjesërisht emrin e përkatësisë te lista, nëse është aktivizuar publikimi i listës së kufizimeve të përkatësive private_comment: Koment privat private_comment_hint: Koment mbi këtë kufizim përkatësie për përdorim të brendshëm nga moderatorët. public_comment: Koment publik @@ -411,6 +443,7 @@ sq: instances: by_domain: Përkatësi delivery_available: Ka shpërndarje të mundshme + empty: S’u gjetën përkatësi. known_accounts: one: "%{count} llogari e njohur" other: "%{count} llogari të njohura" @@ -434,6 +467,21 @@ sq: expired: I skaduar title: Filtrim title: Ftesa + ip_blocks: + add_new: Krijoni rregull + created_msg: U shtua me sukses rregull i ri IP + delete: Fshije + expires_in: + '1209600': 2 javë + '15778476': 6 muaj + '2629746': 1 muaj + '31556952': 1 vit + '86400': 1 ditë + '94670856': 3 vjet + new: + title: Krijoni rregull IP të ri + no_ip_block_selected: S’u ndryshua ndonjë rregull IP, ngaqë s’u përzgjodh ndonjë i tillë + title: Rregulla IP pending_accounts: title: Llogari pezull (%{count}) relationships: @@ -473,6 +521,8 @@ sq: comment: none: Asnjë created_at: Raportuar më + forwarded: U përcoll + forwarded_to: U përcoll te %{domain} mark_as_resolved: Vëri shenjë si i zgjidhur mark_as_unresolved: Vëri shenjë si të pazgjidhur notes: @@ -516,6 +566,7 @@ sq: domain_blocks_rationale: title: Shfaq arsye enable_bootstrap_timeline_accounts: + desc_html: Bëj që përdoruesit e rinj automatikisht të ndjekin llogaritë e formësuara, që prurja e tyre bazë të mos nisë e zbrazët title: Aktivizo ndjekje parazgjedhje për përdorues të rinj hero: desc_html: E shfaqur në faqen ballore. Këshillohet të paktën 600x100px. Kur nuk caktohet gjë, përdoret miniaturë e shërbyesit @@ -542,6 +593,9 @@ sq: min_invite_role: disabled: Asnjë title: Lejo ftesa nga + require_invite_text: + desc_html: Kur regjistrimet lypin miratim dorazi, tekstin e kërkesës për ftesë “Pse doni të merrni pjesë?†bëje të detyrueshëm, në vend se opsional + title: Kërkoju përdoruesve të rinj të plotësojnë doemos një tekst kërkese për ftesë registrations_mode: modes: approved: Për regjistrim, lypset miratimi @@ -681,8 +735,11 @@ sq: prefix_sign_up: Regjistrohuni në Mastodon që sot! suffix: Me një llogari, do të jeni në gjendje të ndiqni persona, përditësime postimesh dhe të shkëmbeni mesazhe me përdorues nga cilido shërbyes Mastodon, etj! didnt_get_confirmation: S’morët udhëzime ripohimi? + dont_have_your_security_key: S’i keni kyçet tuaj të sigurisë? forgot_password: Harruat fjalëkalimin tuaj? invalid_reset_password_token: Token-i i ricaktimit të fjalëkalimit është i pavlefshëm ose ka skaduar. Ju lutemi, kërkoni një të ri. + link_to_otp: Jepni një kod mirëfilltësimi dyfaktorësh prej telefonit tuaj ose një kod rimarrjeje + link_to_webauth: Përdorni pajisjen tuaj të kyçeve të sigurisë login: Hyni logout: Dalje migrate_account: Kaloni në një tjetër llogari @@ -707,7 +764,9 @@ sq: functional: Llogaria juaj është tërësisht funksionale. pending: Aplikimi juaj është në pritje të shqyrtimit nga stafi ynë. Kjo mund të dojë ca kohë. Nëse aplikimi juaj miratohet, do të merrni një email. redirecting_to: Llogaria juaj është joaktive, ngaqë aktualisht ridrejton te %{acct}. + too_fast: Formulari u parashtrua shumë shpejt, riprovoni. trouble_logging_in: Probleme me hyrjen? + use_security_key: Përdor kyç sigurie authorize_follow: already_following: E ndiqni tashmë këtë llogari already_requested: Keni dërguar tashmë një kërkesë ndjekjeje te ajo llogari @@ -732,6 +791,7 @@ sq: date: formats: default: "%b %d, %Y" + with_month_name: "%d %B, %Y" datetime: distance_in_words: about_x_hours: "%{count}o" @@ -796,6 +856,7 @@ sq: request: Kërkoni arkivin tuaj size: Madhësi blocks: Bllokoni + bookmarks: Faqerojtës csv: CSV domain_blocks: Bllokime përkatësish lists: Lista @@ -863,6 +924,8 @@ sq: status: Gjendje verifikimi view_proof: Shihni provën imports: + errors: + over_rows_processing_limit: përmban më shumë se %{count} rreshta modes: merge: Përzieji merge_long: Mbaji zërat ekzistues dhe shto të rinjtë @@ -872,6 +935,7 @@ sq: success: Të dhënat tuaja u ngarkuan me sukses dhe tani do të përpunohet në kohë types: blocking: Listë bllokimesh + bookmarks: Faqerojtës domain_blocking: Listë bllokimesh përkatësish following: Listë ndjekjesh muting: Listë heshtimesh @@ -992,6 +1056,14 @@ sq: quadrillion: K thousand: M trillion: T + otp_authentication: + code_hint: Që të bëhet ripohimi, jepni kodin e prodhuar nga aplikacioni juaj i mirëfilltësimeve + description_html: Nëse aktivizoni <strong>mirëfilltësim dyfaktorësh</strong> duke përdorur një aplikacion mirëfilltësimesh, hyrja do të dojë që të keni telefonin tuaj, i cili do të prodhojë për ju token-ë hyrjesh. + enable: Aktivizoje + instructions_html: "<strong>Skanoje këtë kod QR me Google Authenticator ose një aplikacion të ngjashëm TOTP në telefonin tuaj</strong>. Tani e tutje, ai aplikacion do të prodhojë token-ë të cilët do t’ju duhet t’i jepni kur bëni hyrje." + manual_instructions: 'Nëse nuk skanoni kodin QR dhe ju duhet ta jepni dorazi, ja e fshehta si tekst i thjeshtë:' + setup: Ujdiseni + wrong_code: Kodi i dhënë është i pavlefshëm! A janë të sakta koha e shërbyesit dhe koha e pajisjes? pagination: newer: Më të ri next: Pasuesi @@ -1020,6 +1092,7 @@ sq: relationships: activity: Veprimtari llogarie dormant: Në gjumë + follow_selected_followers: Ndiq ndjekësit e përzgjedhur followers: Ndjekës following: Ndjek invited: Të ftuar @@ -1116,6 +1189,7 @@ sq: profile: Profil relationships: Ndjekje dhe ndjekës two_factor_authentication: Mirëfilltësim Dyfaktorësh + webauthn_authentication: Kyçe sigurie spam_check: spam_detected: Ky është një raportim i automatizuar. Është pikasur mesazh i padëshiruar. statuses: @@ -1154,6 +1228,8 @@ sq: other: "%{count} vota" vote: Votë show_more: Shfaq më tepër + show_newer: Shfaq më të reja + show_older: Shfaq më të vjetra show_thread: Shfaq rrjedhën sign_in_to_participate: Bëni hyrjen, që të merrni pjesë te biseda title: '%{name}: "%{quote}"' @@ -1262,21 +1338,20 @@ sq: default: "%d %b, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Që të bëhet ripohimi, jepni kodin e prodhuar nga aplikacioni juaj i mirëfilltësimeve - description_html: Nëse aktivizoni <strong>mirëfilltësimin dyfaktorësh</strong>, hyrja do të kërkojë të jeni në zotërim të telefonit tuaj, i cili do të prodhojë kod që duhet ta jepni. + add: Shtoje disable: Çaktivizoje - enable: Aktivizoje + disabled_success: Mirëfilltësimi dyfaktorësh u çaktivizua me sukses + edit: Përpunojeni enabled: Mirëfilltësimi dyfaktorësh është i aktivizuar enabled_success: Mirëfilltësimi dyfaktorësh u aktivizua me sukses generate_recovery_codes: Prodho kode rikthimesh - instructions_html: "<strong>Skanojeni këtë kod QR me Google Authenticator ose një aplikacion TOTP të ngjashëm në telefonin tuaj</strong>. Tani e tutje, ai aplikacion do të prodhojë kode të cilët duhet t’i jepni kur bëni hyrje." lost_recovery_codes: Kodet e rikthimit ju lejojnë të rifitoni hyrje në llogarinë tuaj, nëse humbni telefonin tuaj. Nëse keni humbur kodet tuaj të rikthimit, mund t’i prodhoni sërish këtu. Kodet tuaj të vjetër të rikthimit do të bëhen të pavlefshëm. - manual_instructions: 'Nëse nuk skanoni dot kodin QR dhe ju duhet ta jepni dorazi, ja e fshehta si tekst i thjeshtë:' + methods: Metoda dyfaktorëshi + otp: Aplikacion mirëfilltësimesh recovery_codes: Kopjeruani kode rikthimesh recovery_codes_regenerated: Kodet e rikthimeve u riprodhuan me sukses recovery_instructions_html: Në ndodhtë që të humbni hyrje te telefoni juaj, mund të përdorni një nga kodet e rikthimit më poshtë, që të rifitoni hyrje te llogaria juaj. <strong>Mbajini të parrezikuar kodet e rikthimeve</strong>. Për shembull, mund t’i shtypni dhe t’i ruani tok me dokumente të tjerë të rëndësishëm. - setup: Ujdiseni - wrong_code: Kodi i dhënë është i pavlefshëm! A janë të sakta koha e shërbyesit dhe koha e pajisjes? + webauthn: Kyçe sigurie user_mailer: backup_ready: explanation: Kërkuat një kopjeruajtje të plotë të llogarisë tuaj Mastodon. E keni gati për shkarkim! @@ -1291,6 +1366,7 @@ sq: warning: explanation: disable: Kur llogaria juaj është e ngrirë, të dhënat në llogarinë tuaj mbeten të paprekura, por s’mund të kryeni ndonjë veprim, para se të shkyçet. + sensitive: Kartelat tuaja media të ngarkuara dhe media e lidhur prej jush do të trajtohet si rezervat. silence: Kur llogaria juaj është e kufizuar, mesazhet tuaj në këtë shërbyes do t’i shohin vetëm personat që ju ndjekin tashmë. dhe mund të liheni jashtë nga lista të ndryshme publike. Megjithatë, të tjerët prapë mund t’ju ndjekin dorazi. suspend: Llogaria juaj është pezulluar, dhe krejt mesazhet tuaja dhe kartelat media të ngarkuara janë hequr në mënyrë të pakthyeshme nga ky shërbyes, dhe nga shërbyesit te të cilët kishit ndjekës. get_in_touch: Që të lidheni me ekipin e %{instance}, mund t’i përgjigjeni këtij email-i. @@ -1299,11 +1375,13 @@ sq: subject: disable: Llogaria juaj %{acct} është ngrirë none: Sinjalizim për %{acct} + sensitive: Medias postuar nga llogaria juaj %{acct} i është vënë shenjë si rezervat silence: Llogaria juaj %{acct} është kufizuar suspend: Llogaria juaj %{acct} është pezulluar title: disable: Llogari e ngrirë none: Sinjalizim + sensitive: Medias tuaj i është vënë shenjë si rezervat silence: Llogari e kufizuar suspend: Llogari e pezulluar welcome: @@ -1324,9 +1402,11 @@ sq: tips: Ndihmëza title: Mirë se vini, %{name}! users: + blocked_email_provider: Ky furnizues shërbimi email nuk lejohet follow_limit_reached: S’mund të ndiqni më tepër se %{limit} persona generic_access_help_html: Problem me hyrjen në llogarinë tuaj? Për asistencë mund të lidheni me %{email} invalid_email: Adresa email është e pavlefshme + invalid_email_mx: Adresa email s’duket se ekziston invalid_otp_token: Kod dyfaktorësh i pavlefshëm invalid_sign_in_token: Kod sigurie i pavlefshëm otp_lost_help_html: Nëse humbi hyrjen te të dy, mund të lidheni me %{email} @@ -1336,3 +1416,20 @@ sq: verification: explanation_html: 'Mundeni <strong>të verifikoni veten si i zoti i lidhjeve te tejtëdhënat e profilit tuaj</strong>. Për këtë, sajti i lidhur duhet të përmbajë një lidhje për te profili juaj Mastodon. Lidhje për te ajo <strong>duhet</strong> të ketë një atribut <code>rel="me"</code>. Lënda tekst e lidhjes nuk ngre peshë. Ja një shembull:' verification: Verifikim + webauthn_credentials: + add: Shton kyç të ri sigurie + create: + error: Pati një problem me shtimin e kyçeve tuaj të sigurisë. Ju lutemi, riprovoni. + success: Kyçi juaj i sigurisë u shtua me sukses. + delete: Fshije + delete_confirmation: Jeni i sigurt se doni të fshihet ky kyç sigurie? + description_html: Nëse aktivizoni <strong>mirëfilltësim me kyç sigurie</strong>, hyrja do të kërkojë që të përdorni një nga kyçet tuaj të sigurisë. + destroy: + error: Pati një problem me fshirjen e kyçit tuaj të sigurisë. Ju lutemi, riprovoni. + success: Kyçi juaj i sigurisë u fshi me sukses. + invalid_credential: Kyç i pavlefshëm sigurie + nickname_hint: Jepni nofkën e kyçit tuaj të ri të sigurisë + not_enabled: S’e keni aktivizuar ende WebAuthn-in + not_supported: Ky shfletues nuk mbulon kyçe sigurie + otp_required: Që të përdoren kyçe sigurie, ju lutemi, së pari aktivizoni mirëfilltësimin dyfaktorësh. + registered_on: Regjistruar më %{date} diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index 61cea8c21408df18084dc92c49af83eb3305fc3c..da8eda86f48ec44af412edce44985ecbfbbe2477 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -472,21 +472,14 @@ sr-Latn: themes: default: Mastodont two_factor_authentication: - code_hint: Unesite kod sa VaÅ¡e aplikacije za proveru identiteta da potvrdite - description_html: Ako ukljuÄite <strong>dvofaktorsku identifikaciju</strong>, moraćete da imate telefon sa sobom da biste mogli da se prijavite. Telefon će onda generisati tokene za VaÅ¡u prijavu. disable: IskljuÄi - enable: UkljuÄi enabled: Dvofaktorska identifikacija je ukljuÄena enabled_success: Dvofaktorska identifikacija je uspeÅ¡no ukljuÄena generate_recovery_codes: GeneriÅ¡i kodove za oporavak - instructions_html: "<strong>Skenirajte ovaj QR kod u Google Authenticator ili nekoj sliÄnoj TOTP aplikaciji na VaÅ¡em telefonu</strong>. Od sada, ta aplikacija će Vam generisati tokene koje morate uneti da biste se prijavili." lost_recovery_codes: Kodovi za oporavak Vam omogućavaju da povratite pristup nalogu ako izgubite telefon. Ako izgubite kodove za oporavak, možete ih regenerisati ovde. Od tog trenutka, stari kodovi za oporavak viÅ¡e ne važe. - manual_instructions: 'Ukoliko ne možete da skenirate QR kod i morate ga unesete ruÄno, evo je ogoljena Å¡ifra:' recovery_codes: Napravite rezervu kodova za oporavak recovery_codes_regenerated: Kodovi za oporavak uspeÅ¡no regenerisani recovery_instructions_html: Ako ikada izgubite pristup telefonu, možete iskoristiti kodove za oporavak date ispod da povratite pristup nalogu. <strong>Držite kodove za oporavak na sigurnom</strong>. Na primer, odÅ¡tampajte ih i Äuvajte ih sa ostalim važnim dokumentima. - setup: NameÅ¡tanje - wrong_code: Uneseni kod nije ispravan! Da li su vremena na serveru i na ureÄ‘aju ispravna? users: invalid_email: Adresa e-poÅ¡te nije ispravna invalid_otp_token: Neispravni dvofaktorski kod diff --git a/config/locales/sr.yml b/config/locales/sr.yml index d7fb6f74d6aea13650e6700c6009dad4ac6f15e5..e26682891c25b7df7f3b6844df565bd2a9c965e8 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -757,21 +757,14 @@ sr: default: МаÑтодон mastodon-light: МаÑтодон (Ñветло) two_factor_authentication: - code_hint: Да биÑте потврдили, унеÑите код генериÑан од Ñтране ваше апликације за потврду идентитета - description_html: Ðко укључите <strong>двофакторÑку идентификацију</strong>, мораћете да имате телефон Ñа Ñобом да биÑте могли да Ñе пријавите. Телефон ће онда генериÑати токене за Вашу пријаву. disable: ИÑкључи - enable: Омогући enabled: ДвофакторÑка идентификација је укључена enabled_success: ДвофакторÑка идентификација је уÑпешно укључена generate_recovery_codes: Генериши кодове за опоравак - instructions_html: "<strong>Скенирајте овај QR код у Google Authenticator или некој Ñличној TOTP апликацији на Вашем телефону</strong>. Од Ñада, та апликација ће Вам генериÑати токене које морате унети да биÑте Ñе пријавили." lost_recovery_codes: Кодови за опоравак Вам омогућавају да повратите приÑтуп налогу ако изгубите телефон. Ðко изгубите кодове за опоравак, можете их ре-генериÑати овде. Од тог тренутка, Ñтари кодови за опоравак више не важе. - manual_instructions: 'Уколико не можете да Ñкенирате QR код и морате га унеÑете ручно, ево је огољена шифра:' recovery_codes: Ðаправите резерву кодова за опоравак recovery_codes_regenerated: Кодови за опоравак уÑпешно ре-генериÑани recovery_instructions_html: Ðко икада изгубите приÑтуп телефону, можете иÑкориÑтити кодове за опоравак дате иÑпод да повратите приÑтуп налогу. <strong>Држите кодове за опоравак на Ñигурном</strong>. Ðа пример, одштампајте их и чувајте их Ñа оÑталим важним документима. - setup: Ðамештање - wrong_code: УнеÑени код није иÑправан! Да ли Ñу времена на Ñерверу и на уређају иÑправна? user_mailer: backup_ready: explanation: Тражили Ñте потпуну резервну копију вашег МаÑтодон рачуна. Спремна за преузимање! diff --git a/config/locales/sv.yml b/config/locales/sv.yml index ebedfb4f944ce47964f4a839bb40ad113a69bc2f..36154b49b4162f5d410d86a5e11318a4c2e53eb9 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -21,7 +21,9 @@ sv: federation_hint_html: Med ett konto pÃ¥ %{instance} kommer du att kunna följa personer pÃ¥ alla Mastodon-servers och mer än sÃ¥. get_apps: Prova en mobilapp hosted_on: Mastodon-värd pÃ¥ %{domain} - instance_actor_flash: Detta konto är en virtuell agent som används för att representera servern själv och inte nÃ¥gon individuell användare. Det används av sammanslutningsskäl och ska inte blockeras sÃ¥vitt du inte vill blockera hela instansen, och för detta fall ska domänblockering användas. + instance_actor_flash: 'Detta konto är en virtuell agent som används för att representera servern själv och inte nÃ¥gon individuell användare. Det används av sammanslutningsskäl och ska inte blockeras sÃ¥vitt du inte vill blockera hela instansen, och för detta fall ska domänblockering användas. + +' learn_more: Lär dig mer privacy_policy: Integritetspolicy see_whats_happening: Se vad som händer @@ -41,6 +43,9 @@ sv: suspended: 'Ingen data frÃ¥n dessa serverdatorer kommer bearbetas, lagras eller bytas ut vilket omöjliggör kommunikation med användare frÃ¥n dessa serverdatorer:' suspended_title: Avstängda värddatorer unavailable_content_html: Mastodon lÃ¥ter dig se material frÃ¥n, och interagera med, andra användare i servernätverket. Det är undantag som gjorts pÃ¥ denna serverdator. + user_count_after: + one: användare + other: användare user_count_before: Hem till what_is_mastodon: Vad är Mastodon? accounts: @@ -84,6 +89,7 @@ sv: delete: Ta bort destroyed_msg: Modereringsnotering borttagen utan problem! accounts: + add_email_domain_block: Blockera e-postdomän approve: Godkänn approve_all: Godkänn alla are_you_sure: Är du säker? @@ -164,6 +170,7 @@ sv: staff: Personal user: Användare search: Sök + search_same_email_domain: Andra användare med samma e-postdomän search_same_ip: Annan användare med samma IP-adress shared_inbox_url: Delad inkorg URL show: @@ -185,16 +192,49 @@ sv: web: Webb whitelisted: Vitlistad action_logs: + action_types: + assigned_to_self_report: Tilldela anmälan + change_email_user: Ändra e-post för användare + confirm_user: Bekräfta användare + create_account_warning: Skapa varning + create_announcement: Skapa ett anslag + create_custom_emoji: Skapa egen emoji + create_domain_allow: Skapa tillÃ¥ten domän + create_domain_block: Skapa blockerad domän + destroy_announcement: Ta bort anslag + destroy_custom_emoji: Ta bort egen emoji + destroy_domain_allow: Ta bort tillÃ¥ten domän + destroy_domain_block: Ta bort blockerad domän + destroy_status: Ta bort status + disable_2fa_user: Inaktivera 2FA + disable_custom_emoji: Inaktivera egna emojis + disable_user: Inaktivera användare + enable_custom_emoji: Aktivera egna emojis + enable_user: Aktivera användare + memorialize_account: Minnesmärk konto + promote_user: Befordra användare + remove_avatar_user: Ta bort avatar + reset_password_user: Ã…terställ lösenord + resolve_report: Lös rapport + silence_account: Tysta konto + suspend_account: Stäng av konto + unsuspend_account: Ã…teraktivera konto + update_announcement: Uppdatera meddelande + update_custom_emoji: Uppdatera egna emojis + update_domain_block: Uppdatera blockerad domän + update_status: Uppdatera status actions: assigned_to_self_report: "%{name} tilldelade anmälan %{target} till sig själv" change_email_user: "%{name} bytte e-postadress för användare %{target}" confirm_user: "%{name} bekräftade e-postadress för användare %{target}" create_account_warning: "%{name} sände en varning till %{target}" + create_announcement: "%{name} skapade nytt meddelande %{target}" create_custom_emoji: "%{name} laddade upp ny emoji %{target}" create_domain_allow: "%{name} vitlistade domän %{target}" create_domain_block: "%{name} blockerade domän %{target}" create_email_domain_block: "%{name} svartlistade e-postdomän %{target}" demote_user: "%{name} degraderade användare %{target}" + destroy_announcement: "%{name} raderade meddelanden %{target}" destroy_custom_emoji: "%{name} förstörde emoji %{target}" destroy_domain_allow: "%{name} raderade domän %{target} frÃ¥n vitlistan" destroy_domain_block: "%{name} avblockerade domän %{target}" @@ -217,8 +257,10 @@ sv: unsilence_account: "%{name} Ã¥terljudade %{target}s konto" unsuspend_account: "%{name} aktiverade %{target}s konto" update_custom_emoji: "%{name} uppdaterade emoji %{target}" + update_domain_block: "%{name} uppdaterade blockerad domän för %{target}" update_status: "%{name} uppdaterade status för %{target}" deleted_status: "(raderad status)" + empty: Inga loggar hittades. title: Revisionslogg announcements: scheduled_for: Schemalagd för %{time} @@ -304,12 +346,15 @@ sv: silence: Tysta ner suspend: Suspendera title: Nytt domänblock + obfuscate: Dölj domännamn + obfuscate_hint: Dölj domännamnet i listan till viss del, om underrättelser för listan över domänbegränsningar aktiverats private_comment: Privat kommentar private_comment_hint: Kommentar för moderatorer om denna domänbegränsning. public_comment: Offentlig kommentar reject_media: Avvisa mediafiler reject_media_hint: Raderar lokalt lagrade mediefiler och förhindrar möjligheten att ladda ner nÃ¥got i framtiden. Irrelevant för suspensioner severity: + silence: tystad suspend: avstängd show: affected_accounts: @@ -328,28 +373,40 @@ sv: destroyed_msg: E-postdomän har tagits bort frÃ¥n domänblockslistan utan problem domain: Domän empty: För tillfället inga svartlistade mejl. + from_html: frÃ¥n %{domain} new: create: Skapa domän title: Ny E-postdomänblocklistningsinmatning title: E-postdomänblock instances: by_domain: Domän + empty: Inga domäner hittades. moderation: all: Alla limited: Begränsad + title: Moderering private_comment: Privat kommentar + public_comment: Offentlig kommentar title: Kända instanser + total_blocked_by_us: Blockerad av oss + total_followed_by_them: Följs av dem + total_followed_by_us: Följs av oss invites: + deactivate_all: Inaktivera alla filter: all: Alla available: Tillgängliga expired: UtgÃ¥ngna title: Filtrera title: Inbjudningar + pending_accounts: + title: Väntande konton (%{count}) relays: delete: Radera disable: Inaktivera + disabled: Inaktiverad enable: Aktivera + enable_hint: När den är aktiverad kommer din server att prenumerera pÃ¥ alla publika toots frÃ¥n detta relay, och kommer att börja skicka serverns publika toots till den. enabled: Aktivera save_and_enable: Spara och aktivera status: Status @@ -361,9 +418,12 @@ sv: are_you_sure: Är du säker? assign_to_self: Tilldela till mig assigned: Tilldelad moderator + by_target_domain: Domän för rapporterat konto comment: none: Ingen created_at: Anmäld + forwarded: Vidarebefordrad + forwarded_to: Vidarebefordrad till %{domain} mark_as_resolved: Markera som löst mark_as_unresolved: Markera som olöst notes: @@ -394,10 +454,25 @@ sv: email: Företag E-post username: Användarnamn för kontakt custom_css: + desc_html: Ändra utseendet genom CSS laddat pÃ¥ varje sida title: Anpassad CSS + default_noindex: + desc_html: PÃ¥verkar alla användare som inte har ändrat denna inställning själva + title: Undantag användare frÃ¥n sökmotorindexering som standard + domain_blocks: + all: Till alla + disabled: För ingen + title: Visa domän-blockeringar + users: För inloggade lokala användare + domain_blocks_rationale: + title: Visa motiv + enable_bootstrap_timeline_accounts: + title: Aktivera standard följer för nya användare hero: desc_html: Visas pÃ¥ framsidan. Minst 600x100px rekommenderas. Om inte angiven faller den tillbaka pÃ¥ instansens miniatyrbild title: Hjältebild + mascot: + title: Maskot bild peers_api_enabled: desc_html: Domännamn denna instans har pÃ¥träffat i fediverse title: Publicera lista över upptäckta instanser @@ -411,6 +486,9 @@ sv: min_invite_role: disabled: Ingen title: TillÃ¥t inbjudningar av + require_invite_text: + desc_html: När nyregistrering kräver manuellt godkännande, gör det obligatoriskt att fylla i text i fältet "Varför vill du gÃ¥ med?" + title: Kräv att nya användare fyller i en inbjudningsförfrÃ¥gan show_known_fediverse_at_about_page: desc_html: När den växlas, kommer toots frÃ¥n hela fediverse visas pÃ¥ förhandsvisning. Annars visas bara lokala toots. title: Visa det kända fediverse pÃ¥ tidslinjens förhandsgranskning @@ -508,6 +586,8 @@ sv: email_settings_hint_html: Bekräftelsemeddelandet skickades till %{email}. Om den e-postadressen inte stämmer sÃ¥ kan du ändra den i kontoinställningarna. status: account_status: Kontostatus + redirecting_to: Ditt konto är inaktivt eftersom det för närvarande dirigeras om till %{acct}. + too_fast: Formuläret har skickats för snabbt, försök igen. authorize_follow: already_following: Du följer redan detta konto already_requested: Du har redan skickat en vänförfrÃ¥gan till det kontot @@ -545,6 +625,8 @@ sv: confirm_password: Ange ditt lösenord för att verifiera din identitet proceed: Ta bort konto success_msg: Ditt konto har raderats + warning: + irreversible: Du kan inte Ã¥terställa eller Ã¥teraktivera ditt konto domain_validator: invalid_domain: är inte ett giltigt domännamn errors: @@ -571,6 +653,7 @@ sv: request: EfterfrÃ¥ga ditt arkiv size: Storlek blocks: Du blockerar + bookmarks: Bokmärken csv: CSV lists: Listor mutes: Du tystar @@ -599,11 +682,17 @@ sv: validation_errors: one: NÃ¥got är inte riktigt rätt ännu! Kontrollera felet nedan other: NÃ¥got är inte riktigt rätt ännu! Kontrollera dom %{count} felen nedan + identity_proofs: + active: Aktiv + inactive: Inaktiv imports: + errors: + over_rows_processing_limit: innehÃ¥ller fler än %{count} rader preface: Du kan importera data som du exporterat frÃ¥n en annan instans, till exempel en lista över personer du följer eller blockerar. success: Dina uppgifter har laddats upp och kommer nu att behandlas snarast types: blocking: Lista av blockerade + bookmarks: Bokmärken following: Lista av följare muting: Lista av nertystade upload: Ladda upp @@ -639,6 +728,7 @@ sv: too_many: Det gÃ¥r inte att bifoga mer än 4 filer migrations: acct: användarnamn@domän av det nya kontot + cancel_explanation: Avstängning av omdirigeringen kommer att Ã¥teraktivera ditt nuvarande konto, men kommer inte att Ã¥terskapa följare som har flyttats till det kontot. incoming_migrations: Flyttar frÃ¥n ett annat konto redirected_msg: Ditt konto dirigeras om till %{acct}. moderation: @@ -691,14 +781,17 @@ sv: other: Annat relationships: activity: Kontoaktivitet + follow_selected_followers: Följ valda personer followers: Följare following: Följer + last_active: Senast aktiv status: Kontostatus remote_follow: acct: Ange ditt användarnamn@domän du vill följa frÃ¥n missing_resource: Det gick inte att hitta den begärda omdirigeringsadressen för ditt konto proceed: Fortsätt för att följa prompt: 'Du kommer att följa:' + reason_html: "<strong>Varför är det här steget nödvändigt?</strong> <code>%{instance}</code> är kanske inte den server du är registrerad vid, sÃ¥ vi behöver dirigera dig till din hemserver först." sessions: activity: Senaste aktivitet browser: Webbläsare @@ -873,21 +966,14 @@ sv: default: Mastodon mastodon-light: Mastodon (ljust) two_factor_authentication: - code_hint: Ange koden som genererats av din autentiseringsapp för att bekräfta - description_html: Om du aktiverar <strong>tvÃ¥faktorsautentisering</strong> kommer inloggningen kräva att du har din telefon tillgänglig, vilket kommer att generera tokens för dig att ange. disable: Inaktivera - enable: Aktivera enabled: TvÃ¥faktorsautentisering är aktiverad enabled_success: TvÃ¥faktorsautentisering aktiverad generate_recovery_codes: Generera Ã¥terställningskoder - instructions_html: "<strong>Skanna den här QR-koden i Google Authenticator eller en liknande TOTP-app pÃ¥ din telefon </strong>. FrÃ¥n och med nu genererar den appen tokens som du mÃ¥ste ange när du loggar in." lost_recovery_codes: Ã…terställningskoder tillÃ¥ter dig att fÃ¥ tillgÃ¥ng till ditt konto om du förlorar din telefon. Om du har förlorat dina Ã¥terställningskoder kan du regenerera dem här. Dina gamla Ã¥terställningskoder kommer att ogiltigförklaras. - manual_instructions: 'Om du inte kan skanna QR-koden och behöver skriva in den manuellt, här är den hemliga nyckeln i ren text:' recovery_codes: Backup Ã¥terställningskod recovery_codes_regenerated: Ã…terställningskoder genererades pÃ¥ nytt recovery_instructions_html: Om du nÃ¥gonsin tappar Ã¥tkomst till din telefon kan du använda nÃ¥gon av Ã¥terställningskoderna nedan för att Ã¥terställa Ã¥tkomst till ditt konto. <strong> HÃ¥ll Ã¥terställningskoderna säkra </strong>. Du kan till exempel skriva ut dem och lagra dem med andra viktiga dokument. - setup: Ställ in - wrong_code: Den angivna koden var ogiltig! Är servertid och enhetstid korrekt? user_mailer: backup_ready: explanation: Du begärde en fullständig säkerhetskopiering av ditt Mastodon-konto. Det är nu klart för nedladdning! @@ -910,7 +996,9 @@ sv: tip_mobile_webapp: Om din mobila webbläsare erbjuder dig att lägga till Mastodon pÃ¥ din hemskärm kan du fÃ¥ push-aviseringar. Det fungerar som en inbyggd app pÃ¥ mÃ¥nga sätt! title: Välkommen ombord, %{name}! users: + blocked_email_provider: Denna e-postleverantör är inte tillÃ¥ten invalid_email: E-postadressen är ogiltig + invalid_email_mx: E-postadressen verkar inte finnas invalid_otp_token: Ogiltig tvÃ¥faktorskod otp_lost_help_html: Om du förlorat Ã¥tkomst till bÃ¥da kan du komma i kontakt med %{email} seamless_external_login: Du är inloggad via en extern tjänst, sÃ¥ lösenord och e-postinställningar är inte tillgängliga. diff --git a/config/locales/szl.yml b/config/locales/szl.yml index 54a411c08de256ba55e5ad2e7a1b139679000ae2..4359f4d610ecfdf2d06ad55c3c3ac15c726ff077 100644 --- a/config/locales/szl.yml +++ b/config/locales/szl.yml @@ -10,11 +10,3 @@ szl: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/ta.yml b/config/locales/ta.yml index fa4c1a87b6b99007d992890c0f251039ea1c5a40..18a2077150ce8d59762a0d0c1a906b16123b403f 100644 --- a/config/locales/ta.yml +++ b/config/locales/ta.yml @@ -34,6 +34,9 @@ ta: unavailable_content_description: domain: வழஙà¯à®•ி reason: காரணம௠+ rejecting_media_title: வடிகடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ மீடியா + silenced_title: அணைகà¯à®•படà¯à®Ÿ சரà¯à®µà®°à¯à®•ள௠+ suspended_title: இடைநீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ சரà¯à®µà®°à¯à®•ள௠user_count_after: one: பயனர௠other: பயனரà¯à®•ள௠@@ -222,6 +225,7 @@ ta: unpublished_msg: அறிவிபà¯à®ªà¯ வெறà¯à®±à®¿à®•ரமாகத௠திரà¯à®®à¯à®ªà®ªà¯ பெறபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯! updated_msg: அறிவிபà¯à®ªà¯ வெறà¯à®±à®¿à®•ரமாகத௠திரà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯! custom_emojis: + not_permitted: இசà¯à®šà¯†à®¯à®²à¯ˆà®šà¯ செயà¯à®¯ உஙà¯à®•ளà¯à®•à¯à®•௠அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ uncategorized: வகைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤à®µà¯ˆ unlist: படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ அகறà¯à®±à¯à®• unlisted: படà¯à®Ÿà®¿à®¯à®²à®¿à®Ÿà®ªà¯à®ªà®Ÿà®¾à®¤ @@ -264,12 +268,18 @@ ta: site_uploads: delete: பதிவேறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®ªà¯ படம௠அழிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ destroyed_msg: பதிவேறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿ வலைதளம௠வெறà¯à®±à®¿à®•à¯à®•ரமாக அழிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯! + aliases: + empty: உஙà¯à®•ளà¯à®•à¯à®•௠மாறà¯à®±à¯à®ªà¯à®ªà¯†à®¯à®°à¯à®•ள௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ. appearance: localization: body: மாஸà¯à®Ÿà¯‹à®Ÿà®¾à®©à¯ தனà¯à®©à®¾à®°à¯à®µà®²à®°à¯à®•ளால௠மொழிபெயரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®•ிறதà¯. guide_link_text: அனைவரà¯à®®à¯ பஙà¯à®•ளிகà¯à®•லாமà¯. authorize_follow: already_requested: இகà¯à®•ணகà¯à®•ைப௠பினà¯à®¤à¯Šà®Ÿà®°à¯à®®à¯ கோரிகà¯à®•ையை நீஙà¯à®•ள௠à®à®±à¯à®•னவே அனà¯à®ªà¯à®ªà®¿à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•ள௠+ crypto: + errors: + invalid_key: ஒர௠மà¯à®±à¯ˆà®¯à®¾à®© Ed25519 அலà¯à®²à®¤à¯ Curve25519 key அலà¯à®² + invalid_signature: ஒர௠மà¯à®±à¯ˆà®¯à®¾à®© Ed25519 அடையாளம௠அலà¯à®² date: formats: default: "%b %d, %Y" @@ -288,17 +298,18 @@ ta: empty: தடà¯à®ªà¯à®ªà¯à®•ள௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ. generic: delete: நீகà¯à®•௠- invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day + identity_proofs: + remove: ஆதாரதà¯à®¤à¯ˆà®•௠கணகà¯à®•ிலிரà¯à®¨à¯à®¤à¯ நீகà¯à®•௠+ removed: ஆதாரம௠கணகà¯à®•ிலிரà¯à®¨à¯à®¤à¯ வெறà¯à®±à®¿à®•ரமாக நீகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ media_attachments: validations: not_ready: பதிவேறà¯à®±à®®à¯ à®®à¯à®Ÿà®¿à®µà®Ÿà¯ˆà®¯à®¾à®¤ கோபà¯à®ªà¯à®•ளை இணைகà¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. சிறித௠நேரம௠கழிதà¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿ செயà¯à®¯à®µà¯à®®à¯! + migrations: + redirected_msg: உஙà¯à®•ள௠கணகà¯à®•௠இபà¯à®ªà¯Šà®´à¯à®¤à¯ %{acct}-இறà¯à®•à¯à®¤à¯ திரà¯à®ªà¯à®ªà®¿à®µà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®•ிறதà¯. + move_handler: + carry_blocks_over_text: இபà¯à®ªà®¯à®©à®°à¯ %{acct}-இலிரà¯à®¨à¯à®¤à¯ நகரà¯à®¨à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¾à®°à¯, அகà¯à®•ணகà¯à®•ை நீஙà¯à®•ள௠தடà¯à®¤à¯à®¤à®¿à®°à¯à®¨à¯à®¤à¯€à®°à¯à®•ளà¯. + carry_mutes_over_text: இபà¯à®ªà®¯à®©à®°à¯ %{acct}-இலிரà¯à®¨à¯à®¤à¯ நகரà¯à®¨à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¾à®°à¯, அகà¯à®•ணகà¯à®•ை நீஙà¯à®•ள௠மà¯à®Ÿà®•à¯à®•ியிரà¯à®¨à¯à®¤à¯€à®°à¯à®•ளà¯. + copy_account_note_text: 'இபà¯à®ªà®¯à®©à®°à¯ %{acct}-லிரà¯à®¨à¯à®¤à¯ நகரà¯à®¨à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¾à®°à¯, இவரைப௠பறà¯à®±à®¿à®¯ உஙà¯à®•ள௠மà¯à®¨à¯à®¤à¯ˆà®¯ கà¯à®±à®¿à®ªà¯à®ªà¯à®•ள௠இஙà¯à®•ே:' notifications: email_events: மினà¯à®©à®žà¯à®šà®²à¯ அறிவிபà¯à®ªà¯à®•ளà¯à®•à¯à®•ான நிகழà¯à®µà¯à®•ள௠email_events_hint: 'எநà¯à®¤ நிகழà¯à®µà¯à®•ளà¯à®•à¯à®•௠அறிவிபà¯à®ªà¯à®•ளைப௠பெற வேணà¯à®Ÿà¯à®®à¯ எனà¯à®±à¯ தேரà¯à®µà¯ செயà¯à®•:' @@ -311,6 +322,21 @@ ta: limit_reached: எதிரà¯à®µà®¿à®©à¯ˆà®•ளà¯à®•à¯à®•ான உசà¯à®šà®µà®°à®®à¯à®ªà¯ எடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ unrecognized_emoji: à®…à®™à¯à®•ீகரிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ ஈமோஜி அலà¯à®² statuses: + attached: + audio: + one: "%{count} ஒலி" + other: "%{count} ஒலிகளà¯" errors: in_reply_not_found: நீஙà¯à®•ள௠மறà¯à®®à¯Šà®´à®¿ அளிகà¯à®• à®®à¯à®¯à®²à¯à®®à¯ பதிவ௠இரà¯à®ªà¯à®ªà®¤à¯à®ªà¯‹à®²à¯ தெரியவிலà¯à®²à¯ˆ. show_thread: தொடரைக௠காடà¯à®Ÿà¯ + user_mailer: + sign_in_token: + details: 'à®…à®®à¯à®®à¯à®¯à®±à¯à®šà®¿ பறà¯à®±à®¿à®¯ விவரஙà¯à®•ள௠இஙà¯à®•ே:' + explanation: 'à®…à®™à¯à®•ீகரிகà¯à®•பà¯à®ªà®Ÿà®¾à®¤ ஓர௠IP à®®à¯à®•வரியிலிரà¯à®¨à¯à®¤à¯ உஙà¯à®•ள௠கணகà¯à®•ிறà¯à®•à¯à®³à¯ நà¯à®´à¯ˆà®¯à¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿ நடநà¯à®¤à¯à®³à¯à®³à®¤à¯. இத௠நீஙà¯à®•ளà¯à®¤à®¾à®©à¯ எனà¯à®±à®¾à®²à¯, தயவà¯à®šà¯†à®¯à¯à®¤à¯ பாதà¯à®•ாபà¯à®ªà¯ கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆà®•௠கீழே உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯:' + further_actions: 'இத௠நீஙà¯à®•ள௠இலà¯à®²à¯ˆ எனà¯à®±à®¾à®²à¯, தயவà¯à®šà¯†à®¯à¯à®¤à¯ உஙà¯à®•ள௠கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à®µà¯à®®à¯. மேலà¯à®®à¯, உஙà¯à®•ள௠கணகà¯à®•ிறà¯à®•௠இரணà¯à®Ÿà¯ கடà¯à®Ÿ à®…à®™à¯à®•ீகாரதà¯à®¤à¯ˆ (two-factor authentication) செயலாகà¯à®•வà¯à®®à¯. அதை இஙà¯à®•௠செயà¯à®¯ இயலà¯à®®à¯:' + subject: உளà¯à®¨à¯à®´à¯ˆà®¯ à®®à¯à®¯à®±à¯à®šà®¿à®¤à¯à®¤à®¤à¯ˆ தயவà¯à®šà¯†à®¯à¯à®¤à¯ உறà¯à®¤à®¿à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯ + title: உளà¯à®¨à¯à®´à¯ˆà®¯ à®®à¯à®¯à®±à¯à®šà®¿ + users: + generic_access_help_html: உஙà¯à®•ள௠கணகà¯à®•ை அணà¯à®•à¯à®µà®¤à®¿à®²à¯ சிகà¯à®•லா? உதவிகà¯à®•௠%{email} -உடன௠தொடரà¯à®ªà¯ கொளà¯à®³à®µà¯à®®à¯ + invalid_sign_in_token: தவறான பாதà¯à®•ாபà¯à®ªà¯à®•௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯ + suspicious_sign_in_confirmation: இதறà¯à®•௠மà¯à®©à¯à®ªà¯ இநà¯à®¤ சாதனதà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ நீஙà¯à®•ள௠உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤à®¤à¯à®ªà¯‹à®²à¯ தெரியவிலà¯à®²à¯ˆ. மேலà¯à®®à¯, நீஙà¯à®•ள௠உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤à¯‡ சில காலம௠ஆகிறதà¯. எனவே, இத௠நீஙà¯à®•ளà¯à®¤à®¾à®©à®¾ எனà¯à®ªà®¤à¯ˆ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤ உஙà¯à®•ள௠மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•வரிகà¯à®•௠ஒர௠பாதà¯à®•ாபà¯à®ªà¯à®•௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆ அனà¯à®ªà¯à®ªà¯à®•ிறோமà¯. diff --git a/config/locales/tai.yml b/config/locales/tai.yml index 27e4a8b7837e3101c31790f3460ce65971c0860d..3b22e9999b5641a9985826558ef3f9784a35b169 100644 --- a/config/locales/tai.yml +++ b/config/locales/tai.yml @@ -10,11 +10,3 @@ tai: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/te.yml b/config/locales/te.yml index 79415b1d16eb7c9776c0619eaebc678310ca87cf..0028ac3253c25ac88d6f580cc5d4bf0cc0ce9123 100644 --- a/config/locales/te.yml +++ b/config/locales/te.yml @@ -116,11 +116,3 @@ te: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/th.yml b/config/locales/th.yml index f5bab5d3040bdf8d059f46c34430768f3979a253..63ce98d4ba23428735550f25cb0f11b43e8c261c 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -35,9 +35,11 @@ th: unavailable_content_description: domain: เซิร์ฟเวà¸à¸£à¹Œ reason: เหตุผล - rejecting_media: 'ไฟล์สื่à¸à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸ˆà¸°à¹„ม่ได้รับà¸à¸²à¸£à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¸«à¸£à¸·à¸à¸ˆà¸±à¸”เà¸à¹‡à¸š à¹à¸¥à¸°à¸ˆà¸°à¹„ม่à¹à¸ªà¸”งภาพขนาดย่ภต้à¸à¸‡à¸¡à¸µà¸à¸²à¸£à¸„ลิà¸à¹„ปยังไฟล์ต้นฉบับด้วยตนเà¸à¸‡:' + rejecting_media: 'จะไม่ประมวลผลหรืà¸à¸ˆà¸±à¸”เà¸à¹‡à¸šà¹„ฟล์สื่à¸à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰ à¹à¸¥à¸°à¸ˆà¸°à¹„ม่à¹à¸ªà¸”งภาพขนาดย่ภต้à¸à¸‡à¸¡à¸µà¸à¸²à¸£à¸„ลิà¸à¹„ปยังไฟล์ต้นฉบับด้วยตนเà¸à¸‡:' rejecting_media_title: สื่à¸à¸—ี่à¸à¸£à¸à¸‡à¸à¸¢à¸¹à¹ˆ + silenced: 'จะซ่à¸à¸™à¹‚พสต์จาà¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¹ƒà¸™à¹€à¸ªà¹‰à¸™à¹€à¸§à¸¥à¸²à¸ªà¸²à¸˜à¸²à¸£à¸“ะà¹à¸¥à¸°à¸à¸²à¸£à¸ªà¸™à¸—นา à¹à¸¥à¸°à¸ˆà¸°à¹„ม่สร้างà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸ˆà¸²à¸à¸à¸²à¸£à¹‚ต้ตà¸à¸šà¸‚à¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ เว้นà¹à¸•่คุณà¸à¸³à¸¥à¸±à¸‡à¸•ิดตามผู้ใช้:' silenced_title: เซิร์ฟเวà¸à¸£à¹Œà¸—ี่เงียบà¸à¸¢à¸¹à¹ˆ + suspended: 'จะไม่ประมวลผล จัดเà¸à¹‡à¸š หรืà¸à¹à¸¥à¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰ ทำให้à¸à¸²à¸£à¹‚ต้ตà¸à¸šà¸«à¸£à¸·à¸à¸à¸²à¸£à¸ªà¸·à¹ˆà¸à¸ªà¸²à¸£à¹ƒà¸” ๆ à¸à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸ˆà¸²à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¹€à¸›à¹‡à¸™à¹„ปไม่ได้:' suspended_title: เซิร์ฟเวà¸à¸£à¹Œà¸—ี่ระงับà¸à¸¢à¸¹à¹ˆ user_count_after: other: ผู้ใช้ @@ -74,13 +76,14 @@ th: admin: account_actions: action: ทำà¸à¸²à¸£à¸à¸£à¸°à¸—ำ + title: ทำà¸à¸²à¸£à¸à¸£à¸°à¸—ำà¸à¸²à¸£à¸„วบคุม %{acct} account_moderation_notes: create: เขียนหมายเหตุ created_msg: สร้างหมายเหตุà¸à¸²à¸£à¸„วบคุมสำเร็จ! delete: ลบ destroyed_msg: ทำลายหมายเหตุà¸à¸²à¸£à¸„วบคุมสำเร็จ! accounts: - add_email_domain_block: ขึ้นบัà¸à¸Šà¸µà¸”ำโดเมนà¸à¸µà¹€à¸¡à¸¥ + add_email_domain_block: ปิดà¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥ approve: à¸à¸™à¸¸à¸¡à¸±à¸•ิ approve_all: à¸à¸™à¸¸à¸¡à¸±à¸•ิทั้งหมด are_you_sure: คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸à¹„ม่? @@ -96,22 +99,24 @@ th: confirm: ยืนยัน confirmed: ยืนยันà¹à¸¥à¹‰à¸§ confirming: à¸à¸³à¸¥à¸±à¸‡à¸¢à¸·à¸™à¸¢à¸±à¸™ + delete: ลบข้à¸à¸¡à¸¹à¸¥ deleted: ลบà¹à¸¥à¹‰à¸§ demote: ลดขั้น - disable: ปิดใช้งาน + disable: à¸à¸²à¸¢à¸±à¸” disable_two_factor_authentication: ปิดใช้งาน 2FA - disabled: ปิดใช้งานà¸à¸¢à¸¹à¹ˆ + disabled: à¸à¸²à¸¢à¸±à¸”à¸à¸¢à¸¹à¹ˆ display_name: ชื่à¸à¸—ี่à¹à¸ªà¸”ง domain: โดเมน edit: à¹à¸à¹‰à¹„ข email: à¸à¸µà¹€à¸¡à¸¥ email_status: สถานะà¸à¸µà¹€à¸¡à¸¥ - enable: เปิดใช้งาน + enable: เลิà¸à¸à¸²à¸¢à¸±à¸” enabled: เปิดใช้งานà¸à¸¢à¸¹à¹ˆ followers: ผู้ติดตาม follows: à¸à¸²à¸£à¸•ิดตาม header: ส่วนหัว inbox_url: URL à¸à¸¥à¹ˆà¸à¸‡à¸‚าเข้า + invite_request_text: เหตุผลสำหรับà¸à¸²à¸£à¹€à¸‚้าร่วม invited_by: เชิà¸à¹‚ดย ip: IP joined: เข้าร่วมเมื่ภ@@ -123,6 +128,7 @@ th: login_status: สถานะà¸à¸²à¸£à¹€à¸‚้าสู่ระบบ media_attachments: ไฟล์à¹à¸™à¸šà¸ªà¸·à¹ˆà¸ memorialize: เปลี่ยนเป็นà¸à¸™à¸¸à¸ªà¸£à¸“์ + memorialized_msg: เปลี่ยน %{username} เป็นบัà¸à¸Šà¸µà¸à¸™à¸¸à¸ªà¸£à¸“์สำเร็จ moderation: active: ใช้งานà¸à¸¢à¸¹à¹ˆ all: ทั้งหมด @@ -133,6 +139,7 @@ th: moderation_notes: หมายเหตุà¸à¸²à¸£à¸„วบคุม most_recent_activity: à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸¥à¹ˆà¸²à¸ªà¸¸à¸” most_recent_ip: IP ล่าสุด + no_limits_imposed: ไม่มีขีดจำà¸à¸±à¸”ที่à¸à¸³à¸«à¸™à¸” not_subscribed: ไม่ได้บà¸à¸à¸£à¸±à¸š pending: à¸à¸²à¸£à¸•รวจทานที่รà¸à¸”ำเนินà¸à¸²à¸£ perform_full_suspension: ระงับ @@ -145,6 +152,8 @@ th: reject_all: ปà¸à¸´à¹€à¸ªà¸˜à¸—ั้งหมด remove_avatar: เà¸à¸²à¸ าพประจำตัวà¸à¸à¸ remove_header: เà¸à¸²à¸ªà¹ˆà¸§à¸™à¸«à¸±à¸§à¸à¸à¸ + removed_avatar_msg: เà¸à¸²à¸ าพประจำตัวขà¸à¸‡ %{username} à¸à¸à¸à¸ªà¸³à¹€à¸£à¹‡à¸ˆ + removed_header_msg: เà¸à¸²à¸ าพส่วนหัวขà¸à¸‡ %{username} à¸à¸à¸à¸ªà¸³à¹€à¸£à¹‡à¸ˆ resend_confirmation: already_confirmed: ผู้ใช้นี้ได้รับà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ send: ส่งà¸à¸µà¹€à¸¡à¸¥à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¸µà¸à¸„รั้ง @@ -164,8 +173,8 @@ th: show: created_reports: รายงานที่สร้าง targeted_reports: รายงานโดยผู้à¸à¸·à¹ˆà¸™ - silence: ทำให้เงียบ - silenced: เงียบà¸à¸¢à¸¹à¹ˆ + silence: จำà¸à¸±à¸” + silenced: จำà¸à¸±à¸”à¸à¸¢à¸¹à¹ˆ statuses: สถานะ subscribe: บà¸à¸à¸£à¸±à¸š suspended: ระงับà¸à¸¢à¸¹à¹ˆ @@ -175,10 +184,11 @@ th: undo_silenced: เลิà¸à¸—ำà¸à¸²à¸£à¸—ำให้เงียบ undo_suspension: เลิà¸à¸—ำà¸à¸²à¸£à¸£à¸°à¸‡à¸±à¸š unsubscribe: เลิà¸à¸šà¸à¸à¸£à¸±à¸š + unsuspended_msg: เลิà¸à¸£à¸°à¸‡à¸±à¸šà¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡ %{username} สำเร็จ username: ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ warn: เตืà¸à¸™ web: เว็บ - whitelisted: ขึ้นบัà¸à¸Šà¸µà¸‚าวà¹à¸¥à¹‰à¸§ + whitelisted: à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¹à¸¥à¹‰à¸§ action_logs: action_types: assigned_to_self_report: มà¸à¸šà¸«à¸¡à¸²à¸¢à¸£à¸²à¸¢à¸‡à¸²à¸™ @@ -190,12 +200,14 @@ th: create_domain_allow: สร้างà¸à¸²à¸£à¸à¸™à¸¸à¸à¸²à¸•โดเมน create_domain_block: สร้างà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน create_email_domain_block: สร้างà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥ + create_ip_block: สร้างà¸à¸Ž IP demote_user: ลดขั้นผู้ใช้ destroy_announcement: ลบประà¸à¸²à¸¨ destroy_custom_emoji: ลบà¸à¸µà¹‚มจิที่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ destroy_domain_allow: ลบà¸à¸²à¸£à¸à¸™à¸¸à¸à¸²à¸•โดเมน destroy_domain_block: ลบà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน destroy_email_domain_block: ลบà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥ + destroy_ip_block: ลบà¸à¸Ž IP destroy_status: ลบสถานะ disable_2fa_user: ปิดใช้งาน 2FA disable_custom_emoji: ปิดใช้งานà¸à¸µà¹‚มจิที่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ @@ -208,29 +220,35 @@ th: reopen_report: เปิดรายงานใหม่ reset_password_user: ตั้งรหัสผ่านใหม่ resolve_report: à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²à¸£à¸²à¸¢à¸‡à¸²à¸™ + sensitive_account: ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณว่าละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™ silence_account: ทำให้บัà¸à¸Šà¸µà¹€à¸‡à¸µà¸¢à¸š suspend_account: ระงับบัà¸à¸Šà¸µ unassigned_report: เลิà¸à¸¡à¸à¸šà¸«à¸¡à¸²à¸¢à¸£à¸²à¸¢à¸‡à¸²à¸™ + unsensitive_account: เลิà¸à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณว่าละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™ unsilence_account: เลิà¸à¸—ำให้บัà¸à¸Šà¸µà¹€à¸‡à¸µà¸¢à¸š unsuspend_account: เลิà¸à¸£à¸°à¸‡à¸±à¸šà¸šà¸±à¸à¸Šà¸µ update_announcement: à¸à¸±à¸›à¹€à¸”ตประà¸à¸²à¸¨ update_custom_emoji: à¸à¸±à¸›à¹€à¸”ตà¸à¸µà¹‚มจิที่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ + update_domain_block: à¸à¸±à¸›à¹€à¸”ตà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน update_status: à¸à¸±à¸›à¹€à¸”ตสถานะ actions: + assigned_to_self_report: "%{name} ได้มà¸à¸šà¸«à¸¡à¸²à¸¢à¸£à¸²à¸¢à¸‡à¸²à¸™ %{target} ให้à¸à¸±à¸šà¸•นเà¸à¸‡" change_email_user: "%{name} ได้เปลี่ยนที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸‚à¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ %{target}" confirm_user: "%{name} ได้ยืนยันที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸‚à¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ %{target}" create_account_warning: "%{name} ได้ส่งคำเตืà¸à¸™à¹„ปยัง %{target}" create_announcement: "%{name} ได้สร้างประà¸à¸²à¸¨à¹ƒà¸«à¸¡à¹ˆ %{target}" create_custom_emoji: "%{name} ได้à¸à¸±à¸›à¹‚หลดà¸à¸µà¹‚มจิใหม่ %{target}" - create_domain_allow: "%{name} ได้ขึ้นบัà¸à¸Šà¸µà¸‚าวโดเมน %{target}" + create_domain_allow: "%{name} ได้à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมน %{target}" create_domain_block: "%{name} ได้ปิดà¸à¸±à¹‰à¸™à¹‚ดเมน %{target}" - create_email_domain_block: "%{name} ได้ขึ้นบัà¸à¸Šà¸µà¸”ำโดเมนà¸à¸µà¹€à¸¡à¸¥ %{target}" + create_email_domain_block: "%{name} ได้ปิดà¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥ %{target}" + create_ip_block: "%{name} ได้สร้างà¸à¸Žà¸ªà¸³à¸«à¸£à¸±à¸š IP %{target}" demote_user: "%{name} ได้ลดขั้นผู้ใช้ %{target}" destroy_announcement: "%{name} ได้ลบประà¸à¸²à¸¨ %{target}" destroy_custom_emoji: "%{name} ได้ทำลายà¸à¸µà¹‚มจิ %{target}" - destroy_domain_allow: "%{name} ได้เà¸à¸²à¹‚ดเมน %{target} à¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸‚าว" + destroy_domain_allow: "%{name} ได้ไม่à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมน %{target}" destroy_domain_block: "%{name} ได้เลิà¸à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน %{target}" - destroy_email_domain_block: "%{name} ได้ขึ้นบัà¸à¸Šà¸µà¸‚าวโดเมนà¸à¸µà¹€à¸¡à¸¥ %{target}" + destroy_email_domain_block: "%{name} ได้เลิà¸à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥ %{target}" + destroy_ip_block: "%{name} ได้ลบà¸à¸Žà¸ªà¸³à¸«à¸£à¸±à¸š IP %{target}" destroy_status: "%{name} ได้เà¸à¸²à¸ªà¸–านะโดย %{target} à¸à¸à¸" disable_2fa_user: "%{name} ได้ปิดใช้งานความต้à¸à¸‡à¸à¸²à¸£à¸ªà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸ªà¸³à¸«à¸£à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ %{target}" disable_custom_emoji: "%{name} ได้ปิดใช้งานà¸à¸µà¹‚มจิ %{target}" @@ -241,14 +259,18 @@ th: promote_user: "%{name} ได้เลื่à¸à¸™à¸‚ั้นผู้ใช้ %{target}" remove_avatar_user: "%{name} ได้เà¸à¸²à¸ าพประจำตัวขà¸à¸‡ %{target} à¸à¸à¸" reopen_report: "%{name} ได้เปิดรายงาน %{target} ใหม่" + reset_password_user: "%{name} ได้ตั้งรหัสผ่านขà¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ %{target} ใหม่" resolve_report: "%{name} ได้à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²à¸£à¸²à¸¢à¸‡à¸²à¸™ %{target}" + sensitive_account: "%{name} ได้ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸‚à¸à¸‡ %{target} ว่าละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™" silence_account: "%{name} ได้ทำให้บัà¸à¸Šà¸µà¸‚à¸à¸‡ %{target} เงียบ" suspend_account: "%{name} ได้ระงับบัà¸à¸Šà¸µà¸‚à¸à¸‡ %{target}" unassigned_report: "%{name} ได้เลิà¸à¸¡à¸à¸šà¸«à¸¡à¸²à¸¢à¸£à¸²à¸¢à¸‡à¸²à¸™ %{target}" + unsensitive_account: "%{name} ได้เลิà¸à¸—ำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸ªà¸·à¹ˆà¸à¸‚à¸à¸‡ %{target} ว่าละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™" unsilence_account: "%{name} ได้เลิà¸à¸—ำให้บัà¸à¸Šà¸µà¸‚à¸à¸‡ %{target} เงียบ" unsuspend_account: "%{name} ได้เลิà¸à¸£à¸°à¸‡à¸±à¸šà¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡ %{target}" update_announcement: "%{name} ได้à¸à¸±à¸›à¹€à¸”ตประà¸à¸²à¸¨ %{target}" update_custom_emoji: "%{name} ได้à¸à¸±à¸›à¹€à¸”ตà¸à¸µà¹‚มจิ %{target}" + update_domain_block: "%{name} ได้à¸à¸±à¸›à¹€à¸”ตà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนสำหรับ %{target}" update_status: "%{name} ได้à¸à¸±à¸›à¹€à¸”ตสถานะโดย %{target}" deleted_status: "(สถานะที่ลบà¹à¸¥à¹‰à¸§)" empty: ไม่พบรายà¸à¸²à¸£à¸šà¸±à¸™à¸—ึภ@@ -273,7 +295,9 @@ th: custom_emojis: assign_category: à¸à¸³à¸«à¸™à¸”หมวดหมู่ by_domain: โดเมน + copied_msg: สร้างสำเนาขà¸à¸‡à¸à¸µà¹‚มจิในเซิร์ฟเวà¸à¸£à¹Œà¸ªà¸³à¹€à¸£à¹‡à¸ˆ copy: คัดลà¸à¸ + copy_failed_msg: ไม่สามารถสร้างสำเนาขà¸à¸‡à¸à¸µà¹‚มจินั้นในเซิร์ฟเวà¸à¸£à¹Œ create_new_category: สร้างหมวดหมู่ใหม่ created_msg: สร้างà¸à¸µà¹‚มจิสำเร็จ! delete: ลบ @@ -327,12 +351,12 @@ th: week_interactions: à¸à¸²à¸£à¹‚ต้ตà¸à¸šà¹ƒà¸™à¸ªà¸±à¸›à¸”าห์นี้ week_users_active: ใช้งานà¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸ªà¸±à¸›à¸”าห์นี้ week_users_new: ผู้ใช้ในสัปดาห์นี้ - whitelist_mode: โหมดบัà¸à¸Šà¸µà¸‚าว + whitelist_mode: โหมดà¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¹à¸šà¸šà¸ˆà¸³à¸à¸±à¸” domain_allows: - add_new: ขึ้นบัà¸à¸Šà¸µà¸‚าวโดเมน - created_msg: ขึ้นบัà¸à¸Šà¸µà¸‚าวโดเมนสำเร็จ - destroyed_msg: เà¸à¸²à¹‚ดเมนà¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸‚าวà¹à¸¥à¹‰à¸§ - undo: เà¸à¸²à¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸‚าว + add_new: à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมน + created_msg: à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมนสำเร็จ + destroyed_msg: ไม่à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมนà¹à¸¥à¹‰à¸§ + undo: ไม่à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸à¸à¸±à¸šà¹‚ดเมน domain_blocks: add_new: เพิ่มà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนใหม่ created_msg: à¸à¸³à¸¥à¸±à¸‡à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน @@ -353,6 +377,8 @@ th: reject_media: ปà¸à¸´à¹€à¸ªà¸˜à¹„ฟล์สื่ภreject_media_hint: เà¸à¸²à¹„ฟล์สื่à¸à¸—ี่จัดเà¸à¹‡à¸šà¹„ว้ในเซิร์ฟเวà¸à¸£à¹Œà¸à¸à¸à¹à¸¥à¸°à¸›à¸à¸´à¹€à¸ªà¸˜à¸—ี่จะดาวน์โหลดไฟล์ใด ๆ ในà¸à¸™à¸²à¸„ต ไม่เà¸à¸µà¹ˆà¸¢à¸§à¸‚้à¸à¸‡à¸à¸±à¸šà¸à¸²à¸£à¸£à¸°à¸‡à¸±à¸š reject_reports: ปà¸à¸´à¹€à¸ªà¸˜à¸£à¸²à¸¢à¸‡à¸²à¸™ + rejecting_media: à¸à¸³à¸¥à¸±à¸‡à¸›à¸à¸´à¹€à¸ªà¸˜à¹„ฟล์สื่ภ+ rejecting_reports: à¸à¸³à¸¥à¸±à¸‡à¸›à¸à¸´à¹€à¸ªà¸˜à¸£à¸²à¸¢à¸‡à¸²à¸™ severity: silence: เงียบà¸à¸¢à¸¹à¹ˆ suspend: ระงับà¸à¸¢à¸¹à¹ˆ @@ -368,18 +394,19 @@ th: view: ดูà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน email_domain_blocks: add_new: เพิ่มใหม่ - created_msg: เพิ่มโดเมนà¸à¸µà¹€à¸¡à¸¥à¹€à¸›à¹‡à¸™à¸šà¸±à¸à¸Šà¸µà¸”ำสำเร็จ + created_msg: ปิดà¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥à¸ªà¸³à¹€à¸£à¹‡à¸ˆ delete: ลบ - destroyed_msg: ลบโดเมนà¸à¸µà¹€à¸¡à¸¥à¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸”ำสำเร็จ + destroyed_msg: เลิà¸à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥à¸ªà¸³à¹€à¸£à¹‡à¸ˆ domain: โดเมน - empty: ไม่มีโดเมนà¸à¸µà¹€à¸¡à¸¥à¸—ี่ขึ้นบัà¸à¸Šà¸µà¸”ำà¸à¸¢à¸¹à¹ˆ + empty: ไม่มีโดเมนà¸à¸µà¹€à¸¡à¸¥à¸—ี่ปิดà¸à¸±à¹‰à¸™à¸à¸¢à¸¹à¹ˆ from_html: จาภ%{domain} new: create: เพิ่มโดเมน - title: รายà¸à¸²à¸£à¸šà¸±à¸à¸Šà¸µà¸”ำà¸à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¸¡à¹ˆ - title: บัà¸à¸Šà¸µà¸”ำà¸à¸µà¹€à¸¡à¸¥ + title: ปิดà¸à¸±à¹‰à¸™à¹‚ดเมนà¸à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¸¡à¹ˆ + title: โดเมนà¸à¸µà¹€à¸¡à¸¥à¸—ี่ปิดà¸à¸±à¹‰à¸™à¸à¸¢à¸¹à¹ˆ instances: by_domain: โดเมน + empty: ไม่พบโดเมน known_accounts: other: "%{count} บัà¸à¸Šà¸µà¸—ี่รู้จัà¸" moderation: @@ -389,6 +416,10 @@ th: private_comment: ความคิดเห็นส่วนตัว public_comment: ความคิดเห็นสาธารณะ title: à¸à¸²à¸£à¸•ิดต่à¸à¸à¸±à¸šà¸ ายนà¸à¸ + total_blocked_by_us: ปิดà¸à¸±à¹‰à¸™à¹‚ดยเรา + total_followed_by_them: ติดตามโดยเขา + total_followed_by_us: ติดตามโดยเรา + total_reported: รายงานเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¹€à¸‚า total_storage: ไฟล์à¹à¸™à¸šà¸ªà¸·à¹ˆà¸ invites: deactivate_all: ปิดใช้งานทั้งหมด @@ -398,6 +429,20 @@ th: expired: หมดà¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ title: ตัวà¸à¸£à¸à¸‡ title: คำเชิภ+ ip_blocks: + add_new: สร้างà¸à¸Ž + created_msg: เพิ่มà¸à¸Ž IP ใหม่สำเร็จ + delete: ลบ + expires_in: + '1209600': 2 สัปดาห์ + '15778476': 6 เดืà¸à¸™ + '2629746': 1 เดืà¸à¸™ + '31556952': 1 ปี + '86400': 1 วัน + '94670856': 3 ปี + new: + title: สร้างà¸à¸Ž IP ใหม่ + title: à¸à¸Ž IP pending_accounts: title: บัà¸à¸Šà¸µà¸—ี่รà¸à¸”ำเนินà¸à¸²à¸£ (%{count}) relationships: @@ -430,6 +475,8 @@ th: comment: none: ไม่มี created_at: รายงานเมื่ภ+ forwarded: ส่งต่à¸à¹à¸¥à¹‰à¸§ + forwarded_to: ส่งต่à¸à¹„ปยัง %{domain} à¹à¸¥à¹‰à¸§ mark_as_resolved: ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸§à¹ˆà¸²à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²à¹à¸¥à¹‰à¸§ mark_as_unresolved: ทำเครื่à¸à¸‡à¸«à¸¡à¸²à¸¢à¸§à¹ˆà¸²à¸¢à¸±à¸‡à¹„ม่ได้à¹à¸à¹‰à¸›à¸±à¸à¸«à¸² notes: @@ -455,7 +502,10 @@ th: email: à¸à¸µà¹€à¸¡à¸¥à¸˜à¸¸à¸£à¸à¸´à¸ˆ username: ชื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¹ƒà¸™à¸à¸²à¸£à¸•ิดต่ภcustom_css: + desc_html: ปรับเปลี่ยนรูปลัà¸à¸©à¸“์ด้วย CSS ที่โหลดในทุà¸à¸«à¸™à¹‰à¸² title: CSS ที่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ + default_noindex: + desc_html: มีผลต่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸—ั้งหมดที่ไม่ได้เปลี่ยนà¸à¸²à¸£à¸•ั้งค่านี้ด้วยตนเà¸à¸‡ domain_blocks: all: ให้à¸à¸±à¸šà¸—ุà¸à¸„น disabled: ให้à¸à¸±à¸šà¹„ม่มีใคร @@ -466,12 +516,16 @@ th: enable_bootstrap_timeline_accounts: title: เปิดใช้งานà¸à¸²à¸£à¸•ิดตามเริ่มต้นสำหรับผู้ใช้ใหม่ hero: + desc_html: à¹à¸ªà¸”งในหน้าà¹à¸£à¸ à¸à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸à¸¢ 600x100px ที่à¹à¸™à¸°à¸™à¸³ เมื่à¸à¹„ม่ได้ตั้ง à¸à¸¥à¸±à¸šà¹„ปใช้ภาพขนาดย่à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ title: ภาพà¹à¸šà¸™à¹€à¸™à¸à¸£à¹Œà¸«à¸¥à¸±à¸ mascot: + desc_html: à¹à¸ªà¸”งในหลายหน้า à¸à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸à¸¢ 293×205px ที่à¹à¸™à¸°à¸™à¸³ เมื่à¸à¹„ม่ได้ตั้ง à¸à¸¥à¸±à¸šà¹„ปใช้มาสคà¸à¸•เริ่มต้น title: ภาพมาสคà¸à¸• peers_api_enabled: desc_html: ชื่à¸à¹‚ดเมนที่เซิร์ฟเวà¸à¸£à¹Œà¸™à¸µà¹‰à¹„ด้พบในเฟดิเวิร์ส title: เผยà¹à¸žà¸£à¹ˆà¸£à¸²à¸¢à¸à¸²à¸£à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œà¸—ี่ค้นพบ + preview_sensitive_media: + title: à¹à¸ªà¸”งสื่à¸à¸—ี่ละเà¸à¸µà¸¢à¸”à¸à¹ˆà¸à¸™à¹ƒà¸™à¸•ัวà¸à¸¢à¹ˆà¸²à¸‡ OpenGraph profile_directory: desc_html: à¸à¸™à¸¸à¸à¸²à¸•ให้ผู้ใช้สามารถค้นพบได้ title: เปิดใช้งานไดเรà¸à¸—à¸à¸£à¸µà¹‚ปรไฟล์ @@ -507,11 +561,14 @@ th: title: เงื่à¸à¸™à¹„ขà¸à¸²à¸£à¹ƒà¸«à¹‰à¸šà¸£à¸´à¸à¸²à¸£à¸—ี่à¸à¸³à¸«à¸™à¸”เà¸à¸‡ site_title: ชื่à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ thumbnail: + desc_html: ใช้สำหรับตัวà¸à¸¢à¹ˆà¸²à¸‡à¸œà¹ˆà¸²à¸™ OpenGraph à¹à¸¥à¸° API 1200x630px ที่à¹à¸™à¸°à¸™à¸³ title: ภาพขนาดย่à¸à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ timeline_preview: desc_html: à¹à¸ªà¸”งลิงà¸à¹Œà¹„ปยังเส้นเวลาสาธารณะในหน้าเริ่มต้นà¹à¸¥à¸°à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¹€à¸‚้าถึง API ไปยังเส้นเวลาสาธารณะโดยไม่มีà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡ title: à¸à¸™à¸¸à¸à¸²à¸•à¸à¸²à¸£à¹€à¸‚้าถึงเส้นเวลาสาธารณะที่ไม่ได้รับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡ title: à¸à¸²à¸£à¸•ั้งค่าไซต์ + trendable_by_default: + desc_html: มีผลต่à¸à¹à¸®à¸Šà¹à¸—็à¸à¸—ี่ไม่ได้ไม่à¸à¸™à¸¸à¸à¸²à¸•à¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰ trends: title: à¹à¸®à¸Šà¹à¸—็à¸à¸—ี่à¸à¸³à¸¥à¸±à¸‡à¸™à¸´à¸¢à¸¡ site_uploads: @@ -551,12 +608,15 @@ th: edit_preset: à¹à¸à¹‰à¹„ขคำเตืà¸à¸™à¸—ี่ตั้งไว้ล่วงหน้า title: จัดà¸à¸²à¸£à¸„ำเตืà¸à¸™à¸—ี่ตั้งไว้ล่วงหน้า admin_mailer: + new_pending_account: + body: รายละเà¸à¸µà¸¢à¸”ขà¸à¸‡à¸šà¸±à¸à¸Šà¸µà¹ƒà¸«à¸¡à¹ˆà¸à¸¢à¸¹à¹ˆà¸”้านล่าง คุณสามารถà¸à¸™à¸¸à¸¡à¸±à¸•ิหรืà¸à¸›à¸à¸´à¹€à¸ªà¸˜à¹ƒà¸šà¸ªà¸¡à¸±à¸„รนี้ new_report: body: "%{reporter} ได้รายงาน %{target}" body_remote: ใครสัà¸à¸„นจาภ%{domain} ได้รายงาน %{target} subject: รายงานใหม่สำหรับ %{instance} (#%{id}) aliases: add_new: สร้างนามà¹à¸à¸‡ + deleted_msg: เà¸à¸²à¸™à¸²à¸¡à¹à¸à¸‡à¸à¸à¸à¸ªà¸³à¹€à¸£à¹‡à¸ˆ จะไม่สามารถย้ายจาà¸à¸šà¸±à¸à¸Šà¸µà¸™à¸±à¹‰à¸™à¹„ปยังบัà¸à¸Šà¸µà¸™à¸µà¹‰à¹„ด้à¸à¸µà¸à¸•่à¸à¹„ป empty: คุณไม่มีนามà¹à¸à¸‡ remove: เลิà¸à¹€à¸Šà¸·à¹ˆà¸à¸¡à¹‚ยงนามà¹à¸à¸‡ appearance: @@ -580,6 +640,8 @@ th: created: สร้างà¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันสำเร็จ destroyed: ลบà¹à¸à¸›à¸žà¸¥à¸´à¹€à¸„ชันสำเร็จ invalid_url: URL ที่ระบุไม่ถูà¸à¸•้à¸à¸‡ + regenerate_token: สร้างโทเคนà¸à¸²à¸£à¹€à¸‚้าถึงใหม่ + token_regenerated: สร้างโทเคนà¸à¸²à¸£à¹€à¸‚้าถึงใหม่สำเร็จ your_token: โทเคนà¸à¸²à¸£à¹€à¸‚้าถึงขà¸à¸‡à¸„ุณ auth: apply_for_account: ขà¸à¸„ำเชิภ@@ -587,29 +649,42 @@ th: checkbox_agreement_html: ฉันยà¸à¸¡à¸£à¸±à¸š <a href="%{rules_path}" target="_blank">à¸à¸Žà¸‚à¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ</a> à¹à¸¥à¸° <a href="%{terms_path}" target="_blank">เงื่à¸à¸™à¹„ขà¸à¸²à¸£à¹ƒà¸«à¹‰à¸šà¸£à¸´à¸à¸²à¸£</a> checkbox_agreement_without_rules_html: ฉันยà¸à¸¡à¸£à¸±à¸š <a href="%{terms_path}" target="_blank">เงื่à¸à¸™à¹„ขà¸à¸²à¸£à¹ƒà¸«à¹‰à¸šà¸£à¸´à¸à¸²à¸£</a> delete_account: ลบบัà¸à¸Šà¸µ + delete_account_html: หาà¸à¸„ุณต้à¸à¸‡à¸à¸²à¸£à¸¥à¸šà¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณ คุณสามารถ <a href="%{path}">ดำเนินà¸à¸²à¸£à¸•่à¸à¸—ี่นี่</a> คุณจะได้รับà¸à¸²à¸£à¸–ามเพื่à¸à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™ description: + prefix_invited_by_user: "@%{name} เชิà¸à¸„ุณเข้าร่วมเซิร์ฟเวà¸à¸£à¹Œ Mastodon นี้!" prefix_sign_up: ลงทะเบียนใน Mastodon วันนี้! didnt_get_confirmation: ไม่ได้รับคำà¹à¸™à¸°à¸™à¸³à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™? + dont_have_your_security_key: ไม่มีà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณ? forgot_password: ลืมรหัสผ่านขà¸à¸‡à¸„ุณ? + invalid_reset_password_token: โทเคนà¸à¸²à¸£à¸•ั้งรหัสผ่านใหม่ไม่ถูà¸à¸•้à¸à¸‡à¸«à¸£à¸·à¸à¸«à¸¡à¸”à¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ โปรดขà¸à¹‚ทเคนใหม่ + link_to_otp: ป้à¸à¸™à¸£à¸«à¸±à¸ªà¸ªà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸ˆà¸²à¸à¹‚ทรศัพท์ขà¸à¸‡à¸„ุณหรืà¸à¸£à¸«à¸±à¸ªà¸à¸¹à¹‰à¸„ืน + link_to_webauth: ใช้à¸à¸¸à¸›à¸à¸£à¸“์à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณ login: เข้าสู่ระบบ logout: à¸à¸à¸à¸ˆà¸²à¸à¸£à¸°à¸šà¸š migrate_account: ย้ายไปยังบัà¸à¸Šà¸µà¸à¸·à¹ˆà¸™ + migrate_account_html: หาà¸à¸„ุณต้à¸à¸‡à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างบัà¸à¸Šà¸µà¸™à¸µà¹‰à¹„ปยังบัà¸à¸Šà¸µà¸à¸·à¹ˆà¸™ คุณสามารถ <a href="%{path}">à¸à¸³à¸«à¸™à¸”ค่าบัà¸à¸Šà¸µà¸—ี่นี่</a> or_log_in_with: หรืà¸à¹€à¸‚้าสู่ระบบด้วย providers: cas: CAS saml: SAML register: ลงทะเบียน + registration_closed: "%{instance} ไม่ได้à¸à¸³à¸¥à¸±à¸‡à¹€à¸›à¸´à¸”รับสมาชิà¸à¹ƒà¸«à¸¡à¹ˆ" resend_confirmation: ส่งคำà¹à¸™à¸°à¸™à¸³à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¹ƒà¸«à¸¡à¹ˆ reset_password: ตั้งรหัสผ่านใหม่ security: ความปลà¸à¸”ภัย set_new_password: ตั้งรหัสผ่านใหม่ + setup: + email_below_hint_html: หาà¸à¸—ี่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸”้านล่างไม่ถูà¸à¸•้à¸à¸‡ คุณสามารถเปลี่ยนที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸—ี่นี่à¹à¸¥à¸°à¸£à¸±à¸šà¸à¸µà¹€à¸¡à¸¥à¸¢à¸·à¸™à¸¢à¸±à¸™à¹ƒà¸«à¸¡à¹ˆ + email_settings_hint_html: ส่งà¸à¸µà¹€à¸¡à¸¥à¸¢à¸·à¸™à¸¢à¸±à¸™à¹„ปยัง %{email} à¹à¸¥à¹‰à¸§ หาà¸à¸—ี่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸™à¸±à¹‰à¸™à¹„ม่ถูà¸à¸•้à¸à¸‡ คุณสามารถเปลี่ยนที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¹ƒà¸™à¸à¸²à¸£à¸•ั้งค่าบัà¸à¸Šà¸µ status: account_status: สถานะบัà¸à¸Šà¸µ confirming: à¸à¸³à¸¥à¸±à¸‡à¸£à¸à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¹‰à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์ functional: บัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณทำงานได้à¸à¸¢à¹ˆà¸²à¸‡à¹€à¸•็มที่ trouble_logging_in: มีปัà¸à¸«à¸²à¹ƒà¸™à¸à¸²à¸£à¹€à¸‚้าสู่ระบบ? + use_security_key: ใช้à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัย authorize_follow: already_following: คุณà¸à¸³à¸¥à¸±à¸‡à¸•ิดตามบัà¸à¸Šà¸µà¸™à¸µà¹‰à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ + already_requested: คุณได้ส่งคำขà¸à¸•ิดตามไปยังบัà¸à¸Šà¸µà¸™à¸±à¹‰à¸™à¹„ปà¹à¸¥à¹‰à¸§ follow: ติดตาม follow_request: 'คุณได้ส่งคำขà¸à¸•ิดตามไปยัง:' following: 'สำเร็จ! คุณà¸à¸³à¸¥à¸±à¸‡à¸•ิดตาม:' @@ -629,6 +704,7 @@ th: date: formats: default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count} ชั่วโมง" @@ -673,6 +749,7 @@ th: title: à¸à¸²à¸£à¸•รวจสà¸à¸šà¸„วามปลà¸à¸”ภัยล้มเหลว '429': คำขà¸à¸¡à¸²à¸à¹€à¸à¸´à¸™à¹„ป '500': + content: เราขà¸à¸à¸ ัย à¹à¸•่มีบางà¸à¸¢à¹ˆà¸²à¸‡à¸œà¸´à¸”พลาดในส่วนขà¸à¸‡à¹€à¸£à¸² title: หน้านี้ไม่ถูà¸à¸•้à¸à¸‡ '503': The page could not be served due to a temporary server failure. existing_username_validator: @@ -685,6 +762,7 @@ th: request: ขà¸à¸à¸²à¸£à¹€à¸à¹‡à¸šà¸–าวรขà¸à¸‡à¸„ุณ size: ขนาด blocks: คุณปิดà¸à¸±à¹‰à¸™ + bookmarks: ที่คั่นหน้า csv: CSV domain_blocks: à¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน lists: รายà¸à¸²à¸£ @@ -695,7 +773,7 @@ th: filters: contexts: account: โปรไฟล์ - home: เส้นเวลาหน้าà¹à¸£à¸ + home: หน้าà¹à¸£à¸à¹à¸¥à¸°à¸£à¸²à¸¢à¸à¸²à¸£ notifications: à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™ public: เส้นเวลาสาธารณะ thread: à¸à¸²à¸£à¸ªà¸™à¸—นา @@ -724,13 +802,18 @@ th: identity_proofs: active: ใช้งานà¸à¸¢à¸¹à¹ˆ authorize: ใช่ à¸à¸™à¸¸à¸à¸²à¸• + i_am_html: ฉันคืภ%{username} ใน %{service} identity: ตัวตน inactive: ไม่ได้ใช้งาน publicize_checkbox: 'à¹à¸¥à¸°à¹‚พสต์สิ่งนี้:' + publicize_toot: 'พิสูจน์ตัวตนà¹à¸¥à¹‰à¸§! ฉันคืภ%{username} ใน %{service}: %{url}' remove: เà¸à¸²à¸à¸²à¸£à¸žà¸´à¸ªà¸¹à¸ˆà¸™à¹Œà¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µ removed: เà¸à¸²à¸à¸²à¸£à¸žà¸´à¸ªà¸¹à¸ˆà¸™à¹Œà¸à¸à¸à¸ˆà¸²à¸à¸šà¸±à¸à¸Šà¸µà¸ªà¸³à¹€à¸£à¹‡à¸ˆ status: สถานะà¸à¸²à¸£à¸•รวจสà¸à¸š + view_proof: ดูà¸à¸²à¸£à¸žà¸´à¸ªà¸¹à¸ˆà¸™à¹Œ imports: + errors: + over_rows_processing_limit: มีมาà¸à¸à¸§à¹ˆà¸² %{count} à¹à¸–ว modes: merge: ผสาน merge_long: เà¸à¹‡à¸šà¸£à¸°à¹€à¸šà¸µà¸¢à¸™à¸—ี่มีà¸à¸¢à¸¹à¹ˆà¹à¸¥à¸°à¹€à¸žà¸´à¹ˆà¸¡à¸£à¸°à¹€à¸šà¸µà¸¢à¸™à¹ƒà¸«à¸¡à¹ˆ @@ -738,6 +821,7 @@ th: overwrite_long: à¹à¸—นที่ระเบียนปัจจุบันด้วยระเบียนใหม่ types: blocking: รายà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™ + bookmarks: ที่คั่นหน้า domain_blocking: รายà¸à¸²à¸£à¸›à¸´à¸”à¸à¸±à¹‰à¸™à¹‚ดเมน following: รายà¸à¸²à¸£à¸•ิดตาม muting: รายà¸à¸²à¸£à¸‹à¹ˆà¸à¸™ @@ -745,6 +829,7 @@ th: in_memoriam_html: เพื่à¸à¸£à¸°à¸¥à¸¶à¸à¸–ึง invites: delete: ปิดใช้งาน + expired: หมดà¸à¸²à¸¢à¸¸à¹à¸¥à¹‰à¸§ expires_in: '1800': 30 นาที '21600': 6 ชั่วโมง @@ -758,6 +843,7 @@ th: max_uses: other: "%{count} à¸à¸²à¸£à¹ƒà¸Šà¹‰" max_uses_prompt: ไม่มีขีดจำà¸à¸±à¸” + prompt: สร้างà¹à¸¥à¸°à¹à¸šà¹ˆà¸‡à¸›à¸±à¸™à¸¥à¸´à¸‡à¸à¹Œà¸à¸±à¸šà¸œà¸¹à¹‰à¸à¸·à¹ˆà¸™à¹€à¸žà¸·à¹ˆà¸à¸à¸™à¸¸à¸à¸²à¸•ให้เข้าถึงเซิร์ฟเวà¸à¸£à¹Œà¸™à¸µà¹‰ table: expires_at: หมดà¸à¸²à¸¢à¸¸à¹€à¸¡à¸·à¹ˆà¸ uses: à¸à¸²à¸£à¹ƒà¸Šà¹‰ @@ -780,6 +866,8 @@ th: redirected_msg: บัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณà¸à¸³à¸¥à¸±à¸‡à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างไปยัง %{acct} redirecting_to: บัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณà¸à¸³à¸¥à¸±à¸‡à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างไปยัง %{acct} set_redirect: ตั้งà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—าง + warning: + followers: à¸à¸²à¸£à¸à¸£à¸°à¸—ำนี้จะย้ายผู้ติดตามทั้งหมดจาà¸à¸šà¸±à¸à¸Šà¸µà¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¹„ปยังบัà¸à¸Šà¸µà¹ƒà¸«à¸¡à¹ˆ moderation: title: à¸à¸²à¸£à¸„วบคุม move_handler: @@ -821,6 +909,10 @@ th: email_events: เหตุà¸à¸²à¸£à¸“์สำหรับà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸à¸µà¹€à¸¡à¸¥ email_events_hint: 'เลืà¸à¸à¹€à¸«à¸•ุà¸à¸²à¸£à¸“์ที่คุณต้à¸à¸‡à¸à¸²à¸£à¸£à¸±à¸šà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™:' other_settings: à¸à¸²à¸£à¸•ั้งค่าà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ืà¸à¸™à¸à¸·à¹ˆà¸™ ๆ + otp_authentication: + code_hint: ป้à¸à¸™à¸£à¸«à¸±à¸ªà¸—ี่สร้างโดยà¹à¸à¸›à¸•ัวรับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸‚à¸à¸‡à¸„ุณเพื่à¸à¸¢à¸·à¸™à¸¢à¸±à¸™ + enable: เปิดใช้งาน + wrong_code: รหัสที่ป้à¸à¸™à¹„ม่ถูà¸à¸•้à¸à¸‡! เวลาเซิร์ฟเวà¸à¸£à¹Œà¹à¸¥à¸°à¹€à¸§à¸¥à¸²à¸à¸¸à¸›à¸à¸£à¸“์ถูà¸à¸•้à¸à¸‡à¸«à¸£à¸·à¸à¹„ม่? pagination: newer: ใหม่à¸à¸§à¹ˆà¸² next: ถัดไป @@ -829,8 +921,9 @@ th: truncate: "…" polls: errors: - already_voted: คุณได้ลงคะà¹à¸™à¸™à¹ƒà¸™à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นนี้à¸à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ + already_voted: คุณได้ลงคะà¹à¸™à¸™à¹ƒà¸™à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นนี้ไปà¹à¸¥à¹‰à¸§ duplicate_options: มีรายà¸à¸²à¸£à¸—ี่ซ้ำà¸à¸±à¸™ + expired: à¸à¸²à¸£à¸ªà¸³à¸£à¸§à¸ˆà¸„วามคิดเห็นได้สิ้นสุดไปà¹à¸¥à¹‰à¸§ invalid_choice: ไม่มีตัวเลืà¸à¸à¸à¸²à¸£à¸¥à¸‡à¸„ะà¹à¸™à¸™à¸—ี่เลืà¸à¸à¸à¸¢à¸¹à¹ˆ too_few_options: ต้à¸à¸‡à¸¡à¸µà¸¡à¸²à¸à¸à¸§à¹ˆà¸²à¸«à¸™à¸¶à¹ˆà¸‡à¸£à¸²à¸¢à¸à¸²à¸£ too_many_options: ไม่สามารถมีมาà¸à¸à¸§à¹ˆà¸² %{max} รายà¸à¸²à¸£ @@ -844,6 +937,7 @@ th: relationships: activity: à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸šà¸±à¸à¸Šà¸µ dormant: ไม่เคลื่à¸à¸™à¹„หว + follow_selected_followers: ติดตามผู้ติดตามที่เลืà¸à¸ followers: ผู้ติดตาม following: à¸à¸³à¸¥à¸±à¸‡à¸•ิดตาม invited: เชิà¸à¹à¸¥à¹‰à¸§ @@ -934,6 +1028,7 @@ th: profile: โปรไฟล์ relationships: à¸à¸²à¸£à¸•ิดตามà¹à¸¥à¸°à¸œà¸¹à¹‰à¸•ิดตาม two_factor_authentication: à¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢ + webauthn_authentication: à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัย spam_check: spam_detected: นี่คืà¸à¸£à¸²à¸¢à¸‡à¸²à¸™à¹à¸šà¸šà¸à¸±à¸•โนมัติ ตรวจพบสà¹à¸›à¸¡ statuses: @@ -962,12 +1057,14 @@ th: other: "%{count} à¸à¸²à¸£à¸¥à¸‡à¸„ะà¹à¸™à¸™" vote: ลงคะà¹à¸™à¸™ show_more: à¹à¸ªà¸”งเพิ่มเติม + show_newer: à¹à¸ªà¸”งที่ใหม่à¸à¸§à¹ˆà¸² + show_older: à¹à¸ªà¸”งที่เà¸à¹ˆà¸²à¸à¸§à¹ˆà¸² show_thread: à¹à¸ªà¸”งà¸à¸£à¸°à¸—ู้ sign_in_to_participate: ลงชื่à¸à¹€à¸‚้าเพื่à¸à¹€à¸‚้าร่วมà¸à¸²à¸£à¸ªà¸™à¸—นา title: '%{name}: "%{quote}"' visibilities: private: ผู้ติดตามเท่านั้น - private_long: à¹à¸ªà¸”งต่à¸à¸œà¸¹à¹‰à¸•ิดตามเท่านั้น + private_long: à¹à¸ªà¸”งà¹à¸à¹ˆà¸œà¸¹à¹‰à¸•ิดตามเท่านั้น public: สาธารณะ public_long: ทุà¸à¸„นสามารถเห็น unlisted: ไม่à¸à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£ @@ -988,16 +1085,25 @@ th: default: "%d %b %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: ป้à¸à¸™à¸£à¸«à¸±à¸ªà¸—ี่สร้างโดยà¹à¸à¸›à¸•ัวรับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸‚à¸à¸‡à¸„ุณเพื่à¸à¸¢à¸·à¸™à¸¢à¸±à¸™ - disable: ปิดใช้งาน - enable: เปิดใช้งาน + add: เพิ่ม + disable: ปิดใช้งาน 2FA + disabled_success: ปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸ªà¸³à¹€à¸£à¹‡à¸ˆ + edit: à¹à¸à¹‰à¹„ข enabled: เปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¹à¸¥à¹‰à¸§ enabled_success: เปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸ªà¸³à¹€à¸£à¹‡à¸ˆ generate_recovery_codes: สร้างรหัสà¸à¸¹à¹‰à¸„ืน + methods: วิธีà¸à¸²à¸£à¸ªà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢ + otp: à¹à¸à¸›à¸•ัวรับรà¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡ recovery_codes: รหัสà¸à¸¹à¹‰à¸„ืนข้à¸à¸¡à¸¹à¸¥à¸ªà¸³à¸£à¸à¸‡ - setup: ตั้งค่า - wrong_code: รหัสที่ป้à¸à¸™à¹„ม่ถูà¸à¸•้à¸à¸‡! เวลาเซิร์ฟเวà¸à¸£à¹Œà¹à¸¥à¸°à¹€à¸§à¸¥à¸²à¸à¸¸à¸›à¸à¸£à¸“์ถูà¸à¸•้à¸à¸‡à¸«à¸£à¸·à¸à¹„ม่? + recovery_codes_regenerated: สร้างรหัสà¸à¸¹à¹‰à¸„ืนใหม่สำเร็จ + webauthn: à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัย user_mailer: + sign_in_token: + details: 'นี่คืà¸à¸£à¸²à¸¢à¸¥à¸°à¹€à¸à¸µà¸¢à¸”ขà¸à¸‡à¸„วามพยายาม:' + explanation: 'เราตรวจพบความพยายามลงชื่à¸à¹€à¸‚้าบัà¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณจาà¸à¸—ี่à¸à¸¢à¸¹à¹ˆ IP ที่ไม่รู้จัภหาà¸à¸™à¸µà¹ˆà¸„ืà¸à¸„ุณ โปรดป้à¸à¸™à¸£à¸«à¸±à¸ªà¸„วามปลà¸à¸”ภัยด้านล่างในหน้าตรวจสà¸à¸šà¸à¸²à¸£à¸¥à¸‡à¸Šà¸·à¹ˆà¸à¹€à¸‚้า:' + further_actions: 'หาà¸à¸™à¸µà¹ˆà¹„ม่ใช่คุณ โปรดเปลี่ยนรหัสผ่านขà¸à¸‡à¸„ุณà¹à¸¥à¸°à¹€à¸›à¸´à¸”ใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µà¸‚à¸à¸‡à¸„ุณ คุณสามารถทำได้ที่นี่:' + subject: โปรดยืนยันà¸à¸²à¸£à¸¥à¸‡à¸Šà¸·à¹ˆà¸à¹€à¸‚้าที่พยายาม + title: ความพยายามลงชื่à¸à¹€à¸‚้า warning: review_server_policies: ตรวจทานนโยบายขà¸à¸‡à¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸à¸£à¹Œ subject: @@ -1012,11 +1118,28 @@ th: tips: เคล็ดลับ title: ยินดีต้à¸à¸™à¸£à¸±à¸š %{name}! users: + blocked_email_provider: ไม่à¸à¸™à¸¸à¸à¸²à¸•ผู้ให้บริà¸à¸²à¸£à¸à¸µà¹€à¸¡à¸¥à¸™à¸µà¹‰ follow_limit_reached: คุณไม่สามารถติดตามมาà¸à¸à¸§à¹ˆà¸² %{limit} คน invalid_email: ที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¹„ม่ถูà¸à¸•้à¸à¸‡ + invalid_email_mx: ดูเหมืà¸à¸™à¸§à¹ˆà¸²à¹„ม่มีที่à¸à¸¢à¸¹à¹ˆà¸à¸µà¹€à¸¡à¸¥à¸à¸¢à¸¹à¹ˆ invalid_otp_token: รหัสสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¹„ม่ถูà¸à¸•้à¸à¸‡ invalid_sign_in_token: รหัสความปลà¸à¸”ภัยไม่ถูà¸à¸•้à¸à¸‡ seamless_external_login: คุณได้เข้าสู่ระบบผ่านบริà¸à¸²à¸£à¸ ายนà¸à¸ ดังนั้นจึงไม่มีà¸à¸²à¸£à¸•ั้งค่ารหัสผ่านà¹à¸¥à¸°à¸à¸µà¹€à¸¡à¸¥ signed_in_as: 'ลงชื่à¸à¹€à¸‚้าเป็น:' verification: verification: à¸à¸²à¸£à¸•รวจสà¸à¸š + webauthn_credentials: + add: เพิ่มà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยใหม่ + create: + error: มีปัà¸à¸«à¸²à¹ƒà¸™à¸à¸²à¸£à¹€à¸žà¸´à¹ˆà¸¡à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณ โปรดลà¸à¸‡à¸à¸µà¸à¸„รั้ง + success: เพิ่มà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณสำเร็จ + delete: ลบ + delete_confirmation: คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸à¹„ม่ว่าต้à¸à¸‡à¸à¸²à¸£à¸¥à¸šà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยนี้? + destroy: + error: มีปัà¸à¸«à¸²à¹ƒà¸™à¸à¸²à¸£à¸¥à¸šà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณ โปรดลà¸à¸‡à¸à¸µà¸à¸„รั้ง + success: ลบà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยขà¸à¸‡à¸„ุณสำเร็จ + invalid_credential: à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัยไม่ถูà¸à¸•้à¸à¸‡ + not_enabled: คุณยังไม่ได้เปิดใช้งาน WebAuthn + not_supported: เบราว์เซà¸à¸£à¹Œà¸™à¸µà¹‰à¹„ม่รà¸à¸‡à¸£à¸±à¸šà¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัย + otp_required: เพื่à¸à¹ƒà¸Šà¹‰à¸à¸¸à¸à¹à¸ˆà¸„วามปลà¸à¸”ภัย โปรดเปิดใช้งานà¸à¸²à¸£à¸£à¸±à¸šà¸£à¸à¸‡à¸„วามถูà¸à¸•้à¸à¸‡à¸”้วยสà¸à¸‡à¸›à¸±à¸ˆà¸ˆà¸±à¸¢à¸à¹ˆà¸à¸™ + registered_on: ลงทะเบียนเมื่ภ%{date} diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 650166781f4ec7d93ecd0c01c7545a02ba720c94..62247bf56a2fd11eb8605bba31c954a806278285 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -3,10 +3,10 @@ tr: about: about_hashtag_html: Bunlar <strong>#%{hashtag}</strong> ile etiketlenen genel tootlar. Fediverse içinde herhangi bir yerde bir hesabınız varsa, onlarla etkileÅŸime geçebilirsiniz. about_mastodon_html: Mastodon <em>ücretsiz ve açık kaynaklı</em> bir sosyal aÄŸdır. <em>MerkezileÅŸtirilmemiÅŸ</em> yapısı sayesinde diÄŸer ticari sosyal platformların aksine iletiÅŸimininizin tek bir firmada tutulmasının/yönetilmesinin önüne geçer. GüvendiÄŸiniz bir sunucuyu seçerek oradaki kiÅŸilerle etkileÅŸimde bulunabilirsiniz. Herkes kendi Mastodon sunucusunu kurabilir ve sorunsuz bir ÅŸekilde Mastodon <em>sosyal ağına</em> dahil edebilir. - about_this: Bu sunucu hakkında + about_this: Hakkında active_count_after: etkin active_footnote: Aylık Aktif Kullanıcılar (AAK) - administered_by: 'Yöneten:' + administered_by: 'Yönetici:' api: API apps: Mobil uygulamalar apps_platforms: İos, Android ve diÄŸer platformlardaki Mastodon'u kullanın @@ -30,19 +30,21 @@ tr: server_stats: 'Sunucu istatistikleri:' source_code: Kaynak kodu status_count_after: - one: durum - other: durum + one: durum yazıldı + other: durum yazıldı status_count_before: Åžu ana kadar tagline: ArkadaÅŸlarını takip et ve yenilerini keÅŸfet terms: Kullanım ÅŸartları - unavailable_content: Mevcut olmayan içerik + unavailable_content: Denetlenen sunucular unavailable_content_description: domain: Sunucu reason: Sebep rejecting_media: 'Bu sunuculardaki medya dosyaları iÅŸlenmeyecek ya da saklanmayacak, ve hiçbir küçük resim gösterilmeyecektir, dolayısıyla orjinal dosyaya manuel tıklama gerekecektir:' rejecting_media_title: FiltrelenmiÅŸ medya silenced: 'Bu sunuculardan gelen gönderiler genel zaman çizelgelerinde ve konuÅŸmalarda gizlenecek ve siz onları takip etmediÄŸiniz sürece, kullanıcıların etkileÅŸimlerinden hiçbir bildirim alınmayacaktır:' + silenced_title: SusturulmuÅŸ sunucular suspended: 'Bu sunuculardaki hiçbir veri iÅŸlenmeyecek, saklanmayacak veya deÄŸiÅŸ tokuÅŸ edilmeyecektir, dolayısıyla bu sunuculardaki kullanıcılarla herhangi bir etkileÅŸim ya da iletiÅŸim imkansız olacaktır:' + suspended_title: Askıya alınan sunucular unavailable_content_html: Mastodon, genel olarak fediverse'teki herhangi bir sunucudan içerik görüntülemenize ve kullanıcılarıyla etkileÅŸim kurmanıza izin verir. Bunlar, bu sunucuda yapılmış olan istisnalardır. user_count_after: one: kullanıcı @@ -50,16 +52,16 @@ tr: user_count_before: Kayıtlı what_is_mastodon: Mastodon nedir? accounts: - choices_html: "%{name} seçimleri:" + choices_html: "%{name} kiÅŸisinin seçimleri:" endorsements_hint: Takip ettiÄŸiniz kiÅŸileri web arayüzünden onaylayabilirsiniz, burada görünecekler. featured_tags_hint: Burada görüntülenecek belirli etiketlere sahip olabilirsiniz. follow: Takip et followers: one: Takipçi other: Takipçi - following: Takip ettikleri + following: Takip edilenler joined: "%{date} tarihinde katıldı" - last_active: son aktivite + last_active: son etkinlik link_verified_on: Bu baÄŸlantının mülkiyeti %{date} tarihinde kontrol edildi media: Medya moved_html: "%{name}, %{new_profile_link} adresine taşındı:" @@ -72,10 +74,10 @@ tr: following: Onaylamak istediÄŸiniz kiÅŸiyi zaten takip ediyor olmalısınız posts: one: Toot - other: Tootlar + other: Toot posts_tab_heading: Tootlar posts_with_replies: Tootlar ve yanıtlar - reserved_username: Kullanıcı adı saklıdır + reserved_username: Kullanıcı adı rezerve edildi roles: admin: Yönetici bot: Bot @@ -88,16 +90,18 @@ tr: action: Eylemi gerçekleÅŸtir title: "%{acct} üzerinde denetleme eylemi gerçekleÅŸtir" account_moderation_notes: - create: Not bırakın + create: Not bırak created_msg: Denetim notu baÅŸarıyla oluÅŸturuldu! delete: Sil destroyed_msg: Denetim notu baÅŸarıyla yok edildi! accounts: + add_email_domain_block: E-posta alan adını engelle approve: Onayla approve_all: Tümünü onayla + approved_msg: "%{username} adlı kullanıcının kayıt baÅŸvurusu baÅŸarıyla onaylandı" are_you_sure: Emin misiniz? - avatar: Avatar - by_domain: Sunucu + avatar: Profil resmi + by_domain: Alan adı change_email: changed_msg: Hesap e-postası baÅŸarıyla deÄŸiÅŸtirildi! current_email: Mevcut e-posta @@ -107,19 +111,22 @@ tr: title: "%{username} için e-postayı deÄŸiÅŸtir" confirm: Onayla confirmed: Onaylandı - confirming: Onaylama - deleted: Silinen + confirming: Onaylanıyor + delete: Veriyi sil + deleted: Silindi demote: Düşür + destroyed_msg: "%{username} verilerinin hemen silinmesi için kuyruÄŸa alındı" disable: Devre dışı disable_two_factor_authentication: 2AD kapat disabled: Kapalı - display_name: Görünen adınız - domain: Sunucu + display_name: Görünen isim + domain: Alan adı edit: Düzenle email: E-posta email_status: E-posta durumu enable: EtkinleÅŸtir enabled: Etkin + enabled_msg: "%{username} hesabı baÅŸarıyla çözüldü" followers: Takipçiler follows: Takip edilen header: Üstbilgi @@ -132,16 +139,18 @@ tr: local: Yerel remote: Uzaktan title: Konum - login_status: GiriÅŸ durumu + login_status: Oturum açma durumu media_attachments: Medya ekleri - memorialize: Bir hatıraya dön + memorialize: Anıta dönüştür + memorialized: AnıtlaÅŸtırıldı + memorialized_msg: "%{username} hesabı baÅŸarıyla anıt hesabına dönüştürüldü" moderation: active: Etkin all: Hepsi pending: Bekliyor silenced: Susturulanlar suspended: UzaklaÅŸtırılanlar - title: Yönetim + title: Denetim moderation_notes: Denetleme notları most_recent_activity: Son aktivite most_recent_ip: Son IP @@ -155,16 +164,20 @@ tr: public: Herkese açık push_subscription_expires: PuSH aboneliÄŸi dolumu redownload: Profili yenile + redownloaded_msg: "%{username} kullanıcısının profili kökenden baÅŸarıyla yenilendi" reject: Reddet reject_all: Tümünü reddet - remove_avatar: Avatarı kaldır + rejected_msg: "%{username} adlı kullanıcının kayıt baÅŸvurusu baÅŸarıyla reddedildi" + remove_avatar: Profil resmini kaldır remove_header: Üstbilgiyi kaldır + removed_avatar_msg: "%{username} hesabının avatar resmi baÅŸarıyla kaldırıldı" + removed_header_msg: "%{username} hesabının baÅŸlık resmi baÅŸarıyla kaldırıldı" resend_confirmation: already_confirmed: Bu kullanıcı zaten onaylandı send: DoÄŸrulama epostasını yeniden gönder success: Onay e-postası baÅŸarıyla gönderildi! reset: Sıfırla - reset_password: Parolayı deÄŸiÅŸtir + reset_password: Åžifreyi sıfırla resubscribe: Yeniden abone ol role: İzinler roles: @@ -173,7 +186,10 @@ tr: staff: Personel user: Kullanıcı search: Ara + search_same_email_domain: Aynı e-posta alan adına sahip diÄŸer kullanıcılar search_same_ip: Aynı IP adresine sahip diÄŸer kullanıcılar + sensitive: Hassas + sensitized: hassas olarak iÅŸaretlendi shared_inbox_url: Paylaşılan gelen kutusu baÄŸlantısı show: created_reports: Yapılan ÅŸikayetler @@ -183,23 +199,64 @@ tr: statuses: Durumlar subscribe: Abone ol suspended: Askıya alındı + suspension_irreversible: Bu hesabın verileri geri dönüşümsüz olarak silindi. Hesabı kullanılabilir hale getirmek için hesabın askıya alınmasını kaldırabilirsiniz, ancak daha önce sahip olduÄŸu herhangi bir veri kurtarılamaz. + suspension_reversible_hint_html: Hesap askıya alındı ve veriler %{date} tarihinde tamamen kaldırılacak. O zamana kadar, hesap herhangi bir olumsuz etki olmaksızın geri yüklenebilir. Hesabın tüm verilerini hemen kaldırmak isterseniz, bunu aÅŸağıdan yapabilirsiniz. time_in_queue: "%{time} kuyruÄŸunda bekliyor" title: Hesaplar unconfirmed_email: Onaylanmamış e-posta + undo_sensitized: Hassaslığı geri al undo_silenced: Susturmayı geri al undo_suspension: UzaklaÅŸtırmayı geri al + unsilenced_msg: "%{username} hesabı baÅŸarıyla sınırsız yapıldı" unsubscribe: Abonelikten çık + unsuspended_msg: "%{username} hesabının askıya alınması baÅŸarıyla kaldırıldı" username: Kullanıcı adı + view_domain: Alan adı için özeti görüntüleyin warn: Uyar web: Web whitelisted: Beyaz listede action_logs: action_types: - change_email_user: Kullanıcı için e-postayı deÄŸiÅŸtir + assigned_to_self_report: Raporu Ata + change_email_user: Kullanıcı E-postasını DeÄŸiÅŸtir confirm_user: Kullanıcıyı Onayla + create_account_warning: Uyarı OluÅŸtur create_announcement: Duyuru OluÅŸtur create_custom_emoji: Özel İfade OluÅŸtur + create_domain_allow: İzin Verilen Alan Adı OluÅŸtur + create_domain_block: Engellenen Alan Adı OluÅŸtur + create_email_domain_block: E-Posta Alan Adı Engeli OluÅŸtur + create_ip_block: IP kuralı oluÅŸtur + demote_user: Kullanıcıyı Düşür + destroy_announcement: Duyuru Sil + destroy_custom_emoji: Özel İfadeyi Sil + destroy_domain_allow: İzin Verilen Alan Adını Sil + destroy_domain_block: Engellenen Alan Adını Sil + destroy_email_domain_block: E-posta alan adı engelini sil + destroy_ip_block: IP kuralını sil destroy_status: Durumu Sil + disable_2fa_user: 2AD Kapat + disable_custom_emoji: Özel İfadeyi Devre Dışı Bırak + disable_user: Kullanıcıyı Devre Dışı Bırak + enable_custom_emoji: Özel İfadeyi EtkinleÅŸtir + enable_user: Kullanıcıyı EtkinleÅŸtir + memorialize_account: Hesabı AnıtlaÅŸtır + promote_user: Kullanıcıyı Yükselt + remove_avatar_user: Profil Resmini Kaldır + reopen_report: Åžikayeti Tekrar Aç + reset_password_user: Parolayı Sıfırla + resolve_report: Åžikayeti Çöz + sensitive_account: Hesabınızdaki medyayı hassas olarak iÅŸaretleyin + silence_account: Hesabı Sustur + suspend_account: Hesabı Askıya Al + unassigned_report: Rapor Atamasını Kaldır + unsensitive_account: Hesabınızdaki medyayı hassas olarak iÅŸaretlemeyin + unsilence_account: Hesabın Sesini Aç + unsuspend_account: Hesabı Askıdan Kaldır + update_announcement: Duyuruyu Güncelle + update_custom_emoji: Özel İfadeyi Güncelle + update_domain_block: Engellenen Alan Adını Güncelle + update_status: Durumu Güncelle actions: assigned_to_self_report: "%{name} kendilerine %{target} adlı raporu verdi" change_email_user: "%{name}, %{target} kullanıcısının e-posta adresini deÄŸiÅŸtirdi" @@ -210,31 +267,36 @@ tr: create_domain_allow: "%{target} alan adı, %{name} tarafından beyaz listeye alındı" create_domain_block: "%{target} alanı, %{name} tarafından engellendi" create_email_domain_block: "%{target} e-posta alanı, %{name} tarafından kara listeye alınmış" + create_ip_block: "%{name}, IP %{target} için kural oluÅŸturdu" demote_user: "%{name} %{target} kullanıcısını düşürdü" destroy_announcement: "%{name}, %{target} duyurusunu sildi" destroy_custom_emoji: "%{target} emoji, %{name} tarafından kaldırıldı" destroy_domain_allow: "%{target} alan adı, %{name} tarafından beyaz listeden çıkartıldı" destroy_domain_block: "%{target} alan adının engeli %{name} tarafından kaldırıldı" destroy_email_domain_block: "%{target} e-posta sunucusu, %{name} tarafından beyaz listeye alındı" + destroy_ip_block: "%{name}, IP %{target} için kuralı sildi" destroy_status: "%{name}, %{target} kullanıcısının durumunu kaldırdı" disable_2fa_user: "%{name}, %{target} kullanıcısı için iki adım gereksinimini kapattı" disable_custom_emoji: "%{target} emoji, %{name} tarafından devre dışı bırakıldı" disable_user: "%{name} %{target} kullanıcısı için oturum açmayı devre dışı bıraktı" enable_custom_emoji: "%{name} %{target} için emojiyi etkinleÅŸtirdi" enable_user: "%{name} %{target} için oturum açmayı etkinleÅŸtirdi" - memorialize_account: "%{name} %{target}'in hesabını bir hatıra sayfasına dönüştürdü" + memorialize_account: "%{name}, %{target} kiÅŸisinin hesabını anıt sayfasına dönüştürdü" promote_user: "%{name} %{target} kullanıcısını yükseltti" remove_avatar_user: "%{name} %{target}'in avatarını kaldırdı" reopen_report: "%{name} %{target} ÅŸikayetini yeniden açtı" reset_password_user: "%{name} %{target} kullanıcısının parolasını resetledi" resolve_report: "%{name} %{target} ÅŸikayetini çözdü" + sensitive_account: "%{name}, %{target} kiÅŸisinin medyasını hassas olarak iÅŸaretledi" silence_account: "%{name} %{target}'in hesabını susturdu" suspend_account: "%{name} %{target}'in hesabını uzaklaÅŸtırdı" unassigned_report: "%{name} %{target} ÅŸikayetinin atamasını geri aldı" + unsensitive_account: "%{name}, %{target} kiÅŸisinin medyasını hassas olarak iÅŸaretlemedi" unsilence_account: "%{name} %{target}'in hesabının susturmasını kaldırdı" unsuspend_account: "%{name} %{target}'in hesabının uzaklaÅŸtırmasını kaldırdı" update_announcement: "%{name}, %{target} duyurusunu güncelledi" update_custom_emoji: "%{name} %{target} emojiyi güncelledi" + update_domain_block: "%{name}, %{target} için alan adı engelini güncelledi" update_status: "%{name}, %{target} kullanıcısının durumunu güncelledi" deleted_status: "(silinmiÅŸ durum)" empty: Kayıt bulunamadı. @@ -252,7 +314,7 @@ tr: title: Yeni duyuru published_msg: Duyuru baÅŸarıyla yayınlandı! scheduled_for: "%{time} için zamanlandı" - scheduled_msg: Duyuru yayınlanmak üzere planlandı! + scheduled_msg: Duyuru yayınlanmak üzere zamanlandı! title: Duyurular unpublished_msg: Duyuru baÅŸarıyla yayından kaldırıldı! updated_msg: Duyuru baÅŸarıyla güncellendi! @@ -262,8 +324,8 @@ tr: copied_msg: Emojinin yerel kopyası baÅŸarıyla oluÅŸturuldu copy: Kopyala copy_failed_msg: Bu emojinin yerel bir kopyası oluÅŸturulamadı - create_new_category: Yeni kategori ekle - created_msg: Emoji baÅŸarıyla oluÅŸturuldu! + create_new_category: Yeni kategori oluÅŸtur + created_msg: İfade baÅŸarıyla oluÅŸturuldu! delete: Sil destroyed_msg: Emojo baÅŸarıyla yok edildi! disable: Devre dışı bırak @@ -278,6 +340,7 @@ tr: listed: Listelenen new: title: Yeni özel emoji ekle + not_permitted: Bu iÅŸlemi gerçekleÅŸtirme izniniz yok overwrite: Üzerine yaz shortcode: Kısa kod shortcode_hint: En az 2 karakter, sadece alfanümerik karakterler ve alt çizgiler @@ -293,8 +356,8 @@ tr: backlog: bekleyen iÅŸler config: Yapılandırma feature_deletions: Hesap silme - feature_invites: Davet linkleri - feature_profile_directory: Profil dizini + feature_invites: Davet baÄŸlantıları + feature_profile_directory: Profil Dizini feature_registrations: Kayıtlar feature_relay: Federasyon aktarıcısı feature_spam_check: Anti-spam @@ -311,7 +374,7 @@ tr: space: Alan kullanımı title: Kontrol Paneli total_users: toplam kullanıcı - trends: Trendler + trends: Gündemler week_interactions: bu haftaki etkileÅŸimler week_users_active: bu hafta aktif week_users_new: bu hafta kullanıcılar @@ -376,6 +439,7 @@ tr: instances: by_domain: Alan adı delivery_available: Teslimat mevcut + empty: Alan adı bulunamadı. known_accounts: one: "%{count} bilinen hesap" other: "%{count} bilinen hesap" @@ -399,6 +463,21 @@ tr: expired: Süresi dolmuÅŸ title: Filtre title: Davetler + ip_blocks: + add_new: Kural oluÅŸtur + created_msg: Yeni IP kuralı baÅŸarıyla eklendi + delete: Sil + expires_in: + '1209600': 2 hafta + '15778476': 6 ay + '2629746': 1 ay + '31556952': 1 yıl + '86400': 1 gün + '94670856': 3 yıl + new: + title: Yeni IP kuralı oluÅŸtur + no_ip_block_selected: Hiçbiri seçilmediÄŸinden hiçbir IP kuralı deÄŸiÅŸtirilmedi + title: IP kuralları pending_accounts: title: Bekleyen hesaplar (%{count}) relationships: @@ -476,7 +555,7 @@ tr: domain_blocks: all: Herkes için disabled: Hiç kimseye - title: Alan adı bloklarını göster + title: Engellenen alan adlarını göster users: Oturum açan yerel kullanıcılara domain_blocks_rationale: title: Gerekçeyi göster @@ -547,7 +626,7 @@ tr: title: Ön inceleme yapmadan etiketlerin trend olmasına izin ver trends: desc_html: Åžu anda trend olan ve daha önce incelenen etiketleri herkese açık olarak göster - title: Trend etiketler + title: Gündem etiketleri site_uploads: delete: Yüklenen dosyayı sil destroyed_msg: Site yüklemesi baÅŸarıyla silindi! @@ -572,7 +651,7 @@ tr: context: İçerik directory: Dizinde in_directory: Dizinde %{count} - last_active: Son aktivite + last_active: Son etkinlik most_popular: En popüler most_recent: En yeni name: Etiket @@ -594,8 +673,8 @@ tr: body: Yeni hesabın detayları aÅŸağıdadır. Bu baÅŸvuruyu onaylayabilir ya da reddedebilirsiniz. subject: "%{instance} üzerinde gözden geçirmek için yeni hesap (%{username})" new_report: - body: "%{reporter} %{target}'i ÅŸikayet etti" - body_remote: "%{domain}'den birisi %{target}'i ÅŸikayet etti" + body: "%{reporter}, %{target} kiÅŸisini bildirdi" + body_remote: "%{domain} alan adından birisi %{target} kiÅŸisini bildirdi" subject: "%{instance} için yeni ÅŸikayet (#%{id})" new_trending_tag: body: "#%{name} etiketi bugün trend, ancak daha önce incelenmedi. Siz izin vermediÄŸiniz sürece herkese açık olarak gösterilmeyecek, ya da bir daha asla hakkında bir ÅŸey duymamak için olduÄŸu ÅŸekliyle formu kaydedin." @@ -622,9 +701,9 @@ tr: application_mailer: notification_preferences: E-posta tercihlerini deÄŸiÅŸtir salutation: "%{name}," - settings: 'E-mail tercihlerini deÄŸiÅŸtir: %{link}' + settings: 'E-posta tercihlerini deÄŸiÅŸtir: %{link}' view: 'Görüntüle:' - view_profile: Profili Görüntüle + view_profile: Profili görüntüle view_status: Durumu görüntüle applications: created: Uygulama baÅŸarıyla oluÅŸturuldu @@ -636,32 +715,35 @@ tr: your_token: EriÅŸim belirteciniz auth: apply_for_account: Davet et - change_password: Parola - checkbox_agreement_html: <a href="%{rules_path}" target="_blank">sunucu kuralları</a> ve<a href="%{terms_path}" target="_blank">hizmet ÅŸartlarını</a> kabul ediyorum + change_password: Åžifre + checkbox_agreement_html: <a href="%{rules_path}" target="_blank">Sunucu kurallarını</a> ve <a href="%{terms_path}" target="_blank">hizmet ÅŸartlarını</a> kabul ediyorum checkbox_agreement_without_rules_html: <a href="%{terms_path}" target="_blank">Hizmet ÅŸartlarını</a> kabul ediyorum delete_account: Hesabı sil - delete_account_html: Hesabınızı silmek isterseniz, <a href="%{path}">buradan devam edebilirsiniz</a>. Sizden onay istenecektir. + delete_account_html: Hesabınızı silmek isterseniz, <a href="%{path}">buradan devam edebilirsiniz </a>. Onaylamanız istenecektir. description: - prefix_invited_by_user: "@%{name} sizi Mastodon'un bu sunucusuna katılmaya davet ediyor!" + prefix_invited_by_user: "@%{name} sizi bu Mastodon sunucusuna katılmaya davet ediyor!" prefix_sign_up: Bugün Mastodon'a kaydolun! suffix: Bir hesapla, kiÅŸileri takip edebilir, güncellemeler gönderebilir, herhangi bir Mastodon sunucusundan kullanıcılarla mesaj alışveriÅŸinde bulunabilir ve daha birçok ÅŸey yapabilirsin! - didnt_get_confirmation: Hesap doÄŸrulama mailini almadınız mı? - forgot_password: Parolanızı unuttunuz mu? + didnt_get_confirmation: DoÄŸrulama talimatlarını almadınız mı? + dont_have_your_security_key: Güvenlik anahtarınız yok mu? + forgot_password: Åžifrenizi mi unuttunuz? invalid_reset_password_token: Parola sıfırlama belirteci geçersiz veya süresi dolmuÅŸ. Lütfen yeni bir tane talep edin. - login: GiriÅŸ yap - logout: Çıkış - migrate_account: Farklı bir hesaba taşının + link_to_otp: Telefonunuzdan iki adımlı bir kod veya bir kurtarma kodu girin + link_to_webauth: Güvenlik anahtarı cihazınızı kullanın + login: Oturum aç + logout: Oturumu kapat + migrate_account: Farklı bir hesaba taşıyın migrate_account_html: Bu hesabı baÅŸka bir hesaba yönlendirmek istiyorsanız, <a href="%{path}">buradan yapılandırabilirsiniz</a>. - or_log_in_with: Veya giriÅŸ yapın + or_log_in_with: 'Veya ÅŸununla oturum açın:' providers: cas: CAS saml: SAML - register: Üye ol + register: Kaydol registration_closed: "%{instance} yeni üyeler kabul etmemektedir" - resend_confirmation: DoÄŸrulama mailini tekrar gönder - reset_password: Parolayı deÄŸiÅŸtir - security: Kimlik bilgileri - set_new_password: Yeni parola oluÅŸtur + resend_confirmation: Onaylama talimatlarını tekrar gönder + reset_password: Åžifreyi sıfırla + security: Güvenlik + set_new_password: Yeni ÅŸifre belirle setup: email_below_hint_html: EÄŸer aÅŸağıdaki e-posta adresi yanlışsa, onu burada deÄŸiÅŸtirebilir ve yeni bir doÄŸrulama e-postası alabilirsiniz. email_settings_hint_html: Onaylama e-postası %{email} adresine gönderildi. EÄŸer bu e-posta adresi doÄŸru deÄŸilse, hesap ayarlarından deÄŸiÅŸtirebilirsiniz. @@ -672,9 +754,12 @@ tr: functional: Hesabınız tamamen kullanıma hazır. pending: BaÅŸvurunuz personelimiz tarafından gözden geçirilmeyi beklemektedir. Bu biraz zaman alabilir. BaÅŸvurunuz onaylanırsa bir e-posta alacaksınız. redirecting_to: Hesabınız aktif deÄŸil çünkü ÅŸu anda %{acct} adresine yönlendirilmektedir. + too_fast: Form çok hızlı gönderildi, tekrar deneyin. trouble_logging_in: Oturum açarken sorun mu yaşıyorsunuz? + use_security_key: Güvenlik anahtarını kullan authorize_follow: already_following: Bu hesabı zaten takip ediyorsunuz + already_requested: Bu hesaba zaten takip isteÄŸi gönderdiniz error: Uzak hesap aranırken bir hata oluÅŸtu follow: Takip et follow_request: 'Åžuna takip isteÄŸi gönderdiniz:' @@ -683,15 +768,20 @@ tr: close: Ya da, sadece bu pencereyi kapatabilirsiniz. return: Kullanıcının profilini göster web: Web'e git - title: "%{acct}'i takip et" + title: "%{acct} takip et" challenge: confirm: Devam et hint_html: "<strong>İpucu:</strong> Önümüzdeki saat boyunca sana parolanı sormayacağız." - invalid_password: Geçersiz parola - prompt: Devam etmek parolayı doÄŸrulayın + invalid_password: Geçersiz ÅŸifre + prompt: Devam etmek için ÅŸifreyi doÄŸrulayın + crypto: + errors: + invalid_key: geçerli bir Ed25519 veya Curve25519 anahtarı deÄŸil + invalid_signature: geçerli bir Ed25519 imzası deÄŸil date: formats: - default: "%b %d, %Y" + default: "%d %b %Y" + with_month_name: "%d %B %Y" datetime: distance_in_words: about_x_hours: "%{count}sa" @@ -724,7 +814,7 @@ tr: username_available: Kullanıcı adınız tekrar kullanılabilir olacaktır username_unavailable: Kullanıcı adınız kullanılamaz kalacaktır directories: - directory: Profil dizini + directory: Profil Dizini explanation: Kullanıcıları ilgi alanlarına göre keÅŸfedin explore_mastodon: "%{title} sunucusunu keÅŸfet" domain_validator: @@ -753,14 +843,15 @@ tr: download: ArÅŸivinizi indirin hint_html: "<strong>Tootlarınızın ve yüklediÄŸiniz ortamların</strong> bir arÅŸivini talep edebilirsiniz. Dışa aktarılan veriler, herhangi bir uyumlu yazılım tarafından okunabilen ActivityPub formatında olacaktır. Her 7 günde bir arÅŸiv talep edebilirsiniz." in_progress: ArÅŸivinizi derliyoruz... - request: ArÅŸiv isteÄŸi + request: ArÅŸivinizi isteyin size: Boyut - blocks: Engelledikleriniz + blocks: Engellediklerin + bookmarks: Yer imleri csv: CSV - domain_blocks: Alan adı blokları + domain_blocks: Alan adı engelleri lists: Listeler - mutes: Susturduklarınız - storage: Ortam deposu + mutes: Sessize aldıkların + storage: Medya depolaması featured_tags: add_new: Yeni ekle errors: @@ -788,7 +879,7 @@ tr: developers: GeliÅŸtiriciler more: Daha Fazla… resources: Kaynaklar - trending_now: Trendler + trending_now: Åžu an gündemde generic: all: Tümü changes_saved_msg: DeÄŸiÅŸiklikler baÅŸarıyla kaydedildi! @@ -803,8 +894,8 @@ tr: html_validator: invalid_markup: 'geçersiz HTML markup içermektedir: %{error}' identity_proofs: - active: Aktif - authorize: Evet, yetkilendir + active: Etkin + authorize: Evet, izin ver authorize_connection_prompt: Bu kriptolu baÄŸlantıyı yetkilendir? errors: failed: Kriptolu baÄŸlantı baÅŸarısız oldu. Lütfen %{provider} üzerinden tekrar deneyin. @@ -818,8 +909,10 @@ tr: inactive: Pasif publicize_checkbox: 'Ve bunu tootla:' publicize_toot: 'İspatlandı! Ben %{service} üzerinde %{username}: %{url}' + remove: Hesaptan kanıtı kaldır + removed: Kanıt hesaptan baÅŸarıyla kaldırıldı status: DoÄŸrulama durumu - view_proof: Kanıt görüntüle + view_proof: Kanıtı görüntüle imports: modes: merge: BirleÅŸtir @@ -830,6 +923,7 @@ tr: success: Verileriniz baÅŸarıyla yüklendi ve zaman içinde iÅŸlenecek types: blocking: Engellenenler listesi + bookmarks: Yer imleri domain_blocking: Alan adı engelleme listesi following: Takip edilenler listesi muting: Susturulanlar listesi @@ -846,8 +940,8 @@ tr: '604800': 1 hafta '86400': 1 gün expires_in_prompt: Asla - generate: OluÅŸtur - invited_by: 'Tarafından davet edildi:' + generate: Davet baÄŸlantısı oluÅŸtur + invited_by: 'Davet edildiniz:' max_uses: one: 1 kullanım other: "%{count} kullanım" @@ -859,11 +953,12 @@ tr: title: İnsanları davet et lists: errors: - limit: Maksimum liste miktarına ulaÅŸtınız + limit: En yüksek liste sayısına ulaÅŸtınız media_attachments: validations: - images_and_video: Halihazırda görsel içeren bir gönderiye video ekleyemezsiniz - too_many: 4'ten fazla dosya ekleyemezsiniz + images_and_video: Zaten resim içeren bir duruma video eklenemez + not_ready: İşlemi tamamlanmamış dosyalar eklenemez. Birazdan tekrar deneyin! + too_many: 4'ten fazla dosya eklenemiyor migrations: acct: Taşındı cancel: Yönlendirmeyi iptal et @@ -883,6 +978,7 @@ tr: on_cooldown: Son zamanlarda hesabınızı taşıdınız. Bu iÅŸlev %{count} gün içinde tekrar kullanılabilir olacaktır. past_migrations: GeçmiÅŸ taşınmalar proceed_with_move: Takipçileri taşı + redirected_msg: Hesabınız artık %{acct} adresine yönlendiriliyor. redirecting_to: Hesabınız %{acct} hesabına yönlendirilmektedir. set_redirect: Yönlendirme ayarla warning: @@ -895,41 +991,45 @@ tr: other_data: BaÅŸka bir veri otomatik olarak taşınmayacaktır redirect: Mevcut hesabınızın profili bir yönlendirme bildirimi ile güncellenecek ve aramaların dışında tutulacaktır moderation: - title: Yönetim + title: Denetim + move_handler: + carry_blocks_over_text: Bu kullanıcı engellediÄŸiniz %{acct} adresinden taşındı. + carry_mutes_over_text: Bu kullanıcı sessize aldığınız %{acct} adresinden taşındı. + copy_account_note_text: 'Bu kullanıcı %{acct} adresinden taşındı, iÅŸte onlarla ilgili önceki notlarınız:' notification_mailer: digest: action: Tüm bildirimleri görüntüle body: Son ziyaretiniz olan %{since}'den beri'da kaçırdığınız ÅŸeylerin özeti mention: "%{name} senden bahsetti:" new_followers_summary: - one: Yeni bir takipçiniz var! - other: Yeni %{count} takipçiniz var! + one: Ayrıca, uzaktayken yeni bir takipçi kazandınız! YaÅŸasın! + other: Ayrıca, uzaktayken %{count} yeni takipçi kazandınız! İnanılmaz! subject: - one: "Son ziyaretinizden beri 1 yeni bildiriminiz var \U0001F418" - other: "Son ziyaretinizden beri %{count} yeni bildiriminiz var \U0001F418" + one: "Son ziyaretinizden bu yana 1 yeni bildirim \U0001F418" + other: "Son ziyaretinizden bu yana %{count} yeni bildirim \U0001F418" title: Senin yokluÄŸunda... favourite: - body: "%{name} durumunuzu favorilere ekledi:" - subject: "%{name} favorilere ekledi" - title: Yeni favori + body: "%{name} durumunu beÄŸendi:" + subject: "%{name} durumunu beÄŸendi" + title: Yeni beÄŸeni follow: - body: "%{name} sizi takip etmeye baÅŸladı!" - subject: "%{name} sizi takip etmeye baÅŸladı" + body: "%{name} artık seni takip ediyor!" + subject: "%{name} artık seni takip ediyor" title: Yeni takipçi follow_request: action: Takip isteklerini yönet - body: "%{name} size takip isteÄŸi gönderdi" - subject: 'Takip isteÄŸi: %{name}' + body: "%{name} sana takip isteÄŸi gönderdi" + subject: 'Bekleyen takipçi: %{name}' title: Yeni takip isteÄŸi mention: - action: Yanıt - body: "%{name} sizden bahsetti:" - subject: "%{name} sizden bahsetti" + action: Yanıtla + body: "%{name} senden bahsetti:" + subject: "%{name} senden bahsetti" title: Yeni bahsetme reblog: - body: "%{name} durumunuzu boost etti:" - subject: "%{name} durumunuzu boost etti" - title: Yeni gönderi + body: "%{name} durumunuzu boostladı:" + subject: "%{name} durumunuzu boostladı" + title: Yeni boost notifications: email_events: E-posta bildirimi gönderilecek etkinlikler email_events_hint: 'Bildirim almak istediÄŸiniz olayları seçin:' @@ -939,15 +1039,23 @@ tr: decimal_units: format: "%n%u" units: - billion: B - million: M - quadrillion: Q - thousand: K - trillion: T + billion: Mr + million: Mn + quadrillion: Kn + thousand: Bn + trillion: Tn + otp_authentication: + code_hint: Onaylamak için authenticator uygulamanız tarafından oluÅŸturulan kodu girin + description_html: Bir authenticator uygulamasını kullanarak <strong>iki adımlı kimlik doÄŸrulamayı</strong> etkinleÅŸtirirseniz, giriÅŸ yapmak için telefonunuzun elinizde olması gerekir ve telefonunuz giriÅŸ yapmanız için kodlar oluÅŸturur. + enable: EtkinleÅŸtir + instructions_html: "<strong>Bu QR kodunu Google Authenticator'a veya telefonunuzdaki benzer bir TOTP uygulamasına taratın.</strong> Bundan sonra, bu uygulama giriÅŸ yaparken girmeniz gereken kodu üretecektir." + manual_instructions: 'QR kodunu taratamıyorsanız ve elle girmeniz gerekiyorsa, buradaki gizli düz metni girebilirsiniz:' + setup: Yapılandır + wrong_code: Girilen kod geçersiz! Sunucu zamanı ve cihaz zamanı doÄŸru mu? pagination: newer: Daha yeni next: Sonraki - older: Daha Eski + older: Daha eski prev: Önceki truncate: "…" polls: @@ -971,47 +1079,48 @@ tr: unrecognized_emoji: tanınan bir emoji deÄŸil relationships: activity: Hesap etkinliÄŸi - dormant: Atıl + dormant: Uykuda + follow_selected_followers: Seçili takipçileri takip et followers: Takipçiler following: Takip edilenler invited: Davet edildi - last_active: Son aktivite - most_recent: En son + last_active: Son etkinlik + most_recent: En yeni moved: Taşındı - mutual: Ortak - primary: Birincil + mutual: Karşılıklı + primary: Ana relationship: İliÅŸki - remove_selected_domains: Seçili alan adlarından tüm takipçileri kaldır + remove_selected_domains: Seçilen alan adların tüm takipçileri kaldır remove_selected_followers: Seçili takipçileri kaldır remove_selected_follows: Seçili kullanıcıları takip etmeyi bırak status: Hesap durumu remote_follow: - acct: Takip edeceÄŸiniz kiÅŸiyi kullaniciadi@sunuculinki ÅŸeklinde giriniz - missing_resource: Hesabınız için yönlendirme linki bulunamadı + acct: İşlem yapmak istediÄŸiniz kullaniciadi@alanadini girin + missing_resource: Hesabınız için gerekli yönlendirme URL'si bulunamadı no_account_html: Hesabınız yok mu? <a href='%{sign_up_path}' target='_blank'>Buradan kaydolabilirsiniz</a> - proceed: Takip onayı + proceed: Takip etmek için devam edin prompt: Bu kullanıcıyı takip etmek istediÄŸinize emin misiniz? reason_html: "<strong>Bu adım neden gerekli?</strong><code>%{instance}</code> kayıtlı olduÄŸunuz sunucu olmayabilir, bu yüzden önce sizi kendi sunucunuza yönlendirmemiz gerekmektedir." remote_interaction: favourite: - proceed: Favorilere eklemek için ilerle - prompt: 'Bu tootu favorilerinize eklemek istiyorsunuz:' + proceed: BeÄŸenmek için devam edin + prompt: 'Bu tootu beÄŸenmek istiyorsunuz:' reblog: - proceed: Yinelemek için ilerle - prompt: 'Bu tootu yinelemek istiyorsunuz:' + proceed: Boostlamak için devam edin + prompt: 'Bu tootu boostlamak istiyorsunuz:' reply: - proceed: Cevap vermek için ilerle - prompt: 'Bu toota cevap vermek istiyorsunuz:' + proceed: Yanıtlamak için devam edin + prompt: 'Bu tootu yanıtlamak istiyorsunuz:' scheduled_statuses: over_daily_limit: O gün için %{limit} zamanlanmış toot sınırını aÅŸtınız over_total_limit: "%{limit} zamanlanmış toot sınırını aÅŸtınız" too_soon: Programlanan tarih bugünden ileri bir tarihte olmalıdır sessions: - activity: Son aktivite + activity: Son etkinlik browser: Tarayıcı browsers: alipay: Alipay - blackberry: BlackBerry + blackberry: Blackberry chrome: Chrome edge: Microsoft Edge electron: Electron @@ -1027,9 +1136,9 @@ tr: safari: Safari uc_browser: UC Browser weibo: Weibo - current_session: Åžu anki oturum - description: "%{platform} üzerinde %{browser}" - explanation: Bunlar ÅŸu anda Mastodon hesabınızda oturum açan web tarayıcılarıdır. + current_session: Geçerli oturum + description: "%{platform} - %{browser}" + explanation: Bunlar, Mastodon hesabınızda ÅŸu anda oturum açmış web tarayıcılarıdır. ip: IP platforms: adobe_air: Adobe Air @@ -1038,13 +1147,13 @@ tr: chrome_os: ChromeOS firefox_os: Firefox OS ios: iOS - linux: GNU/Linux - mac: Mac + linux: Linux + mac: macOS other: bilinmeyen platform windows: Windows - windows_mobile: Windows Mobil + windows_mobile: Windows Mobile windows_phone: Windows Phone - revoke: İptal + revoke: İptal Et revoke_success: Oturum baÅŸarıyla iptal edildi title: Oturumlar settings: @@ -1052,22 +1161,23 @@ tr: account_settings: Hesap ayarları aliases: Hesap takma adları appearance: Görünüm - authorized_apps: Yetkilendirilen uygulamalar + authorized_apps: Yetkili uygulamalar back: Mastodon'a geri dön delete: Hesap silme development: GeliÅŸtirme edit_profile: Profili düzenle - export: Dışa aktar - featured_tags: Öne çıkan hashtag'ler - identity_proofs: Kimlik belgesi + export: Veriyi dışa aktar + featured_tags: Öne çıkan etiketler + identity_proofs: Kimlik kanıtları import: İçe aktar - import_and_export: İçe al ve dışarı aktar + import_and_export: İçe ve dışa aktar migrate: Hesap taşıma - notifications: Bildirim + notifications: Bildirimler preferences: Tercihler profile: Profil relationships: Takip edilenler ve takipçiler - two_factor_authentication: İki-faktörlü doÄŸrulama + two_factor_authentication: İki adımlı doÄŸrulama + webauthn_authentication: Güvenlik anahtarları spam_check: spam_detected: Bu otomatik bir ÅŸikayettir. Spam tespit edildi. statuses: @@ -1077,16 +1187,18 @@ tr: other: "%{count} ses" description: 'Ekli: %{attached}' image: - one: "%{count} görsel" - other: "%{count} görsel" + one: "%{count} resim" + other: "%{count} resim" video: one: "%{count} video" other: "%{count} video" - boosted_from_html: "%{acct_link} den yinelendi" + boosted_from_html: "%{acct_link} kiÅŸisinden boostladı" content_warning: 'İçerik uyarısı: %{warning}' disallowed_hashtags: one: 'izin verilmeyen bir etiket içeriyordu: %{tags}' other: 'izin verilmeyen hashtag''leri içeriyordu: %{tags}' + errors: + in_reply_not_found: Yanıtlamaya çalıştığınız durum yok gibi görünüyor. language_detection: Dili otomatik olarak algıla open_in_web: Web sayfasında aç over_character_limit: "%{max} karakter limiti aşıldı" @@ -1094,7 +1206,7 @@ tr: limit: Hali hazırda maksimum sayıda tootu sabitlediniz ownership: BaÅŸkasının tootu sabitlenemez private: Halka açık olmayan toot sabitlenemez - reblog: Bir yineleme sabitlenemez + reblog: Bir boost sabitlenemez poll: total_people: one: "%{count} kiÅŸi" @@ -1102,9 +1214,11 @@ tr: total_votes: one: "%{count} oy" other: "%{count} oy" - vote: Oy - show_more: Daha fazla - show_thread: Mesaj dizisini göster + vote: Oy Ver + show_more: Daha fazlasını göster + show_newer: Yenileri göster + show_older: Eskileri göster + show_thread: Konuyu göster sign_in_to_participate: Sohbete katılmak için oturum açın title: '%{name}: "%{quote}"' visibilities: @@ -1116,7 +1230,7 @@ tr: unlisted_long: Herkes görebilir fakat herkese açık zaman tünellerinde listelenmez stream_entries: pinned: SabitlenmiÅŸ toot - reblogged: boost edildi + reblogged: boostladı sensitive_content: Hassas içerik tags: does_not_match_previous_name: önceki adla eÅŸleÅŸmiyor @@ -1209,32 +1323,38 @@ tr: mastodon-light: Mastodon (Açık) time: formats: - default: "%b %d, %Y, %H:%M" + default: "%d %b %Y %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Onaylamak için kimlik doÄŸrulama uygulamanızın oluÅŸturduÄŸu kodu giriniz - description_html: EÄŸer <strong>iki-faktörlü kimlik doÄŸrulamayı</strong> aktif ederseniz, giriÅŸ yaparken sizin için giriÅŸ kodu üreten telefonunuza ihtiyaç duyacaksınız. - disable: Devre dışı bırak - enable: AktifleÅŸtir + add: Ekle + disable: 2FA'yı devre dışı bırak + disabled_success: İki adımlı kimlik doÄŸrulama baÅŸarıyla devre dışı bırakıldı + edit: Düzenle enabled: İki adımlı kimlik doÄŸrulama etkin - enabled_success: İki-faktörlü kimlik doÄŸrulama baÅŸarıyla aktif edildi - generate_recovery_codes: Kurtarma Kodlarını OluÅŸtur - instructions_html: <strong>Bu QR kodunu, telefonunuzdaki <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2">Google Authenticator</a> veya benzer bir TOTP uygulamasıyla taratınız</strong>. Bundan sonra giriÅŸ yaparken uygulamanın ürettiÄŸi kodu kullanarak giriÅŸ yapacaksınız. + enabled_success: İki adımlı kimlik doÄŸrulama baÅŸarıyla etkinleÅŸtirildi + generate_recovery_codes: Kurtarma kodları oluÅŸtur lost_recovery_codes: Kurtarma kodları telefonunuzu kaybettiÄŸiniz durumlarda hesabınıza eriÅŸim yapabilmenize olanak tanır. EÄŸer kurtarma kodlarınızı kaybettiyseniz burada tekrar oluÅŸturabilirsiniz. Eski kurtarma kodlarınız geçersiz hale gelecektir. - manual_instructions: 'EÄŸer QR kodunu taratamıyorsanız ve elle giriÅŸ yapmanız gerekiyorsa buradaki gizli düz metni girebilirsiniz:' + methods: İki adımlı doÄŸrulama yöntemleri + otp: Authenticator uygulaması recovery_codes: Kurtarma kodlarını yedekle - recovery_codes_regenerated: Kurtarma kodları baÅŸarıyla oluÅŸturuldu + recovery_codes_regenerated: Kurtarma kodları baÅŸarıyla yeniden oluÅŸturuldu recovery_instructions_html: 'EÄŸer telefonunuza eriÅŸiminizi kaybederseniz, aÅŸağıdaki kurtarma kodlarından birini kullanarak hesabınıza giriÅŸ yapabilirsiniz. Kurtarma kodlarınızı güvenli halde tutunuz. ÖrneÄŸin: kodların çıktısını alıp diÄŸer önemli belgeleriniz ile birlikte saklayabilirsiniz.' - setup: Kuruluma baÅŸla - wrong_code: GirdiÄŸiniz kod geçersiz! Telefonunuzun saati geri/ileri kalmış olabilir. + webauthn: Güvenlik anahtarları user_mailer: backup_ready: - explanation: Mastodon hesabınızın tam bir yedeÄŸini istediniz. Åžimdi indirmeye hazır! + explanation: Mastodon hesabınızın tam yedeÄŸini istemiÅŸtiniz. Åžimdi indirilebilir durumda! subject: ArÅŸiviniz indirilmeye hazır title: ArÅŸiv paketlemesi + sign_in_token: + details: 'İşte bu giriÅŸimin ayrıntıları:' + explanation: 'Tanınmayan bir IP adresinden hesabınızda oturum açma denemesi tespit ettik. Bu sizseniz, lütfen oturum açma sorgulama sayfasına aÅŸağıdaki güvenlik kodunu girin:' + further_actions: 'Bu siz deÄŸildiyseniz, lütfen ÅŸifrenizi deÄŸiÅŸtirin ve hesabınızda iki faktörlü kimlik doÄŸrulamayı etkinleÅŸtirin. Bunu buradan yapabilirsiniz:' + subject: Lütfen oturum açma giriÅŸimini onaylayın + title: Oturum açma giriÅŸimi warning: explanation: disable: Hesabınız donmuÅŸken, hesap verileriniz bozulmadan kalır, ancak kilidi açılıncaya kadar herhangi bir iÅŸlem gerçekleÅŸtiremezsiniz. + sensitive: YüklediÄŸiniz medya dosyalarınız ve baÄŸlantılı medyanız hassas olarak deÄŸerlendirilecektir. silence: Hesabınız sınırlı iken, yalnızca sizi takip eden kiÅŸiler bu sunucuda tootlarınızı görecek ve çeÅŸitli halka açık listelerin dışında tutulabilirsiniz. Ancak, diÄŸerleri hala sizi manuel olarak takip edebilir. suspend: Hesabınız askıya alındı ve tüm tootlarınız ve yüklediÄŸiniz medya dosyalarınız bu sunucudan ve takipçilerinizin bulunduÄŸu sunuculardan geri alınamaz ÅŸekilde kaldırıldı. get_in_touch: "%{instance} çalışanlarıyla iletiÅŸim kurmak için bu e-postayı yanıtlayabilirsiniz." @@ -1243,15 +1363,17 @@ tr: subject: disable: "%{acct} hesabınız donduruldu" none: "%{acct} için uyarı" + sensitive: Hesabınızdan yayınlanan %{acct} medyanız hassas olarak iÅŸaretlendi silence: "%{acct} hesabınız sınırlandırıldı" suspend: "%{acct} hesabınız askıya alındı" title: disable: Hesap donduruldu none: Uyarı + sensitive: Medyanız hassas olarak iÅŸaretlendi silence: Hesap sınırlandırıldı suspend: Hesap askıya alındı welcome: - edit_profile_action: Profil ayarla + edit_profile_action: Profil kurulumu edit_profile_step: Bir avatar veya baÅŸlık yükleyerek, ekran adınızı deÄŸiÅŸtirerek ve daha fazlasını yaparak profilinizi kiÅŸiselleÅŸtirebilirsiniz. Yeni takipçileri sizi takip etmelerine izin verilmeden önce incelemek isterseniz, hesabınızı kilitleyebilirsiniz. explanation: İşte sana baÅŸlangıç için birkaç ipucu final_action: Gönderi yazmaya baÅŸlayın @@ -1268,13 +1390,34 @@ tr: tips: İpuçları title: Gemiye hoÅŸgeldin, %{name}! users: + blocked_email_provider: Bu e-posta saÄŸlayıcısına izin verilmiyor follow_limit_reached: "%{limit} kiÅŸiden daha fazlasını takip edemezsiniz" - invalid_email: E-posta adresiniz geçersiz - invalid_otp_token: İki-faktörlü kodunuz geçersiz + generic_access_help_html: Hesabınıza eriÅŸirken sorun mu yaşıyorsunuz? Yardım için %{email} ile iletiÅŸime geçebilirsiniz + invalid_email: E-posta adresi geçersiz + invalid_email_mx: E-posta adresi mevcut görünmüyor + invalid_otp_token: Geçersiz iki adımlı doÄŸrulama kodu invalid_sign_in_token: Geçersiz güvenlik kodu otp_lost_help_html: Her ikisine de eriÅŸiminizi kaybettiyseniz, %{email} ile irtibata geçebilirsiniz seamless_external_login: Harici bir servis aracılığıyla oturum açtınız, bu nedenle parola ve e-posta ayarları mevcut deÄŸildir. - signed_in_as: 'GiriÅŸ yapan:' + signed_in_as: 'Oturum açtı:' + suspicious_sign_in_confirmation: Bu cihazdan daha önce oturum açmamış gibi görünüyorsunuz ve bir süredir oturum açmamışsınız, bu yüzden kimliÄŸinizi doÄŸrulamak için e-posta adresinize bir güvenlik kodu gönderiyoruz. verification: explanation_html: '<strong>Profil meta verisindeki baÄŸlantıların sahibi olarak kendinizi doÄŸrulayabilirsiniz</strong>. Bunun için, link verilen web sitesi Mastodon profilinize geri bir link içermelidir. Geri link bir <code>rel="me"</code> özelliÄŸine sahip <strong>olmalıdır</strong>. BaÄŸlantının metin içeriÄŸi önemli deÄŸildir. İşte bir örnek:' verification: DoÄŸrulama + webauthn_credentials: + add: Yeni güvenlik anahtarı ekle + create: + error: Güvenlik anahtarınızı eklerken bir sorun oluÅŸtu. Lütfen tekrar deneyin. + success: Güvenlik anahtarınız baÅŸarıyla eklendi. + delete: Sil + delete_confirmation: Bu güvenlik anahtarını silmek istediÄŸinizden emin misiniz? + description_html: "<strong>Güvenlik anahtarı kimlik doÄŸrulamasını</strong> etkinleÅŸtirirseniz, giriÅŸ yapmak için güvenlik anahtarlarınızdan birini kullanmanız gerekir." + destroy: + error: Güvenlik anahtarını silerken bir sorun oluÅŸtu. Lütfen tekrar deneyin. + success: Güvenlik anahtarınız baÅŸarıyla silindi. + invalid_credential: Geçersiz güvenlik anahtarı + nickname_hint: Yeni güvenlik anahtarınızın takma adını girin + not_enabled: Henüz WebAuthn'u etkinleÅŸtirmediniz + not_supported: Bu tarayıcı güvenlik anahtarlarını desteklemiyor + otp_required: Güvenlik anahtarlarını kullanmak için lütfen önce iki adımlı kimlik doÄŸrulamayı etkinleÅŸtirin. + registered_on: "%{date} tarihinde kaydoldu" diff --git a/config/locales/tt.yml b/config/locales/tt.yml new file mode 100644 index 0000000000000000000000000000000000000000..e35b5da21c98ee1818e6b3c2c21c04c5152f8770 --- /dev/null +++ b/config/locales/tt.yml @@ -0,0 +1,12 @@ +--- +tt: + errors: + '400': The request you submitted was invalid or malformed. + '403': You don't have permission to view this page. + '404': The page you are looking for isn't here. + '406': This page is not available in the requested format. + '410': The page you were looking for doesn't exist here anymore. + '422': + '429': Too many requests + '500': + '503': The page could not be served due to a temporary server failure. diff --git a/config/locales/ug.yml b/config/locales/ug.yml index 7b709a35e9b2c59e307df1e51c5a885401f8ae50..779d4d226fc6557c606f93587371c9421b0f042a 100644 --- a/config/locales/ug.yml +++ b/config/locales/ug.yml @@ -10,11 +10,3 @@ ug: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 7b13c40c0ef6e9e35acf1c1b347ff1290655f60b..dee947dc68476ced8f10f4a56d64d5984c864da5 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -21,7 +21,9 @@ uk: federation_hint_html: З обліковим запиÑом на %{instance} ви зможете Ñлідкувати за людьми на будь-Ñкому Ñервері Mastodon та поза ним. get_apps: Спробуйте мобільний додаток hosted_on: Mastodon розміщено на %{domain} - instance_actor_flash: Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” віртуальною оÑобою, Ñка викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ñамого Ñервера, а не певного кориÑтувача. Він викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ± федерації Ñ– не повинен бути заблокований, Ñкщо тільки ви не хочете заблокувати веÑÑŒ Ñервер, у цьому випадку ви повинні ÑкориÑтатиÑÑ Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñм домену. + instance_actor_flash: 'Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” віртуальною оÑобою, Ñка викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ñамого Ñервера, а не певного кориÑтувача. Він викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ± федерації Ñ– не повинен бути заблокований, Ñкщо тільки ви не хочете заблокувати веÑÑŒ Ñервер, у цьому випадку ви повинні ÑкориÑтатиÑÑ Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñм домену. + +' learn_more: ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ privacy_policy: Політика приватноÑті see_whats_happening: ПоглÑньте, що відбуваєтьÑÑ @@ -205,6 +207,7 @@ uk: whitelisted: У білому ÑпиÑку action_logs: action_types: + assigned_to_self_report: Призначити звіт change_email_user: Змінити електронну пошту Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача confirm_user: Підтвердити кориÑтувача create_account_warning: Створити Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ @@ -220,10 +223,12 @@ uk: destroy_domain_block: Видалити Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ destroy_email_domain_block: Видалити Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÑˆÑ‚Ð¾Ð²Ð¾Ð³Ð¾ домену destroy_status: Видалити поÑÑ‚ + disable_2fa_user: Вимкнути 2FA disable_custom_emoji: Вимкнути кориÑтувацькі емодзі disable_user: Відключити кориÑтувача enable_custom_emoji: Увімкнути кориÑтувацькі емодзі enable_user: Ðктивувати кориÑтувача + memorialize_account: Зробити обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¼ÐµÐ¼Ð¾Ñ€Ñ–Ð°Ð»Ð¾Ð¼ promote_user: Підвищити кориÑтувача remove_avatar_user: Видалити аватар reopen_report: Перевідкрити Ñкаргу @@ -231,6 +236,7 @@ uk: resolve_report: Розв'Ñзати Ñкаргу silence_account: Заглушити обліковий Ð·Ð°Ð¿Ð¸Ñ suspend_account: Призупинити обліковий Ð·Ð°Ð¿Ð¸Ñ + unassigned_report: Видалити Ñкаргу unsilence_account: Розглушити обліковий Ð·Ð°Ð¿Ð¸Ñ unsuspend_account: Розморозити обліковий Ð·Ð°Ð¿Ð¸Ñ update_announcement: Оновити Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ @@ -693,8 +699,11 @@ uk: prefix_sign_up: ЗареєÑтруйтеÑÑ Ð½Ð° Mastodon Ñьогодні! suffix: Маючи обліковий запиÑ, ви зможете підпиÑуватиÑÑ Ð½Ð° людей, публікувати поÑти та лиÑтуватиÑÑ Ð· кориÑтувачами будь-Ñкого Ñервера Mastodon! didnt_get_confirmation: Ви не отримали інÑтрукції з підтвердженнÑ? + dont_have_your_security_key: Ðе маєте ключа безпеки? forgot_password: Забули пароль? invalid_reset_password_token: Токен ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ неправильний або проÑрочений. Спробуйте попроÑити новий. + link_to_otp: Введіть двофакторний код з вашого телефону або код Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + link_to_webauth: ВикориÑтовувати приÑтрій ключа безпеки login: Увійти logout: Вийти migrate_account: Переїхати на інший обліковий Ð·Ð°Ð¿Ð¸Ñ @@ -720,6 +729,7 @@ uk: pending: Ваша заÑва очікує на розглÑд нашим перÑоналом. Це може зайнÑти деÑкий чаÑ. Ви отримаєте електронний лиÑÑ‚, Ñкщо ваша заÑва буде Ñхвалена. redirecting_to: Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– неактивний, тому що він перенаправлений до %{acct}. trouble_logging_in: Проблема під Ñ‡Ð°Ñ Ð²Ñ…Ð¾Ð´Ñƒ? + use_security_key: ВикориÑтовувати ключ безпеки authorize_follow: already_following: Ви вже Ñлідкуєте за цим обліковим запиÑом already_requested: Ви вже надіÑлали запит на підпиÑку до цього облікового запиÑу @@ -744,6 +754,7 @@ uk: date: formats: default: "%b %d, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}г" @@ -1012,6 +1023,14 @@ uk: quadrillion: квдрл thousand: Ñ‚Ð¸Ñ trillion: трлн + otp_authentication: + code_hint: Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ код, згенерований додатком аутентифікатора + description_html: При увімкненні <strong>двофакторної аутентифікації</strong>, вхід буде вимагати від Ð’Ð°Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ телефона Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ— вхідного коду. + enable: Увімкнути + instructions_html: "<strong>ВідÑкануйте цей QR-код за допомогою Google Authenticator чи іншого TOTP-додатку на Вашому телефоні</strong>. Відтепер додаток буде генерувати коди, Ñкі буде необхідно ввеÑти Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ." + manual_instructions: 'Якщо ви не можете Ñканувати QR-код Ñ– потрібно ввеÑти його вручну, оÑÑŒ він:' + setup: Ðалаштувати + wrong_code: Введений код неправильний! Чи правильно вÑтановлений Ñ‡Ð°Ñ Ð½Ð° Ñервері та приÑтрої? pagination: newer: Ðовіше next: Далі @@ -1136,10 +1155,16 @@ uk: profile: Профіль relationships: ПідпиÑки та підпиÑники two_factor_authentication: Двофакторна Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ + webauthn_authentication: Ключі безпеки spam_check: spam_detected: Це автоматична Ñкарга. Було виÑвлено Ñпам. statuses: attached: + audio: + few: "%{count} аудіозапиÑи" + many: "%{count} аудіозапиÑів" + one: "%{count} аудіозапиÑ" + other: "%{count} аудіозапиÑів" description: 'Прикріплено: %{attached}' image: few: "%{count} зображень" @@ -1209,21 +1234,20 @@ uk: default: "%b %d, %Y, %H:%M" month: "%b %Y" two_factor_authentication: - code_hint: Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ код, згенерований заÑтоÑунком аутентифікатора - description_html: При увімкненні <strong>двофакторної аутентифікації</strong>, вхід буде вимагати від Ð’Ð°Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ð°ÑˆÐ¾Ð³Ð¾ телефона, Ñкий згенерує вхідний код. + add: Додати disable: Вимкнути - enable: Увімкнути + disabled_success: Двофакторна Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð° + edit: Редагувати enabled: Двофакторна Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð° enabled_success: Двофакторна Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÑƒÑпішно увімкнена generate_recovery_codes: Згенерувати коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ - instructions_html: "<strong>ВідÑкануйте цей QR-код за допомогою Google Authenticator чи іншого TOTP-заÑтоÑунку на Вашому телефоні</strong>. З цього моменту він буде генерувати коди, Ñкі буде необхідно ввеÑти Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ." lost_recovery_codes: Коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»Ñють повернути доÑтуп до вашого облікового запиÑу у випадку втрати телефону. Якщо ви втратили ваші коди відновленнÑ, ви можете знову згенерувати Ñ—Ñ… тут. Ваші Ñтарі коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ анульовані. - manual_instructions: 'Якщо Ви не можете відÑканувати QR-код та хочете ввеÑти його вручну, Ñекрет предÑтавлений тут відкритим текÑтом:' + methods: Методи двофакторної авторизації + otp: Програма авторизації recovery_codes: ЗапаÑні коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ recovery_codes_regenerated: Коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно згенеровані recovery_instructions_html: У випадку втрати доÑтупу до вашого телефону ви можете викориÑтати один з нижчевказаних кодів відновленнÑ, щоб повернути доÑтуп до вашого облікового запиÑу. <strong>Тримайте коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñƒ безпеці</strong>, наприклад, роздрукуйте Ñ—Ñ… та зберігайте разом з іншими важливими документами. - setup: Ðалаштувати - wrong_code: Введений код неправильний! Чи правильно вÑтановлений Ñ‡Ð°Ñ Ð½Ð° Ñервері та приÑтрої? + webauthn: Ключі безпеки user_mailer: backup_ready: explanation: Ви робили запит повної резервної копії вашого облікового запиÑу Mastodon. Вона вже готова Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ! @@ -1271,9 +1295,11 @@ uk: tips: Поради title: ЛаÑкаво проÑимо, %{name}! users: + blocked_email_provider: Цей поштовий провайдер не дозволений follow_limit_reached: Ðе можна Ñлідкувати більш ніж за %{limit} людей generic_access_help_html: Ðе вдаєтьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ доÑтуп до облікового запиÑу? Ви можете зв'ÑзатиÑÑ Ð· %{email} Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ invalid_email: Введена адреÑа e-mail неправильна + invalid_email_mx: Вказана електронна адреÑа не Ñ–Ñнує invalid_otp_token: Введено неправильний код invalid_sign_in_token: Хибний код безпеки otp_lost_help_html: Якщо ви втратили доÑтуп до обох, ви можете отримати доÑтуп з %{email} @@ -1283,3 +1309,20 @@ uk: verification: explanation_html: 'Ð’Ð¾Ð»Ð¾Ð´Ñ–Ð½Ð½Ñ Ð¿Ð¾ÑиланнÑми у профілі <strong>можна підтвердити</strong>. Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ на зазначеному Ñайті повинна міÑтитиÑÑ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° ваш профіль Mastodon, а у Ñамому поÑиланні <strong>повинен</strong> бути атрибут <code>rel="me"</code>. Що вÑередині поÑÐ¸Ð»Ð°Ð½Ð½Ñ - Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½Ðµ має. ОÑÑŒ вам приклад поÑиланнÑ:' verification: ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ + webauthn_credentials: + add: Додати новий ключ безпеки + create: + error: СталаÑÑ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð° при додаванні ключа безпеки. Спробуйте знову. + success: Ключ безпеки уÑпішно доданий. + delete: Видалити + delete_confirmation: Ви впевнені, що хочете вилучити цей ключ безпеки? + description_html: Якщо ви увімкнете <strong>автентифікацію за допомогою ключа безпеки</strong>, вхід буде вимагати викориÑÑ‚Ð°Ð½Ð½Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ з ваших ключів безпеки. + destroy: + error: СталаÑÑ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð° при видаленні ключа безпеки. Спробуйте знову. + success: Ключ безпеки уÑпішно видалено. + invalid_credential: Ðевірний ключ безпеки + nickname_hint: Введіть пÑевдонім нового ключа безпеки + not_enabled: Ви ще не активували WebAuthn + not_supported: Цей браузер не підтримує ключі безпеки + otp_required: Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² безпеки, Ñпочатку увімкніть двофакторну аутентифікацію. + registered_on: ЗареєÑтровано %{date} diff --git a/config/locales/ur.yml b/config/locales/ur.yml index 2aa72a8f8d1cf051370a44e757138ce5decd9d86..31c2292bbd60de44652c4fa71bfa4bfa91b11ad6 100644 --- a/config/locales/ur.yml +++ b/config/locales/ur.yml @@ -10,11 +10,3 @@ ur: '429': Too many requests '500': '503': The page could not be served due to a temporary server failure. - invites: - expires_in: - '1800': 30 minutes - '21600': 6 hours - '3600': 1 hour - '43200': 12 hours - '604800': 1 week - '86400': 1 day diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 1b5cfe1d1e56a5f7255cc4769dff085e6d56146d..e11c9f308553ca801af47da89ed53124415403e7 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -1,68 +1,71 @@ --- vi: about: - about_hashtag_html: Äây là các tút công khai được gắn thẻ <strong>#%{hashtag}</strong>. Chỉ cần bạn có tà i khoản ở bất cứ đâu trong mạng liên kết là bạn có thể tương tác vá»›i chúng. + about_hashtag_html: Äây là các tút <strong>#%{hashtag}</strong> trên mạng liên hợp. Bạn có thể tương tác vá»›i chúng sau khi đăng nháºp. about_mastodon_html: 'Mạng xã há»™i cá»§a tương lai: Không quảng cáo, không theo dõi ngưá»i dùng và phi táºp quyá»n! Là m chá»§ quyá»n riêng tư cá»§a bạn vá»›i Mastodon!' - about_this: Trong khoảng + about_this: Giá»›i thiệu active_count_after: hoạt động - active_footnote: Ngưá»i dùng hoạt động hà ng tháng + active_footnote: Ngưá»i dùng hoạt động hà ng tháng (MAU) administered_by: 'Quản trị viên:' api: API apps: Ứng dụng di động apps_platforms: Lướt Mastodon trên iOS, Android và các ná»n tảng khác - browse_directory: Những ai đã tham gia máy chá»§ nà y? - browse_local_posts: Xem thá» những tút công khai gần đây + browse_directory: Tìm những ngưá»i cùng chung sở thÃch + browse_local_posts: Xem những gì Ä‘ang xảy ra browse_public_posts: Xem thá» những tút công khai trên mạng Mastodon contact: Liên lạc contact_missing: Chưa thiết láºp contact_unavailable: N/A - discover_users: Khám phá ngưá»i dùng + discover_users: Thà nh viên documentation: Tà i liệu - federation_hint_html: Äăng ký tà i khoản %{instance}, bạn có thể giao tiếp vá»›i má»i ngưá»i trên bất kỳ máy chá»§ Mastodon nà o và hÆ¡n thế nữa. - get_apps: Dùng thỠứng dụng di động + federation_hint_html: Äăng ký tà i khoản %{instance} là bạn có thể giao tiếp vá»›i má»i ngưá»i trên bất kỳ máy chá»§ Mastodon nà o và còn hÆ¡n thế nữa. + get_apps: Ứng dụng di động hosted_on: "%{domain} váºn hà nh nhá» Mastodon" - instance_actor_flash: Tà i khoản nà y là má»™t tác nhân ảo được sá» dụng để đại diện cho chÃnh máy chá»§ chứ không phải bất kỳ ngưá»i dùng cá nhân nà o. Nó được sá» dụng cho mục Ä‘Ãch liên kết và không nên bị chặn trừ khi bạn muốn chặn toà n bá»™ máy chá»§. - learn_more: Tìm hiểu thêm + instance_actor_flash: 'Äây là má»™t tà i khoản ảo được sá» dụng để đại diện cho máy chá»§ chứ không phải bất kỳ ngưá»i dùng cá nhân nà o. Nó được sá» dụng cho mục Ä‘Ãch liên kết và không nên chặn trừ khi bạn muốn chặn toà n bá»™ máy chá»§. + +' + learn_more: Tìm hiểu privacy_policy: ChÃnh sách bảo máºt - see_whats_happening: Xem những gì Ä‘ang xảy ra - server_stats: 'Thống kê máy chá»§:' + see_whats_happening: Dòng thá»i gian + server_stats: 'Cá»™ng đồng:' source_code: Mã nguồn status_count_after: other: tút status_count_before: NÆ¡i lưu giữ - tagline: Mạng xã há»™i liên hợp lá»›n nhất thế giá»›i + tagline: Theo dõi bạn bè và khám phá thế giá»›i terms: Äiá»u khoản dịch vụ - unavailable_content: Máy chá»§ bị giá»›i hạn + unavailable_content: Giá»›i hạn chung unavailable_content_description: domain: Máy chá»§ reason: Lý do - rejecting_media: 'Ảnh và video từ những máy chá»§ sau sẽ không được xá» lý, lưu trữ và hiển thị hình thu nhá», bắt buá»™c nhấp thá»§ công và o tệp gốc để xem:' - rejecting_media_title: Ảnh và các thứ đã lá»c + rejecting_media: 'Ảnh và video từ những máy chá»§ sau sẽ không được xá» lý, lưu trữ và hiển thị hình thu nhá». Bắt buá»™c nhấp thá»§ công và o tệp gốc để xem:' + rejecting_media_title: Ảnh và video silenced: 'Tút từ những máy chá»§ sau sẽ bị ẩn trên bảng tin, trong tin nhắn và không có thông báo nà o được tạo từ các tương tác cá»§a ngưá»i dùng cá»§a há», trừ khi bạn có theo dõi ngưá»i dùng cá»§a há»:' - silenced_title: Những máy chá»§ đã bị tạm ẩn - suspended: 'Những máy chá»§ sau sẽ không được xá» lý, lưu trữ hoặc trao đổi ná»™i dung. Má»i tương tác hoặc giao tiếp vá»›i ngưá»i dùng từ các máy chá»§ nà y cÅ©ng bị cấm:' + silenced_title: Những máy chá»§ bị ẩn + suspended: 'Những máy chá»§ sau sẽ không được xá» lý, lưu trữ hoặc trao đổi ná»™i dung. Má»i tương tác hoặc giao tiếp vá»›i ngưá»i dùng từ các máy chá»§ nà y Ä‘á»u bị cấm:' suspended_title: Những máy chá»§ bị vô hiệu hóa - unavailable_content_html: Mastodon cho phép bạn xem ná»™i dung và tương tác vá»›i ngưá»i dùng từ bất kỳ máy chá»§ nà o khác trong mạng liên kết. Còn máy chá»§ nà y có những ngoại lệ riêng. + unavailable_content_html: Mastodon cho phép bạn xem ná»™i dung và tương tác vá»›i ngưá»i dùng từ bất kỳ máy chá»§ nà o khác trong mạng liên hợp. Còn máy chá»§ nà y có những ngoại lệ riêng. user_count_after: other: ngưá»i dùng user_count_before: Nhà cá»§a what_is_mastodon: Mastodon là gì? accounts: - choices_html: 'Những ngưá»i %{name} theo dõi:' + choices_html: "%{name} vinh danh:" endorsements_hint: Bạn có thể vinh danh những ngưá»i bạn theo dõi và há» sẽ hiển thị ở giao diện web. featured_tags_hint: Bạn có thể cho biết những hashtag thưá»ng dùng ở đây. follow: Theo dõi followers: other: Ngưá»i theo dõi - following: Äang theo dõi + following: Theo dõi + instance_actor_flash: Tà i khoản nà y được dùng để đại diện cho máy chá»§ và không phải là ngưá»i tháºt. Äừng bao giá» vô hiệu hóa tà i khoản nà y. joined: Äã tham gia %{date} - last_active: hoạt động gần đây + last_active: online link_verified_on: Liên kết nà y đã được xác thá»±c quyá»n sở hữu và o %{date} media: Bá»™ sưu táºp moved_html: "%{name} đã dá»i sang %{new_profile_link}:" - network_hidden: Thông tin nà y không còn tồn tại + network_hidden: Dữ liệu đã bị ẩn never_active: Chưa có - nothing_here: Chưa đăng tút nà o cả! + nothing_here: Trống trÆ¡n! people_followed_by: Những ngưá»i %{name} theo dõi people_who_follow: Những ngưá»i theo dõi %{name} pin_errors: @@ -70,28 +73,29 @@ vi: posts: other: Tút posts_tab_heading: Tút - posts_with_replies: Trả lá»i - reserved_username: Tên ngưá»i dùng đã có rồi + posts_with_replies: Tương tác + reserved_username: Tên nà y đã sá» dụng rồi roles: admin: Quản trị viên - bot: Ngưá»i máy + bot: Tà i khoản Bot group: Nhóm moderator: Kiểm duyệt viên - unavailable: Tà i khoản không còn nữa + unavailable: Tà i khoản bị đình chỉ unfollow: Ngưng theo dõi admin: account_actions: - action: Thá»±c hiện các hà nh động - title: Thá»±c hiện kiểm duyệt vá»›i %{acct} + action: Thá»±c hiện hà nh động + title: Ãp đặt kiểm duyệt vá»›i %{acct} account_moderation_notes: - create: Äể lại lá»i nhắn - created_msg: Äể lại lá»i nhắn kiểm duyệt thà nh công! + create: Gá»i tin nhắn kiểm duyệt + created_msg: Gá»i tin nhắn kiểm duyệt thà nh công! delete: Xóa bá» destroyed_msg: Äã ghi chú kiểm duyệt xong! accounts: - add_email_domain_block: Thêm máy chá»§ và o danh sách chặn + add_email_domain_block: Chặn tên miá»n email approve: Phê duyệt approve_all: Phê duyệt tất cả + approved_msg: Äã phê duyệt %{username} đăng ký thà nh công are_you_sure: Bạn có chắc không? avatar: Ảnh đại diện by_domain: Máy chá»§ @@ -102,12 +106,14 @@ vi: new_email: Email má»›i submit: Thay đổi email title: Thay đổi email cho %{username} - confirm: Xác nháºn + confirm: Phê duyệt confirmed: Äã xác thá»±c confirming: Chá» xác nháºn + delete: Xóa dữ liệu deleted: Äã xóa - demote: Gỡ bá» chức vụ - disable: Vô hiệu hóa + demote: Xóa chức vụ + destroyed_msg: Dữ liệu %{username} sẽ được lên lịch xóa ngay bây giá» + disable: Tạm khóa disable_two_factor_authentication: Vô hiệu hóa xác thá»±c hai bước disabled: Äã vô hiệu hóa display_name: Tên hiển thị @@ -115,52 +121,60 @@ vi: edit: Chỉnh sá»a email: Email email_status: Trạng thái email - enable: Phê duyệt + enable: Mở lại enabled: Äã duyệt + enabled_msg: Äã kÃch hoạt lại tà i khoản %{username} thà nh công followers: Ngưá»i theo dõi follows: Äang theo dõi header: Ảnh bìa - inbox_url: URL há»™p thư đến + inbox_url: Há»™p thư cá»§a ngưá»i nà y + invite_request_text: Lý do đăng ký invited_by: ÄÆ°á»£c má»i bởi ip: IP joined: Äã tham gia location: - all: Tất cả + all: Toà n bá»™ local: Máy chá»§ cá»§a bạn - remote: Từ máy chá»§ khác + remote: Máy chá»§ khác title: Vị trà - login_status: Trạng thái đăng nháºp + login_status: Trạng thái tà i khoản media_attachments: Tệp Ä‘Ãnh kèm memorialize: Chuyển sang tà i khoản tưởng niệm + memorialized: Tưởng nhá»› + memorialized_msg: Äã chuyển %{username} thà nh tà i khoản tưởng nhá»› moderation: active: Hoạt động - all: Tất cả - pending: Äang chá» xá» lý + all: Toà n bá»™ + pending: Chá» xá» lý silenced: Tạm ẩn suspended: Vô hiệu hóa - title: Kiểm duyệt + title: Trạng thái moderation_notes: Nháºt ký kiểm duyệt - most_recent_activity: Hoạt động gần đây nhất + most_recent_activity: Hoạt động lần cuối most_recent_ip: IP gần đây nhất no_account_selected: Không có tà i khoản nà o thay đổi vì không có tà i khoản nà o được chá»n - no_limits_imposed: Không áp đặt giá»›i hạn + no_limits_imposed: Bình thưá»ng not_subscribed: Chưa đăng ký - pending: Äang chá» xem xét + pending: Chá» duyệt perform_full_suspension: Vô hiệu hóa promote: Chỉ định chức vụ protocol: Giao thức public: Công khai push_subscription_expires: Äăng ký PuSH hết hạn redownload: Là m má»›i trang cá nhân + redownloaded_msg: Äã tiếp nháºn tà i khoản %{username} thà nh công reject: Từ chối reject_all: Từ chối tất cả + rejected_msg: Äã từ chối đăng ký tà i khoản %{username} remove_avatar: Xóa ảnh đại diện remove_header: Xóa ảnh bìa + removed_avatar_msg: Äã xóa bỠảnh đại diện cá»§a %{username} + removed_header_msg: Äã xóa bỠảnh bìa cá»§a %{username} resend_confirmation: already_confirmed: Ngưá»i dùng nà y đã được xác thá»±c send: Gá»i lại email xác nháºn success: Email xác nháºn đã gá»i thà nh công! - reset: Äặt lại + reset: Là m tươi reset_password: Äặt lại máºt khẩu resubscribe: Äăng ký lại role: Chức vụ @@ -170,105 +184,123 @@ vi: staff: Äá»™i ngÅ© quản lý user: Ngưá»i dùng search: Tìm kiếm - search_same_email_domain: Tìm ngưá»i dùng có cùng địa chỉ email - search_same_ip: Tìm ngưá»i dùng có cùng IP - shared_inbox_url: Chia sẻ URL há»™p thư đến + search_same_email_domain: Tra cứu email + search_same_ip: Tra cứu IP + sensitive: Nhạy cảm + sensitized: đánh dấu nhạy cảm + shared_inbox_url: Há»™p thư cá»§a máy chá»§ ngưá»i nà y show: - created_reports: Xuất báo cáo + created_reports: Lượt báo cáo targeted_reports: Báo cáo bởi ngưá»i khác - silence: Tạm ẩn - silenced: Tạm ẩn + silence: Ẩn + silenced: Äã ẩn statuses: Tút subscribe: Äăng ký suspended: Äã vô hiệu hóa + suspension_irreversible: Toà n bá»™ dữ liệu cá»§a ngưá»i dùng nà y sẽ bị xóa hết. Bạn vẫn có thể ngừng vô hiệu hóa nhưng dữ liệu sẽ không thể phục hồi. + suspension_reversible_hint_html: Má»i dữ liệu cá»§a ngưá»i nà y sẽ bị xóa sạch và o %{date}. Trước thá»i hạn nà y, dữ liệu vẫn có thể phục hồi. Nếu bạn muốn xóa dữ liệu cá»§a ngưá»i nà y ngay láºp tức, hãy tiếp tục. time_in_queue: Äang chá» cách đây %{time} title: Tà i khoản unconfirmed_email: Email chưa được xác thá»±c - undo_silenced: Bá» tạm ẩn - undo_suspension: Ngừng vô hiệu hóa + undo_sensitized: Äánh dấu bình thưá»ng + undo_silenced: BỠẩn + undo_suspension: Bá» vô hiệu hóa + unsilenced_msg: BỠẩn %{username} thà nh công unsubscribe: Há»§y đăng ký - username: Tên tà i khoản - warn: Cảnh cáo + unsuspended_msg: Äã kÃch hoạt lại %{username} thà nh công + username: Tà i khoản + view_domain: Xem mô tả tà i khoản nà y + warn: Cấm upload web: Web whitelisted: Danh sách trắng action_logs: action_types: - assigned_to_self_report: Báo cáo từ đội ngÅ© - change_email_user: Äổi email cho ngưá»i dùng + assigned_to_self_report: Tá»± xá» lý báo cáo + change_email_user: Äổi email confirm_user: Xác nháºn ngưá»i dùng - create_account_warning: Tạo cảnh cáo + create_account_warning: Gá»i cảnh cáo create_announcement: Tạo thông báo create_custom_emoji: Tạo Emoji má»›i - create_domain_allow: Tạo danh sách máy chá»§ cho phép - create_domain_block: Tạo danh sách máy chá»§ chặn - create_email_domain_block: Tạo danh sách địa chỉ email chặn - demote_user: Gỡ bá» chức vụ - destroy_announcement: Gỡ thông báo - destroy_custom_emoji: Gỡ Emoji - destroy_domain_allow: Gỡ máy chá»§ cho phép - destroy_domain_block: Gỡ máy chá»§ chặn - destroy_email_domain_block: Gỡ email đã chặn + create_domain_allow: Cho phép máy chá»§ + create_domain_block: Chặn máy chá»§ + create_email_domain_block: Chặn tên miá»n email + create_ip_block: Chặn IP + demote_user: Xóa chức vụ + destroy_announcement: Xóa thông báo + destroy_custom_emoji: Xóa Emoji + destroy_domain_allow: Bá» máy chá»§ cho phép + destroy_domain_block: Bá» chặn máy chá»§ + destroy_email_domain_block: Bá» chặn email + destroy_ip_block: Bá» chặn IP destroy_status: Xóa tút - disable_2fa_user: Vô hiệu hóa xác thá»±c hai bước + disable_2fa_user: Xóa xác thá»±c hai bước disable_custom_emoji: Vô hiệu hóa Emoji - disable_user: Vô hiệu hóa ngưá»i dùng - enable_custom_emoji: Báºt Emoji - enable_user: Mở lại ngưá»i dùng + disable_user: Tạm khóa ngưá»i dùng + enable_custom_emoji: Cho phép Emoji + enable_user: Mở khóa memorialize_account: Tà i khoản tưởng niệm promote_user: Chỉ định chức vụ - remove_avatar_user: Gỡ bỠảnh đại diện + remove_avatar_user: Xóa ảnh đại diện reopen_report: Mở lại báo cáo reset_password_user: Äặt lại máºt khẩu - resolve_report: Xem xét lại báo cáo - silence_account: Tà i khoản tạm ẩn - suspend_account: Tà i khoản bị vô hiệu hóa - unassigned_report: Báo cáo chưa xem - unsilence_account: Tà i khoản bá» tạm ẩn - unsuspend_account: Tà i khoản đã ngừng vô hiệu hóa + resolve_report: Xá» lý báo cáo + sensitive_account: Äánh dấu nhạy cảm cho tà i khoản + silence_account: Ẩn + suspend_account: Vô hiệu hóa + unassigned_report: Báo cáo chưa xá» lý + unsensitive_account: Äánh dấu bình thưá»ng + unsilence_account: BỠẩn + unsuspend_account: Bá» vô hiệu hóa update_announcement: Cáºp nháºt thông báo update_custom_emoji: Cáºp nháºt Emoji má»›i - update_status: Cáºp nháºt trạng thái máy chá»§ + update_domain_block: Cáºp nháºt máy chá»§ chặn + update_status: Cáºp nháºt tút actions: - assigned_to_self_report: "%{name} đã xuất báo cáo %{target} cho chÃnh há»" + assigned_to_self_report: "%{name} tá»± xá» lý báo cáo %{target}" change_email_user: "%{name} đã thay đổi địa chỉ email cho %{target}" confirm_user: "%{name} xác nháºn địa chỉ email cá»§a ngưá»i dùng %{target}" create_account_warning: "%{name} đã gá»i cảnh cáo %{target}" - create_announcement: "%{name} tạo thông báo tá»›i %{target}" + create_announcement: "%{name} tạo thông báo má»›i %{target}" create_custom_emoji: "%{name} đã tải lên biểu tượng cảm xúc má»›i %{target}" - create_domain_allow: "%{name} đưa máy chá»§ %{target} và o danh sách trắng" + create_domain_allow: "%{name} kÃch hoạt liên hợp vá»›i %{target}" create_domain_block: "%{name} chặn máy chá»§ %{target}" - create_email_domain_block: "%{name} đưa email %{target} và o danh sách Ä‘en" - demote_user: "%{name} đã gỡ bá» chức vụ %{target}" - destroy_announcement: "%{name} gỡ thông báo tá»›i %{target}" - destroy_custom_emoji: "%{name} biểu tượng cảm xúc bị phá há»§y %{target}" + create_email_domain_block: "%{name} chặn tên miá»n email %{target}" + create_ip_block: "%{name} đã chặn IP %{target}" + demote_user: "%{name} đã xóa chức vụ %{target}" + destroy_announcement: "%{name} xóa thông báo %{target}" + destroy_custom_emoji: "%{name} đã xóa emoji %{target}" destroy_domain_allow: "%{name} đã xóa tên miá»n %{target} khá»i danh sách trắng" destroy_domain_block: "%{name} bá» chặn máy chá»§ %{target}" - destroy_email_domain_block: "%{name} cho email %{target} và o danh sách trắng" - destroy_status: "%{name} đã gỡ bá» tút cá»§a %{target}" - disable_2fa_user: "%{name} đã vô hiệu hóa xác thá»±c hai yếu tố cá»§a %{target}" - disable_custom_emoji: "%{name} đã gỡ bá» Emoji %{target}" - disable_user: "%{name} vô hiệu hóa đăng nháºp cá»§a ngưá»i dùng %{target}" - enable_custom_emoji: "%{name} kÃch hoạt Emoji %{target}" - enable_user: "%{name} kÃch hoạt đăng nháºp cho ngưá»i dùng %{target}" + destroy_email_domain_block: "%{name} bá» chặn tên miá»n email %{target}" + destroy_ip_block: "%{name} bá» chặn IP %{target}" + destroy_status: "%{name} đã xóa tút cá»§a %{target}" + disable_2fa_user: "%{name} đã vô hiệu hóa xác thá»±c hai bước cá»§a %{target}" + disable_custom_emoji: "%{name} đã ẩn emoji %{target}" + disable_user: "%{name} vô hiệu hóa đăng nháºp %{target}" + enable_custom_emoji: "%{name} cho phép Emoji %{target}" + enable_user: "%{name} mở khóa cho ngưá»i dùng %{target}" memorialize_account: "%{name} đã biến tà i khoản %{target} thà nh má»™t trang tưởng niệm" promote_user: "%{name} đã chỉ định chức vụ cho %{target}" remove_avatar_user: "%{name} đã xóa ảnh đại diện cá»§a %{target}" reopen_report: "%{name} mở lại báo cáo %{target}" reset_password_user: "%{name} đặt lại máºt khẩu cá»§a ngưá»i dùng %{target}" resolve_report: "%{name} đã giải quyết báo cáo %{target}" - silence_account: "%{name} đã tạm ẩn %{target}" + sensitive_account: "%{name} đánh dấu ná»™i dung cá»§a %{target} là nhạy cảm" + silence_account: "%{name} đã ẩn %{target}" suspend_account: "%{name} đã vô hiệu hóa %{target}" unassigned_report: "%{name} báo cáo chưa được chỉ định %{target}" - unsilence_account: "%{name} đã bá» tạm ẩn %{target}" + unsensitive_account: "%{name} đánh dấu ná»™i dung cá»§a %{target} là bình thưá»ng" + unsilence_account: "%{name} đã bỠẩn %{target}" unsuspend_account: "%{name} đã ngừng vô hiệu hóa %{target}" update_announcement: "%{name} cáºp nháºt thông báo cho %{target}" update_custom_emoji: "%{name} đã cáºp nháºt biểu tượng cảm xúc %{target}" + update_domain_block: "%{name} cáºp nháºt chặn máy chá»§ %{target}" update_status: "%{name} cáºp nháºt tút cá»§a %{target}" deleted_status: "(tút đã xóa)" empty: Không tìm thấy bản ghi. filter_by_action: Lá»c theo hà nh động - filter_by_user: Lá»c theo ngưá»i dùng - title: Nháºt ký đánh giá + filter_by_user: Lá»c theo ngưá»i + title: Nháºt ký kiểm duyệt announcements: destroyed_msg: Xóa thông báo thà nh công! edit: @@ -277,15 +309,15 @@ vi: live: Trá»±c tiếp new: create: Tạo thông báo - title: Thông báo má»›i + title: Tạo thông báo má»›i published_msg: Truyá»n Ä‘i thông báo thà nh công! scheduled_for: Äã lên lịch %{time} scheduled_msg: Thông báo đã lên lịch! title: Thông báo - unpublished_msg: Gỡ bá» thông báo thà nh xong! + unpublished_msg: Xóa bá» thông báo thà nh xong! updated_msg: Cáºp nháºt thông báo thà nh công! custom_emojis: - assign_category: Chỉ định danh mục + assign_category: Xếp và o danh mục by_domain: Máy chá»§ copied_msg: Tạo thà nh công Emoji copy: Sao chép @@ -293,14 +325,14 @@ vi: create_new_category: Tạo danh mục má»›i created_msg: Emoji được tạo thà nh công! delete: Xóa bá» - destroyed_msg: Äã gỡ Emoji thà nh công! + destroyed_msg: Äã xóa Emoji thà nh công! disable: Vô hiệu hóa disabled: Äã vô hiệu hóa disabled_msg: Vô hiệu hóa thà nh công Emoji nà y emoji: Emoji - enable: KÃch hoạt - enabled: Äã kÃch hoạt - enabled_msg: KÃch hoạt thà nh công Emoji nà y + enable: Cho phép + enabled: Äã cho phép + enabled_msg: Äã cho phép thà nh công Emoji nà y image_hint: PNG tối Ä‘a 50KB list: Danh sách listed: Liệt kê @@ -310,49 +342,49 @@ vi: overwrite: Ghi đè shortcode: Viết tắt shortcode_hint: Ãt nhất 2 ký tá»±, chỉ các ký tá»± chữ và số và dấu gạch dưới - title: Tùy chỉnh Emoji + title: Emoji uncategorized: Chưa phân loại unlist: Bá» danh sách - unlisted: Chưa niêm yết + unlisted: Chưa cho phép update_failed_msg: Không thể cáºp nháºt Emoji nà y updated_msg: Cáºp nháºt thà nh công Emoji! upload: Tải lên dashboard: - authorized_fetch_mode: Chế độ bảo máºt + authorized_fetch_mode: Xác thá»±c cao cấp backlog: công việc tồn Ä‘á»ng config: Thiết láºp feature_deletions: Xóa tà i khoản - feature_invites: Những lá»i má»i + feature_invites: Má»i đăng ký feature_profile_directory: Danh sách thà nh viên feature_registrations: Äăng ký feature_relay: Mạng liên hợp feature_spam_check: Chống thư rác feature_timeline_preview: Xem trước bảng tin features: TÃnh năng - hidden_service: Mạng liên kết vá»›i các dịch vụ ẩn - open_reports: mở báo cáo - pending_tags: hashtag Ä‘ang chá» xem xét - pending_users: ngưá»i dùng Ä‘ang chá» xem xét - recent_users: Ngưá»i dùng gần đây - search: Tìm kiếm toà n văn - single_user_mode: Chế độ ngưá»i dùng bình thưá»ng + hidden_service: Liên kết vá»›i các dịch vụ ẩn + open_reports: báo cáo + pending_tags: hashtag chá» duyệt + pending_users: ngưá»i dùng chá» duyệt + recent_users: Ngưá»i dùng má»›i nhất + search: Tìm kiếm ná»™i dung + single_user_mode: Máy chá»§ chỉ có 1 ngưá»i software: Phần má»m space: Dung lượng lưu trữ - title: Bảng cá nhân + title: Thống kê total_users: tổng số ngưá»i dùng trends: Xu hướng week_interactions: tương tác trong tuần nà y week_users_active: hoạt động trong tuần nà y - week_users_new: ngưá»i dùng trong tuần nà y - whitelist_mode: Chế độ danh sách trắng + week_users_new: đăng ký má»›i trong tuần + whitelist_mode: Giá»›i hạn mạng liên hợp domain_allows: - add_new: Máy chá»§ thuá»™c danh sách trắng - created_msg: Máy chá»§ đã được đưa và o danh sách trắng thà nh công - destroyed_msg: Máy chá»§ đã bị xóa khá»i danh sách trắng + add_new: Cho phép liên hợp vá»›i máy chá»§ + created_msg: Máy chá»§ đã được kÃch hoạt liên hợp thà nh công + destroyed_msg: Máy chá»§ đã bị ngưng liên hợp undo: Xóa khá»i danh sách trắng domain_blocks: - add_new: Chặn máy chá»§ má»›i - created_msg: Äang xá» lý chặn máy chá»§ + add_new: Chặn máy chá»§ + created_msg: Äang tiến hà nh chặn máy chá»§ destroyed_msg: Äã thôi chặn máy chá»§ domain: Máy chá»§ edit: Chỉnh sá»a máy chá»§ bị chặn @@ -361,11 +393,13 @@ vi: create: Tạo chặn hint: Chặn máy chá»§ sẽ không ngăn việc hiển thị tút cá»§a máy chá»§ đó trong cÆ¡ sở dữ liệu, nhưng sẽ khiến tá»± động áp dụng các phương pháp kiểm duyệt cụ thể trên các tà i khoản đó. severity: - desc_html: "<strong>Tạm ẩn</strong> sẽ là m cho bà i đăng cá»§a tà i khoản trở nên vô hình đối vá»›i bất kỳ ai không theo dõi há». <strong>Vô hiệu hóa</strong> sẽ xóa tất cả ná»™i dung, phương tiện và dữ liệu khác cá»§a tà i khoản. Sá» dụng <strong>Cấm upload</strong> nếu bạn chỉ muốn cấm tải lên ảnh và video." + desc_html: "<strong>Ẩn</strong> sẽ là m cho bà i đăng cá»§a tà i khoản trở nên vô hình đối vá»›i bất kỳ ai không theo dõi há». <strong>Vô hiệu hóa</strong> sẽ xóa tất cả ná»™i dung, phương tiện và dữ liệu khác cá»§a tà i khoản. Dùng <strong>Cấm upload</strong> nếu bạn chỉ muốn cấm tải lên ảnh và video." noop: Không hoạt động - silence: Tạm ẩn + silence: Ẩn suspend: Vô hiệu hóa title: Máy chá»§ bị chặn má»›i + obfuscate: Là m má» tên máy chá»§ + obfuscate_hint: Là m má» tên máy chá»§ trong danh sách nếu giá»›i hạn máy chá»§ đã báºt private_comment: Bình luáºn riêng private_comment_hint: Cho biết vì sao chặn máy chá»§ nà y để tiện kiểm duyệt viên tham khảo. public_comment: Bình luáºn công khai @@ -377,13 +411,13 @@ vi: rejecting_media: từ chối các táºp tin phương tiện truyá»n thông rejecting_reports: từ chối báo cáo severity: - silence: đã tạm ẩn + silence: bị ẩn suspend: bị vô hiệu hóa show: affected_accounts: other: "%{count} tà i khoản trong cÆ¡ sở dữ liệu bị ảnh hưởng" retroactive: - silence: Những tà i khoản tạm ẩn ở máy chá»§ nà y + silence: Những tà i khoản bị ẩn ở máy chá»§ nà y suspend: Ngưng vô hiệu hóa các tà i khoản ở máy chá»§ nà y title: Há»§y chặn máy chá»§ %{domain} undo: Há»§y bá» @@ -391,32 +425,33 @@ vi: view: Xem máy chá»§ chặn email_domain_blocks: add_new: Thêm má»›i - created_msg: Äã thêm thà nh công e-mail và o danh sách Ä‘en + created_msg: Äã chặn tên miá»n email nà y delete: Xóa bá» - destroyed_msg: Äã xóa thà nh công e-mail khá»i danh sách Ä‘en - domain: Máy chá»§ - empty: Chưa có máy chá»§ nà o trong danh sách Ä‘en. + destroyed_msg: Äã bá» chặn tên miá»n email nà y + domain: Äịa chỉ email + empty: Chưa chặn tên miá»n email nà o. from_html: từ %{domain} new: - create: Thêm máy chá»§ - title: Mục má»›i trong danh sách Ä‘en email - title: Danh sách Ä‘en email + create: Thêm địa chỉ + title: Chặn tên miá»n email má»›i + title: Tên miá»n email đã chặn instances: by_domain: Máy chá»§ delivery_available: Cho phép liên kết + empty: Không có máy chá»§ nà o. known_accounts: - other: "%{count} tà i khoản đã xác thá»±c" + other: "%{count} tà i khoản đã biết" moderation: all: Tất cả limited: Hạn chế title: Kiểm duyệt private_comment: Bình luáºn riêng public_comment: Bình luáºn công khai - title: Mạng liên kết + title: Mạng liên hợp total_blocked_by_us: Bị chặn bởi chúng ta total_followed_by_them: ÄÆ°á»£c há» theo dõi total_followed_by_us: ÄÆ°á»£c quản trị viên theo dõi - total_reported: Báo cáo tổng hợp + total_reported: Toà n bá»™ báo cáo total_storage: Ảnh và video invites: deactivate_all: Vô hiệu hóa tất cả @@ -426,10 +461,25 @@ vi: expired: Äã hết hạn title: Bá»™ lá»c title: Lá»i má»i + ip_blocks: + add_new: Chặn IP má»›i + created_msg: Äã chặn IP thà nh công + delete: Bá» chặn + expires_in: + '1209600': 2 tuần + '15778476': 6 tháng + '2629746': 1 tháng + '31556952': 1 năm + '86400': 1 ngà y + '94670856': 3 năm + new: + title: Chặn má»™t IP má»›i + no_ip_block_selected: Bạn chưa chá»n bất kỳ IP nà o + title: Những IP bị chặn pending_accounts: - title: Tà i khoản Ä‘ang chá» xá» lý (%{count}) + title: Tà i khoản Ä‘ang chá» xem xét (%{count}) relationships: - title: Những mối liên hệ cá»§a %{acct} + title: Mối quan hệ cá»§a %{acct} relays: add_new: Thêm liên hợp má»›i delete: Loại bá» @@ -447,44 +497,46 @@ vi: status: Trạng thái hiện tại title: Mạng liên hợp report_notes: - created_msg: Báo cáo ghi chú được tạo thà nh công! - destroyed_msg: Báo cáo đã xóa thà nh công! + created_msg: Ghi chú kiểm duyệt đã tạo xong! + destroyed_msg: Äã xóa báo cáo kiểm duyệt! reports: account: notes: - other: "%{count} ghi chú" + other: "%{count} kiểm duyệt" reports: other: "%{count} báo cáo" action_taken_by: Hà nh động được thá»±c hiện bởi are_you_sure: Bạn có chắc không? assign_to_self: Giao cho tôi - assigned: Ngưá»i Ä‘iá»u hà nh được phân công - by_target_domain: Máy chá»§ cá»§a tà i khoản bị báo xấu + assigned: Ngưá»i xá» lý + by_target_domain: Tên tà i khoản bị báo cáo comment: - none: Không ai - created_at: Báo cáo + none: Không có mô tả + created_at: Báo cáo lúc + forwarded: Chuyển tiếp + forwarded_to: Chuyển tiếp tá»›i %{domain} mark_as_resolved: Äánh dấu là đã giải quyết mark_as_unresolved: Äánh dấu là chưa giải quyết notes: - create: Thêm ghi chú - create_and_resolve: Giải quyết vá»›i ghi chú - create_and_unresolve: Mở lại vá»›i ghi chú + create: Bổ sung ghi chú + create_and_resolve: Xá» lý kiểm duyệt + create_and_unresolve: Mở lại kèm ghi chú má»›i delete: Xóa bá» - placeholder: Mô tả những hà nh động đã được thá»±c hiện, hoặc bất kỳ cáºp nháºt liên quan khác... + placeholder: Mô tả vi phạm cá»§a ngưá»i nà y, mức độ xá» lý và những cáºp nháºt liên quan khác... reopen: Mở lại báo cáo report: 'Báo cáo #%{id}' - reported_account: Tà i khoản bị báo xấu - reported_by: Báo xấu bởi - resolved: Äã giải quyết - resolved_msg: Giải quyết báo xấu thà nh công! + reported_account: Tà i khoản bị báo cáo + reported_by: Báo cáo bởi + resolved: Äã xá» lý xong + resolved_msg: Äã giải quyết báo cáo xong! status: Trạng thái - title: Báo xấu + title: Báo cáo unassign: Bá» qua - unresolved: Chưa giải quyết - updated_at: Äã cáºp nháºt + unresolved: Chá» xá» lý + updated_at: Cáºp nháºt lúc settings: activity_api_enabled: - desc_html: Số lượng trạng thái được đăng tại địa phương, ngưá»i dùng hoạt động và đăng ký má»›i trong nhóm hà ng tuần + desc_html: Thu tháºp số lượng tút được đăng, ngưá»i dùng hoạt động và ngưá»i dùng đăng ký má»›i hà ng tuần title: Công khai số liệu thống kê vá» hoạt động ngưá»i dùng bootstrap_timeline_accounts: desc_html: Tách tên ngưá»i dùng bằng dấu phẩy. Chỉ có hiệu lá»±c vá»›i các tà i khoản công khai thuá»™c máy chá»§. Mặc định khi trống là tất cả quản trị viên. @@ -506,15 +558,16 @@ vi: domain_blocks_rationale: title: Hiển thị lý do enable_bootstrap_timeline_accounts: + desc_html: Thiết láºp ngưá»i má»›i đăng ký sẽ tá»± động theo dõi những tà i khoản cho trước nhằm tránh việc bảng tin trống title: Gợi ý theo dõi cho ngưá»i dùng má»›i hero: - desc_html: Hiển thị trên trang chá»§. KÃch cỡ tối thiểu 600x100px. Khi không được đặt, sá» dụng hình thu nhá» cá»§a máy chá»§ + desc_html: Hiển thị trên trang chá»§. KÃch cỡ tối thiểu 600x100px. Mặc định dùng hình thu nhá» cá»§a máy chá»§ title: Hình ảnh giá»›i thiệu mascot: - desc_html: Hiển thị trên nhiá»u trang. KÃch cỡ tối thiểu 293 × 205px. Khi không được đặt, sá» dụng linh váºt mặc định Mastodon + desc_html: Hiển thị trên nhiá»u trang. KÃch cỡ tối thiểu 293 × 205px. Mặc định dùng linh váºt Mastodon title: Logo máy chá»§ peers_api_enabled: - desc_html: Tên miá»n mà máy chá»§ nà y đã kết giao trong mạng liên kết + desc_html: Tên miá»n mà máy chá»§ nà y đã kết giao trong mạng liên hợp title: Danh sách công khai các máy chá»§ được phát hiện preview_sensitive_media: desc_html: Liên kết xem trước trên các trang web khác sẽ hiển thị hình thu nhá» ngay cả khi phương tiện được đánh dấu là nhạy cảm @@ -524,7 +577,7 @@ vi: title: Cho phép hiện danh sách thà nh viên registrations: closed_message: - desc_html: Hiển thị trên trang chá»§ khi đăng ký được đóng lại. Bạn có thể sá» dụng thẻ HTML + desc_html: Hiển thị trên trang chá»§ khi đăng ký được đóng lại. Bạn có thể viết bằng thẻ HTML title: Thông Ä‘iệp báo máy chá»§ đã ngừng đăng ký deletion: desc_html: Cho phép má»i ngưá»i xóa tà i khoản cá»§a há» @@ -532,6 +585,9 @@ vi: min_invite_role: disabled: Không má»™t ai title: Cho phép lá»i má»i bằng cách + require_invite_text: + desc_html: Khi chá»n phê duyệt ngưá»i dùng thá»§ công, hiện “Tại sao bạn muốn đăng ký?†thay cho tùy chá»n nháºp + title: Ngưá»i đăng ký má»›i phải nháºp mã má»i tham gia registrations_mode: modes: approved: Yêu cầu phê duyệt để đăng ký @@ -540,31 +596,31 @@ vi: title: Chế độ đăng ký show_known_fediverse_at_about_page: desc_html: Nếu tắt, bảng tin sẽ chỉ hiển thị ná»™i dung do ngưá»i dùng cá»§a máy chá»§ nà y tạo ra - title: Bao gồm ná»™i dung từ mạng liên kết trên bảng tin không được xác thá»±c + title: Bao gồm ná»™i dung từ mạng liên hợp trên bảng tin không được xác thá»±c show_staff_badge: desc_html: Hiển thị huy hiệu nhân viên trên trang ngưá»i dùng title: Hiển thị huy hiệu nhân viên site_description: - desc_html: Äoạn giá»›i thiệu vá» API. Mô tả những gì là m cho máy chá»§ Mastodon nà y đặc biệt và bất cứ Ä‘iá»u gì quan trá»ng khác. Bạn có thể sá» dụng các thẻ HTML, đặc biệt là <code><a></code> và <code><em></code> . + desc_html: Ná»™i dung giá»›i thiệu vá» máy chá»§. Mô tả những gì là m cho máy chá»§ Mastodon nà y đặc biệt và bất cứ Ä‘iá»u gì quan trá»ng khác. Bạn có thể dùng các thẻ HTML, đặc biệt là <code><a></code> và <code><em></code>. title: Mô tả máy chá»§ site_description_extended: - desc_html: Bạn có thể tạo thêm các mục như quy định chung, hướng dẫn và những thứ khác liên quan tá»›i máy chá»§ cá»§a bạn. Sá» dụng thẻ HTML - title: Thông tin mở rá»™ng tùy chỉnh + desc_html: Bạn có thể tạo thêm các mục như quy định chung, hướng dẫn và những thứ khác liên quan tá»›i máy chá»§ cá»§a bạn. Dùng thẻ HTML + title: Thông tin bổ sung site_short_description: desc_html: Hiển thị trong thanh bên và thẻ meta. Mô tả Mastodon là gì và điá»u gì là m cho máy chá»§ nà y trở nên đặc biệt trong má»™t Ä‘oạn văn duy nhất. title: Mô tả máy chá»§ ngắn site_terms: - desc_html: Bạn có thể viết chÃnh sách bảo máºt cá»§a riêng bạn, Ä‘iá»u khoản dịch vụ hoặc pháp lý khác. Bạn có thể sá» dụng thẻ HTML + desc_html: Bạn có thể viết Ä‘iá»u khoản dịch vụ, quyá»n riêng tư hoặc các vấn đỠpháp lý khác. Dùng thẻ HTML title: Äiá»u khoản dịch vụ tùy chỉnh site_title: Tên máy chá»§ spam_check_enabled: desc_html: Mastodon có thể tá»± động báo cáo các tà i khoản gá»i tin nhắn không mong muốn lặp Ä‘i lặp lại. Có thể có dương tÃnh giả. title: Tá»± động chống thư rác thumbnail: - desc_html: ÄÆ°á»£c sá» dụng để xem trước thông qua OpenGraph và API. Khuyến nghị 1200x630px + desc_html: Bản xem trước thông qua OpenGraph và API. Khuyến nghị 1200x630px title: Hình thu nhá» cá»§a máy chá»§ timeline_preview: - desc_html: Hiển thị liên kết đến dòng thá»i gian công khai trên trang Ä‘Ãch và cho phép API truy cáºp và o dòng thá»i gian công khai mà không cần xác thá»±c + desc_html: Hiển thị dòng thá»i gian công khai trên trang Ä‘Ãch và cho phép API truy cáºp và o dòng thá»i gian công khai mà không cần xác thá»±c title: Cho phép truy cáºp không xác thá»±c và o dòng thá»i gian công cá»™ng title: Cà i đặt trang web trendable_by_default: @@ -586,28 +642,28 @@ vi: failed_to_execute: Không thể thá»±c thi media: title: Bá»™ sưu táºp - no_media: Không có ảnh hoặc video - no_status_selected: Không có tút nà o thay đổi vì không có tút nà o được chá»n - title: Trạng thái tà i khoản - with_media: Vá»›i ảnh hoặc video + no_media: Toà n bá»™ + no_status_selected: Bạn chưa chá»n bất kỳ tút nà o + title: Toà n bá»™ tút + with_media: Có ảnh hoặc video tags: accounts_today: Sá» dụng hôm nay - accounts_week: Sá» dụng trong tuần nà y - breakdown: Phân tÃch dung lượng sá» dụng hôm nay + accounts_week: Sá» dụng trong tuần + breakdown: Thống kê số lượt dùng hôm nay context: Bối cảnh - directory: Trong phân loại - in_directory: "%{count} trong phân loại" - last_active: Sá» dụng gần đây + directory: Có trên tiểu sá» + in_directory: "%{count} có trên tiểu sá»" + last_active: Hôm nay most_popular: Phổ biến nhất - most_recent: Vừa má»›i sá» dụng + most_recent: Gần đây name: Hashtag review: Phê duyệt reviewed: Äã phê duyệt title: Hashtag trending_right_now: Xu hướng - unique_uses_today: "%{count} đăng ngà y hôm nay" - unreviewed: Chưa được xem xét - updated_msg: Cà i đặt hashtag được cáºp nháºt thà nh công + unique_uses_today: "%{count} tút dùng hôm nay" + unreviewed: Chưa phê duyệt + updated_msg: Hashtag đã được cáºp nháºt thà nh công title: Quản trị warning_presets: add_new: Thêm má»›i @@ -616,39 +672,39 @@ vi: title: Quản lý cảnh báo cà i sẵn admin_mailer: new_pending_account: - body: Các chi tiết cá»§a tà i khoản má»›i dưới đây. Bạn có thể phê duyệt hoặc từ chối ứng dụng nà y. - subject: Tà i khoản má»›i được xem xét trên %{instance} (%{username}) + body: Thông tin chi tiết cá»§a tà i khoản má»›i ở phÃa dưới. Bạn có thể phê duyệt hoặc từ chối ngưá»i nà y. + subject: Tà i khoản chá» xét duyệt trên %{instance} (%{username}) new_report: - body: "%{reporter} đã báo cáo %{target}" + body: "%{reporter} vừa báo cáo %{target}" body_remote: Ai đó từ %{domain} đã báo cáo %{target} - subject: Báo cáo má»›i cho %{instance} (# %{id}) + subject: "(%{instance}) Báo cáo #%{id}" new_trending_tag: body: 'Hashtag # %{name} Ä‘ang là xu hướng nhưng chưa được kiểm duyệt. Nó sẽ không được hiển thị công khai trừ khi bạn cho phép. Bá» qua nếu bạn không bao giá» muốn thấy nó xuất hiện.' subject: Hashtag má»›i được xem xét trên %{instance} (# %{name}) aliases: - add_new: Tạo tên hiển thị + add_new: Kết nối tà i khoản created_msg: Tạo thà nh công má»™t tên hiển thị má»›i. Bây giá» bạn có thể bắt đầu di chuyển từ tà i khoản cÅ©. deleted_msg: Xóa thà nh công tên hiển thị. Chuyển từ tà i khoản nà y sang tà i khoản nà y sẽ không còn có thể. - empty: Bạn không tên hiển thị nà o. - hint_html: Nếu bạn muốn chuyển từ máy chá»§ khác sang máy chá»§ nà y, tại đây bạn có thể tạo bà danh, Ä‘iá»u nà y là bắt buá»™c trước khi bạn có thể tiến hà nh chuyển ngưá»i theo dõi từ tà i khoản cÅ© sang tà i khoản nà y. Hà nh động nà y cá»§a chÃnh nó là <strong>vô hại và có thể đảo ngược</strong>. <strong>Việc di chuyển tà i khoản được bắt đầu từ tà i khoản cÅ©</strong>. + empty: Bạn không có tà i khoản cÅ© nà o. + hint_html: Nếu bạn muốn chuyển từ máy chá»§ khác sang máy chá»§ nà y, bắt buá»™c bạn phải tạo tên ngưá»i dùng má»›i thì má»›i có thể tiến hà nh chuyển được ngưá»i theo dõi. Hà nh động nà y <strong>không ảnh hưởng gì và có thể đảo ngược</strong>. <strong>Việc di chuyển tà i khoản được bắt đầu từ tà i khoản cÅ©</strong>. remove: Bá» liên kết bà danh appearance: - advanced_web_interface: Giao diện web nâng cao - advanced_web_interface_hint: 'Nếu bạn muốn sá» dụng toà n bá»™ chiá»u rá»™ng mà n hình cá»§a mình, giao diện web nâng cao cho phép bạn định cấu hình nhiá»u cá»™t khác nhau để xem nhiá»u thông tin cùng lúc như bạn muốn: Trang chá»§, thông báo, dòng thá»i gian được liên kết, bất kỳ số lượng danh sách và hashtag nà o.' - animations_and_accessibility: Nâng cao + advanced_web_interface: Bố cục + advanced_web_interface_hint: 'Giao diện nhiá»u cá»™t cho phép bạn chuyển bố cục hiển thị thà nh nhiá»u cá»™t khác nhau. Bao gồm: Bảng tin, thông báo, thế giá»›i, cÅ©ng như danh sách và hashtag. Rất thÃch hợp nếu bạn Ä‘ang dùng mà n hình rá»™ng.' + animations_and_accessibility: Bảng tin confirmation_dialogs: Há»™p thoại xác nháºn discovery: Khám phá localization: - body: Mastodon được dịch bởi Hồ Nhất Duy. - guide_link: https://crowdin.com/project/mastodon - guide_link_text: Tuy nhiên, bạn cÅ©ng vẫn có thể đóng góp. + body: Mastodon Tiếng Việt được dịch bởi Hồ Nhất Duy. + guide_link: https://mas.to/@duy + guide_link_text: Äây là trang cá nhân cá»§a anh ấy. sensitive_content: Ná»™i dung nhạy cảm - toot_layout: Bố cục Tút + toot_layout: Tút application_mailer: notification_preferences: Thay đổi tùy chá»n email salutation: "%{name}," settings: 'Thay đổi tùy chá»n email: %{link}' - view: 'Xem:' + view: 'Chi tiết:' view_profile: Xem trang cá nhân view_status: Xem tút applications: @@ -662,8 +718,8 @@ vi: auth: apply_for_account: Äăng ký change_password: Máºt khẩu - checkbox_agreement_html: Tôi đồng ý vá»›i các <a href="%{rules_path}" target="_blank">quy tắc</a> và <a href="%{terms_path}" target="_blank">Ä‘iá»u khoản dịch vụ</a> - checkbox_agreement_without_rules_html: Tôi đồng ý vá»›i <a href="%{terms_path}" target="_blank">Ä‘iá»u khoản dịch vụ</a> + checkbox_agreement_html: Tôi đồng ý <a href="%{rules_path}" target="_blank">quy tắc</a> và <a href="%{terms_path}" target="_blank">chÃnh sách bảo máºt</a> + checkbox_agreement_without_rules_html: Tôi đồng ý <a href="%{terms_path}" target="_blank">chÃnh sách bảo máºt</a> delete_account: Xóa tà i khoản delete_account_html: Nếu bạn muốn xóa tà i khoản cá»§a mình, hãy <a href="%{path}">yêu cầu tại đây</a>. Bạn sẽ được yêu cầu xác nháºn. description: @@ -671,12 +727,15 @@ vi: prefix_sign_up: Tham gia Mastodon ngay hôm nay! suffix: Vá»›i tà i khoản, bạn sẽ có thể theo dõi má»i ngưá»i, đăng tút và nhắn tin vá»›i ngưá»i dùng từ bất kỳ máy chá»§ Mastodon khác! didnt_get_confirmation: Gá»i lại email xác thá»±c? + dont_have_your_security_key: Bạn có khóa bảo máºt chưa? forgot_password: Quên máºt khẩu invalid_reset_password_token: Mã đặt lại máºt khẩu không hợp lệ hoặc hết hạn. Vui lòng yêu cầu má»™t cái má»›i. + link_to_otp: Nháºp mã xác thá»±c từ Ä‘iện thoại hoặc mã phục hồi + link_to_webauth: Nháºp khóa bảo máºt từ thiết bị login: Äăng nháºp logout: Äăng xuất - migrate_account: Sá» dụng má»™t tà i khoản khác - migrate_account_html: Nếu bạn muốn bá» tà i khoản nà y để sá» dụng má»™t tà i khoản khác, bạn có thể <a href="%{path}">thiết láºp nó ở đây</a>. + migrate_account: Chuyển sang tà i khoản khác + migrate_account_html: Nếu bạn muốn bá» tà i khoản nà y để dùng má»™t tà i khoản khác, bạn có thể <a href="%{path}">thiết láºp nó ở đây</a>. or_log_in_with: Hoặc đăng nháºp bằng providers: cas: CAS @@ -694,13 +753,15 @@ vi: status: account_status: Trạng thái tà i khoản confirming: Äang chá» xác thá»±c email. - functional: Tà i khoản cá»§a bạn đã xác thá»±c và có thể sá» dụng. + functional: Tà i khoản cá»§a bạn đã được xác thá»±c. pending: ÄÆ¡n đăng ký cá»§a bạn Ä‘ang chá» phê duyệt. Äiá»u nà y có thể mất má»™t thá»i gian. Bạn sẽ nháºn được email nếu đơn đăng ký cá»§a bạn được chấp thuáºn. redirecting_to: Tà i khoản cá»§a bạn không hoạt động vì hiện Ä‘ang chuyển hướng đến %{acct}. - trouble_logging_in: Gặp sá»± cố khi đăng nháºp? + too_fast: Nghi vấn đăng ký spam, xin thá» lại. + trouble_logging_in: Quên máºt khẩu? + use_security_key: Dùng khóa bảo máºt authorize_follow: - already_following: Bạn Ä‘ang theo dõi ngưá»i dùng nà y - already_requested: Bạn vừa gá»i má»™t yêu cầu theo dõi tá»›i ngưá»i dùng nà y + already_following: Bạn Ä‘ang theo dõi ngưá»i nà y + already_requested: Bạn vừa gá»i má»™t yêu cầu theo dõi tá»›i ngưá»i nà y error: Rất tiếc, đã xảy ra lá»—i khi tìm kiếm tà i khoản từ nÆ¡i khác follow: Theo dõi follow_request: Bạn đã gá»i yêu cầu theo dõi tá»›i @@ -714,14 +775,15 @@ vi: confirm: Tiếp tục hint_html: "<strong>Mẹo:</strong> Chúng tôi sẽ không há»i lại máºt khẩu cá»§a bạn sau nà y." invalid_password: Máºt khẩu không hợp lệ - prompt: Xác nháºn máºt khẩu để tiếp tục + prompt: Nháºp máºt khẩu để tiếp tục crypto: errors: invalid_key: không phải là mã khóa Ed25519 hoặc Curve25519 đúng invalid_signature: không phải là chữ ký số Ed25519 đúng date: formats: - default: "%b.%-m.%Y" + default: "%-d %B, %Y" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}h" @@ -743,8 +805,8 @@ vi: proceed: Xóa tà i khoản success_msg: Tà i khoản cá»§a bạn đã được xóa thà nh công warning: - before: 'Trước khi tiếp tục, xin vui lòng Ä‘á»c các lưu ý:' - caches: Ná»™i dung đã được lưu trữ bởi các máy chá»§ khác có thể tồn tại + before: 'Trước khi tiếp tục, xin vui lòng xem xét cẩn tháºn:' + caches: Ná»™i dung đã lưu trữ trên các máy chá»§ khác có thể vẫn tồn tại data_removal: Bà i viết cá»§a bạn và dữ liệu khác sẽ bị xóa vÄ©nh viá»…n email_change_html: Bạn có thể <a href="%{path}">thay đổi địa chỉ email</a> mà không cần phải xóa tà i khoản email_contact_html: Nếu vẫn không nháºn được, bạn có thể liên hệ <a href="mailto:%{email}">%{email}</a> để được giúp đỡ @@ -754,9 +816,9 @@ vi: username_available: Tên ngưá»i dùng cá»§a bạn sẽ có thể đăng ký lại username_unavailable: Tên ngưá»i dùng cá»§a bạn sẽ không thể đăng ký má»›i directories: - directory: Danh sách thà nh viên - explanation: Khám phá ngưá»i dùng dá»±a trên sở thÃch cá»§a há» - explore_mastodon: Khám phá %{title} + directory: Khám phá + explanation: Tìm và theo dõi những ngưá»i cùng sở thÃch + explore_mastodon: Thà nh viên %{title} domain_validator: invalid_domain: không phải là má»™t tên miá»n hợp lệ errors: @@ -764,7 +826,7 @@ vi: '403': Bạn không có quyá»n xem trang nà y. '404': Trang nà y chưa được tạo. '406': Trang nà y không thể hiển thị do lá»—i định dạng. - '410': Trang nà y đã bị xóa trước đó. + '410': Trang nà y đã bị xóa '422': content: Xác minh bảo máºt thất bại. Bạn Ä‘ang chặn cookie? title: Xác minh bảo máºt thất bại @@ -773,7 +835,7 @@ vi: content: Chúng tôi xin lá»—i, nhưng đã xảy ra sá»± cố. title: Múi giá» trên thiết bị không đúng '503': Trang không thể hiển thị do lá»—i máy chá»§ tạm thá»i. - noscript_html: Äể sá» dụng ứng dụng web Mastodon, vui lòng báºt JavaScript. Ngoà i ra, hãy thá» má»™t trong những <a href="%{apps_path}">ứng dụng gốc</a> cá»§a Mastodon cho hệ Ä‘iá»u hà nh cá»§a bạn. + noscript_html: Äể và o Mastodon bản web, vui lòng báºt JavaScript. Ngoà i ra, hãy thá» dùng má»™t <a href="%{apps_path}">ứng dụng lướt Mastodon</a> cho thiết bị cá»§a bạn. existing_username_validator: not_found: không có tên ngưá»i dùng nà y trên máy chá»§ not_found_multiple: không tìm thấy %{usernames} @@ -786,6 +848,7 @@ vi: request: Tải vá» dữ liệu cá»§a bạn size: Dung lượng blocks: Ngưá»i bạn chặn + bookmarks: Äã lưu csv: CSV domain_blocks: Máy chá»§ bạn chặn lists: Danh sách @@ -795,14 +858,14 @@ vi: add_new: Thêm má»›i errors: limit: Bạn đã đạt tá»›i số lượng hashtag tối Ä‘a - hint_html: "<strong>Hashtags thưá»ng dùng là gì?</strong> Chúng được hiển thị nổi báºt trên trang cá nhân cá»§a bạn và cho phép má»i ngưá»i tìm kiếm các bà i đăng công khai cá»§a bạn có chứa các hashtag đó. Chúng là má»™t công cụ tuyệt vá»i để theo dõi các tác phẩm sáng tạo hoặc các dá»± án dà i hạn." + hint_html: "<strong>Hashtags thưá»ng dùng</strong> là gì? Chúng là những hashtag sẽ được hiển thị nổi báºt trên trang cá nhân cá»§a bạn, cho phép má»i ngưá»i tìm kiếm các bà i đăng công khai cá»§a bạn có chứa các hashtag đó. TÃnh năng nà y có thể dùng để đánh dấu chuá»—i tác phẩm sáng tạo hoặc dá»± án dà i hạn." filters: contexts: account: Trang cá nhân home: Bảng tin notifications: Thông báo public: Tin công khai - thread: Cuá»™c trò chuyện + thread: Thảo luáºn edit: title: Chỉnh sá»a bá»™ lá»c errors: @@ -817,11 +880,11 @@ vi: footer: developers: Nhà phát triển more: Nhiá»u hÆ¡n - resources: Äá»c + resources: Quy tắc trending_now: Xu hướng generic: all: Tất cả - changes_saved_msg: Thay đổi được lưu thà nh công! + changes_saved_msg: Äã cáºp nháºt thay đổi xong! copy: Sao chép delete: Xóa no_batch_actions_available: Không có sẵn hà nh động hà ng loạt trên trang nà y @@ -841,7 +904,7 @@ vi: invalid_token: Mã đăng nháºp Keybase giống như chữ ký số và phải đảm bảo 66 ký tá»± hex verification_failed: Keybase không nháºn ra mã đăng nháºp nà y là chữ ký cá»§a ngưá»i dùng Keybase %{kb_username}. Vui lòng thá» lại từ Keybase. wrong_user: Không thể tạo bằng chứng cho %{proving} trong khi đăng nháºp là %{current}. Äăng nháºp bằng %{proving} và thá» lại. - explanation_html: Tại đây, bạn có thể kết nối máºt mã các danh tÃnh khác cá»§a mình, chẳng hạn như hồ sÆ¡ Keybase. Äiá»u nà y cho phép ngưá»i khác gá»i cho bạn tin nhắn được mã hóa và tin tưởng ná»™i dung bạn gá»i cho há». + explanation_html: Tại đây, bạn có thể kết nối mã hóa tà i khoản cá»§a bạn trên các ná»n tảng khác, chẳng hạn như Keybase. Äiá»u nà y cho phép ngưá»i khác gá»i cho bạn tin nhắn được mã hóa và tin tưởng ná»™i dung bạn gá»i cho há». i_am_html: Tôi là %{username} trên %{service}. identity: Danh tÃnh inactive: Không hoạt động @@ -852,6 +915,8 @@ vi: status: Tình trạng xác minh view_proof: Xem bằng chứng imports: + errors: + over_rows_processing_limit: chứa nhiá»u hÆ¡n %{count} hà ng modes: merge: Hợp nhất merge_long: Giữ hồ sÆ¡ hiện có và thêm hồ sÆ¡ má»›i @@ -861,9 +926,10 @@ vi: success: Dữ liệu cá»§a bạn đã được tải lên thà nh công và hiện Ä‘ang xá» lý types: blocking: Danh sách chặn + bookmarks: Äã lưu domain_blocking: Danh sách máy chá»§ đã chặn following: Danh sách ngưá»i theo dõi - muting: Danh sách ngưá»i dùng ẩn + muting: Danh sách ngưá»i đã ẩn upload: Tải lên in_memoriam_html: Tưởng Niệm invites: @@ -876,11 +942,11 @@ vi: '43200': 12 giá» '604800': 1 tuần '86400': 1 ngà y - expires_in_prompt: Không bao giá» + expires_in_prompt: Không giá»›i hạn generate: Tạo lá»i má»i invited_by: 'Bạn đã được má»i bởi:' max_uses: - other: "%{count} sá» dụng" + other: "%{count} lần dùng" max_uses_prompt: Không giá»›i hạn prompt: Tạo và chia sẻ liên kết vá»›i những ngưá»i khác để cấp quyá»n truy cáºp và o máy chá»§ nà y table: @@ -911,44 +977,44 @@ vi: incoming_migrations_html: Äể chuyển từ tà i khoản khác sang tà i khoản nà y, trước tiên bạn cần <a href="%{path}">tạo tham chiếu tà i khoản</a>. moved_msg: Tà i khoản cá»§a bạn hiện Ä‘ang chuyển hướng đến %{acct} và những ngưá»i theo dõi bạn cÅ©ng sẽ được chuyển Ä‘i. not_redirecting: Tà i khoản cá»§a bạn hiện không chuyển hướng đến bất kỳ tà i khoản nà o khác. - on_cooldown: Gần đây bạn đã di chuyển tà i khoản cá»§a bạn. Chức năng nà y sẽ trở nên khả dụng má»™t lần nữa sau %{count} ngà y. + on_cooldown: Bạn vừa má»›i chuyển tà i khoản cá»§a bạn Ä‘i nÆ¡i khác. Chỉ có thể sá» dụng tiếp tÃnh năng nà y sau %{count} ngà y. past_migrations: Những lần dá»i nhà cÅ© proceed_with_move: Chuyển hướng ngưá»i theo dõi redirected_msg: Tà i khoản cá»§a bạn đã chuyển hướng đến %{acct}. redirecting_to: Tà i khoản cá»§a bạn Ä‘ang chuyển hướng đến %{acct}. set_redirect: Thiết láºp chuyển hướng warning: - backreference_required: Tà i khoản má»›i trước tiên phải được cấu hình để tham chiếu lại tà i khoản nà y + backreference_required: Bạn cần phải đăng ký tà i khoản má»›i ở máy chá»§ khác trước before: 'Trước khi tiếp tục, xin vui lòng Ä‘á»c các lưu ý:' - cooldown: Sau khi di chuyển, có thá»i gian chiêu hồi, trong đó bạn sẽ không thể di chuyển nữa - disabled_account: Tà i khoản hiện tại cá»§a bạn sẽ không thể sá» dụng đầy đủ sau đó. Tuy nhiên, bạn sẽ có quyá»n truy cáºp để xuất dữ liệu cÅ©ng như kÃch hoạt lại. + cooldown: Bạn sẽ bị hạn chế chuyển sang tà i khoản má»›i trong thá»i gian sắp tá»›i + disabled_account: Tà i khoản nà y sẽ không thể tiếp tục dùng nữa. Tuy nhiên, bạn có quyá»n truy cáºp để xuất dữ liệu cÅ©ng như kÃch hoạt lại. followers: Hà nh động nà y sẽ chuyển tất cả ngưá»i theo dõi từ tà i khoản hiện tại sang tà i khoản má»›i only_redirect_html: Ngoà i ra, bạn có thể <a href="%{path}">đặt chuyển hướng trên trang cá nhân cá»§a bạn</a>. other_data: Dữ liệu khác sẽ không được di chuyển tá»± động - redirect: Trang cá nhân hiện tại cá»§a bạn sẽ được cáºp nháºt vá»›i thông báo chuyển hướng và bị loại khá»i các tìm kiếm + redirect: Trang cá nhân hiện tại cá»§a bạn sẽ hiển thị thông báo chuyển hướng và bị loại khá»i kết quả tìm kiếm moderation: title: Kiểm duyệt move_handler: carry_blocks_over_text: Tà i khoản nà y chuyển từ %{acct}, máy chá»§ mà bạn đã chặn trước đó. carry_mutes_over_text: Tà i khoản nà y chuyển từ %{acct}, máy chá»§ mà bạn đã ẩn trước đó. - copy_account_note_text: 'Tà i khoản nà y chuyển từ %{acct}, đây là ghi chú vá» há» trước đó:' + copy_account_note_text: 'Tà i khoản nà y chuyển từ %{acct}, đây là lịch sá» kiểm duyệt cá»§a há»:' notification_mailer: digest: action: Xem toà n bá»™ thông báo body: Dưới đây là những tin nhắn bạn đã bá» lỡ kể từ lần truy cáºp trước và o %{since} - mention: "%{name} vừa nhắc đến bạn trong:" + mention: "%{name} nhắc đến bạn trong:" new_followers_summary: other: Ngoà i ra, bạn đã có %{count} ngưá»i theo dõi má»›i trong khi Ä‘i chÆ¡i! Ngạc nhiên chưa! subject: other: "%{count} thông báo má»›i kể từ lần truy cáºp trước \U0001F418" title: Khi bạn offline... favourite: - body: Tút cá»§a bạn vừa được %{name} tâm đắc - subject: "%{name} vừa tâm đắc tút cá»§a bạn" - title: Lượt tâm đắc má»›i + body: Tút cá»§a bạn vừa được thÃch bởi %{name} + subject: "%{name} vừa thÃch tút cá»§a bạn" + title: Lượt thÃch má»›i follow: - body: Bạn vừa má»›i được %{name} theo dõi - subject: "%{name} vừa má»›i theo dõi bạn" + body: Bạn vừa được %{name} theo dõi! + subject: "%{name} vừa theo dõi bạn" title: Ngưá»i theo dõi má»›i follow_request: action: Quản lý yêu cầu theo dõi @@ -967,7 +1033,7 @@ vi: notifications: email_events: Email email_events_hint: 'Chá»n những hoạt động sẽ gá»i thông báo qua email:' - other_settings: Cà i đặt thông báo khác + other_settings: Thông báo khác number: human: decimal_units: @@ -978,6 +1044,14 @@ vi: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: Nháºp mã được tạo bởi ứng dụng xác thá»±c cá»§a bạn để xác nháºn + description_html: Nếu kÃch hoạt <strong>xác thá»±c hai bước</strong> thông qua ứng dụng, bạn sẽ đăng nháºp bằng mã token được tạo bởi chÃnh Ä‘iện thoại cá»§a bạn. + enable: KÃch hoạt + instructions_html: "<strong>Quét mã QR bằng Google Authenticator hoặc má»™t ứng dụng TOTP tương tá»± trên Ä‘iện thoại cá»§a bạn</strong>. Kể từ bây giá», ứng dụng đó sẽ tạo những token để bạn đăng nháºp." + manual_instructions: 'Nếu bạn không thể quét mã QR, đây sẽ là dòng chữ gợi ý:' + setup: Thiết láºp + wrong_code: Mã vừa nháºp không chÃnh xác! Thá»i gian máy chá»§ và thá»i gian thiết bị chÃnh xác chưa? pagination: newer: Má»›i hÆ¡n next: Kế tiếp @@ -986,11 +1060,11 @@ vi: truncate: "…" polls: errors: - already_voted: Bạn đã bình chá»n trong cuá»™c thăm dò nà y + already_voted: Bạn đã bình chá»n xong rồi duplicate_options: chứa các lá»±a chá»n trùng lặp duration_too_long: quá xa so vá»›i thá»i Ä‘iểm hiện tại duration_too_short: quá sá»›m - expired: Cuá»™c thăm dò đã kết thúc + expired: Cuá»™c bình chá»n đã kết thúc invalid_choice: Lá»±a chá»n không tồn tại over_character_limit: độ dà i tối Ä‘a %{max} ký tá»± too_few_options: phải có nhiá»u hÆ¡n má»™t mục @@ -1005,31 +1079,32 @@ vi: unrecognized_emoji: không phải là emoji relationships: activity: Hoạt động tà i khoản - dormant: Không có tương tác - followers: Ngưá»i nà y Ä‘ang theo dõi bạn - following: Bạn Ä‘ang theo dõi ngưá»i nà y - invited: Ngưá»i bạn má»i đăng ký + dormant: Chưa tương tác + follow_selected_followers: Theo dõi những ngưá»i đã chá»n + followers: Ngưá»i theo dõi + following: Äang theo dõi + invited: Äã má»i last_active: Hoạt động lần cuối - most_recent: Gần đây nhất - moved: Dá»i sang - mutual: Bằng Hữu - primary: SÆ¡ cấp + most_recent: Má»›i nhất + moved: Äã xóa + mutual: Äồng thá»i + primary: Bình thưá»ng relationship: Mối quan hệ remove_selected_domains: Xóa hết ngưá»i theo dõi từ các máy chá»§ đã chá»n remove_selected_followers: Xóa những ngưá»i theo dõi đã chá»n - remove_selected_follows: Há»§y theo dõi ngưá»i dùng đã chá»n - status: Tình trạng tà i khoản + remove_selected_follows: Ngưng theo dõi những ngưá»i đã chá»n + status: Trạng thái tà i khoản remote_follow: acct: Nháºp địa chỉ Mastodon cá»§a bạn (tên@máy chá»§) - missing_resource: Không thể tìm thấy URL chuyển hướng cần thiết cho tà i khoản cá»§a bạn - no_account_html: Nếu chưa có tà i khoản, bạn có thể <a href='%{sign_up_path}' target='_blank'>đăng ký tại đây</a> - proceed: Tiến hà nh theo - prompt: 'Bạn sắp theo dõi:' + missing_resource: Không tìm thấy URL chuyển hướng cho tà i khoản cá»§a bạn + no_account_html: Nếu chưa có tà i khoản, hãy <a href='%{sign_up_path}' target='_blank'>đăng ký</a> + proceed: Theo dõi + prompt: 'Bạn vừa yêu cầu theo dõi:' reason_html: "<strong>Tại sao bước nà y là cần thiết?</strong> <code>%{instance}</code> có thể không phải là máy chá»§ nÆ¡i bạn đã đăng ký, vì váºy chúng tôi cần chuyển hướng bạn đến máy chá»§ cá»§a bạn trước." remote_interaction: favourite: - proceed: Yêu thÃch tút nà y - prompt: Bạn có muốn tâm đắc tút nà y? + proceed: ThÃch tút + prompt: 'Bạn muốn thÃch tút nà y:' reblog: proceed: Tiếp tục chia sẻ prompt: Bạn có muốn chia sẻ tút nà y? @@ -1041,7 +1116,7 @@ vi: over_total_limit: Bạn đã vượt quá giá»›i hạn %{limit} cá»§a các tút được lên lịch too_soon: Ngà y lên lịch phải trong tương lai sessions: - activity: Hoạt động cuối + activity: Gần đây nhất browser: Trình duyệt browsers: alipay: Alipay @@ -1063,7 +1138,7 @@ vi: weibo: Weibo current_session: Phiên hiện tại description: "%{browser} trên %{platform}" - explanation: Äây là các trình duyệt web sá» dụng để đăng nháºp và o tà i khoản Mastodon cá»§a bạn. + explanation: Äây là các trình duyệt web đã từng đăng nháºp và o tà i khoản Mastodon cá»§a bạn. ip: IP platforms: adobe_air: Adobe Air @@ -1078,36 +1153,37 @@ vi: windows: Windows windows_mobile: Windows Mobile windows_phone: Äiện thoại Windows - revoke: Thu hồi - revoke_success: Thu hồi phiên thà nh công + revoke: Gỡ + revoke_success: Gỡ phiên thà nh công title: Phiên settings: - account: Tà i khoản + account: Bảo máºt account_settings: Cà i đặt tà i khoản - aliases: Äịnh danh tà i khoản + aliases: Kết nối tà i khoản appearance: Giao diện - authorized_apps: App đã sá» dụng + authorized_apps: App đã dùng back: Quay lại Mastodon delete: Xóa tà i khoản - development: Phát triển - edit_profile: Chỉnh sá»a trang cá nhân + development: Láºp trình + edit_profile: Cá nhân hóa export: Xuất dữ liệu featured_tags: Hashtags thưá»ng dùng identity_proofs: Bằng chứng nháºn dạng import: Nháºp dữ liệu - import_and_export: Nháºp và xuất dữ liệu + import_and_export: Dữ liệu migrate: Chuyển tà i khoản sang máy chá»§ khác notifications: Thông báo preferences: Chung profile: Trang cá nhân relationships: Lượt theo dõi two_factor_authentication: Xác thá»±c hai bước + webauthn_authentication: Khóa bảo máºt spam_check: spam_detected: Äây là má»™t báo cáo tá»± động. Äã phát hiện thư rác. statuses: attached: audio: - other: "%{count} bà i hát" + other: "%{count} âm thanh" description: 'ÄÃnh kèm: %{attached}' image: other: "%{count} hình ảnh" @@ -1120,7 +1196,7 @@ vi: errors: in_reply_not_found: Bạn Ä‘ang trả lá»i má»™t tút không còn tồn tại. language_detection: Tá»± động phát hiện ngôn ngữ - open_in_web: Mở trên web + open_in_web: Xem trong Mastodon over_character_limit: vượt quá giá»›i hạn %{max} ký tá»± pin_errors: limit: Bạn đã ghim quá số lượng tút cho phép @@ -1131,19 +1207,21 @@ vi: total_people: other: "%{count} ngưá»i" total_votes: - other: "%{count} bình chá»n" - vote: Cuá»™c thăm dò - show_more: Xem thêm - show_thread: Nguyên văn - sign_in_to_participate: Äăng nháºp để tham gia và o cuá»™c trò chuyện + other: "%{count} ngưá»i" + vote: Bình chá»n + show_more: Äá»c thêm + show_newer: Má»›i hÆ¡n + show_older: CÅ© hÆ¡n + show_thread: Toà n bá»™ chá»§ đỠ+ sign_in_to_participate: Äăng nháºp để trả lá»i chá»§ đỠnà y title: '%{name}: "%{quote}"' visibilities: - private: Äóng + private: Ngưá»i theo dõi private_long: Chỉ ngưá»i theo dõi má»›i xem được tút public: Công khai public_long: Ai cÅ©ng có thể thấy - unlisted: Mở - unlisted_long: Ai cÅ©ng có thể xem nhưng không hiện trên bảng tin máy chá»§ + unlisted: Riêng tư + unlisted_long: Không hiện trên bảng tin máy chá»§ stream_entries: pinned: Tút được ghim reblogged: chia sẻ @@ -1151,7 +1229,54 @@ vi: tags: does_not_match_previous_name: không khá»›p vá»›i tên trước terms: - body_html: "<h2> ChÃnh sách bảo máºt </h2><h3 id=\"collect\"> Chúng ta đã thu tháºp được thông tin gì rồi? </h3><ul><li> <em>Thông tin tà i khoản cÆ¡ bản</em> : Nếu bạn đăng ký trên máy chá»§ nà y, bạn có thể được yêu cầu nháºp tên ngưá»i dùng, địa chỉ email và máºt khẩu. Bạn cÅ©ng có thể nháºp thông tin hồ sÆ¡ bổ sung như tên hiển thị và tiểu sá» và tải lên hình ảnh hồ sÆ¡ và hình ảnh tiêu Ä‘á». Tên ngưá»i dùng, tên hiển thị, tiểu sá», ảnh hồ sÆ¡ và hình ảnh tiêu đỠluôn được liệt kê công khai. </li><li> <em>Bà i đăng, theo dõi và thông tin công khai khác</em> : Danh sách những ngưá»i bạn theo dõi được liệt kê công khai, Ä‘iá»u nà y cÅ©ng đúng vá»›i những ngưá»i theo dõi bạn. Khi bạn gá»i tin nhắn, ngà y và giỠđược lưu trữ cÅ©ng như ứng dụng bạn đã gá»i tin nhắn từ đó. Tin nhắn có thể chứa tệp Ä‘Ãnh kèm phương tiện, chẳng hạn như hình ảnh và video. Bà i viết công khai và chưa niêm yết có sẵn công khai. Khi bạn có má»™t bà i đăng trên hồ sÆ¡ cá»§a bạn, đó cÅ©ng là thông tin có sẵn công khai. Bà i đăng cá»§a bạn được gá»i đến những ngưá»i theo dõi cá»§a bạn, trong má»™t số trưá»ng hợp, Ä‘iá»u đó có nghÄ©a là chúng được gá»i đến các máy chá»§ khác nhau và các bản sao được lưu trữ ở đó. Khi bạn xóa bà i viết, Ä‘iá»u nà y cÅ©ng được gá»i đến những ngưá»i theo dõi cá»§a bạn. Hà nh động đăng ký lại hoặc yêu thÃch má»™t bà i đăng khác luôn được công khai. </li><li> <em>Bà i đăng trá»±c tiếp và chỉ dà nh cho ngưá»i theo dõi</em> : Tất cả các bà i đăng được lưu trữ và xá» lý trên máy chá»§. Các bà i đăng chỉ dà nh cho ngưá»i theo dõi được gá»i đến những ngưá»i theo dõi và ngưá»i dùng cá»§a bạn được đỠcáºp trong đó và các bà i đăng trá»±c tiếp chỉ được gá»i cho ngưá»i dùng được đỠcáºp trong đó. Trong má»™t số trưá»ng hợp, Ä‘iá»u đó có nghÄ©a là chúng được gá»i đến các máy chá»§ khác nhau và các bản sao được lưu trữ ở đó. Chúng tôi thá»±c hiện má»™t ná»— lá»±c thiện chà để giá»›i hạn quyá»n truy cáºp và o các bà i đăng đó chỉ cho những ngưá»i được á»§y quyá»n, nhưng các máy chá»§ khác có thể không là m như váºy. Do đó, Ä‘iá»u quan trá»ng là phải xem xét các máy chá»§ mà ngưá»i theo dõi cá»§a bạn thuá»™c vá». Bạn có thể chuyển đổi tùy chá»n để phê duyệt và từ chối ngưá»i theo dõi má»›i theo cách thá»§ công trong cà i đặt. <em>Xin lưu ý rằng các nhà khai thác cá»§a máy chá»§ và bất kỳ máy chá»§ nháºn nà o cÅ©ng có thể xem các tin nhắn</em> đó và ngưá»i nháºn có thể chụp mà n hình, sao chép hoặc chia sẻ lại chúng. <em>Không chia sẻ bất kỳ thông tin nguy hiểm nà o trên Mastodon.</em> </li><li> <em>IP và siêu dữ liệu khác</em> : Khi bạn đăng nháºp, chúng tôi ghi lại địa chỉ IP bạn đăng nháºp, cÅ©ng như tên cá»§a ứng dụng trình duyệt cá»§a bạn. Tất cả các phiên đăng nháºp có sẵn để bạn xem xét và há»§y bá» trong cà i đặt. Äịa chỉ IP má»›i nhất được sá» dụng được lưu trữ tối Ä‘a 12 tháng. Chúng tôi cÅ©ng có thể giữ lại nháºt ký máy chá»§ bao gồm địa chỉ IP cá»§a má»i yêu cầu đến máy chá»§ cá»§a chúng tôi. </li></ul><hr class=\"spacer\" /><h3 id=\"use\"> Chúng tôi sá» dụng thông tin cá»§a bạn để là m gì? </h3><p> Bất kỳ thông tin nà o chúng tôi thu tháºp từ bạn có thể được sá» dụng theo các cách sau: </p><ul><li> Äể cung cấp các chức năng cốt lõi cá»§a Mastodon. Bạn chỉ có thể tương tác vá»›i ná»™i dung cá»§a ngưá»i khác và đăng ná»™i dung cá»§a riêng bạn khi bạn đăng nháºp. Và dụ: bạn có thể theo dõi ngưá»i khác để xem các bà i đăng kết hợp cá»§a há» trong dòng thá»i gian tại nhà được cá nhân hóa cá»§a bạn. </li><li> Äể há»— trợ kiểm duyệt cá»™ng đồng, và dụ so sánh địa chỉ IP cá»§a bạn vá»›i các địa chỉ đã biết khác để xác định trốn tránh hoặc vi phạm khác. </li><li> Äịa chỉ email bạn cung cấp có thể được sá» dụng để gá»i cho bạn thông tin, thông báo vá» những ngưá»i khác tương tác vá»›i ná»™i dung cá»§a bạn hoặc gá»i tin nhắn cho bạn và để trả lá»i các câu há»i cÅ©ng như / hoặc các yêu cầu hoặc câu há»i khác. </li></ul><hr class=\"spacer\" /><h3 id=\"protect\"> Là m thế nà o để chúng tôi bảo vệ thông tin cá»§a bạn? </h3><p> Chúng tôi thá»±c hiện nhiá»u biện pháp bảo máºt để duy trì sá»± an toà n cá»§a thông tin cá nhân cá»§a bạn khi bạn nháºp, gá»i hoặc truy cáºp thông tin cá nhân cá»§a bạn. Trong số những thứ khác, phiên trình duyệt cá»§a bạn, cÅ©ng như lưu lượng giữa các ứng dụng và API cá»§a bạn, được bảo máºt bằng SSL và máºt khẩu cá»§a bạn được băm bằng thuáºt toán má»™t chiá»u mạnh mẽ. Bạn có thể kÃch hoạt xác thá»±c hai yếu tố để tiếp tục truy cáºp an toà n và o tà i khoản cá»§a mình. </p><hr class=\"spacer\" /><h3 id=\"data-retention\"> ChÃnh sách lưu giữ dữ liệu cá»§a chúng tôi là gì? </h3><p> Chúng tôi sẽ thá»±c hiện má»™t ná»— lá»±c đức tin tốt để: </p><ul><li> Giữ lại nháºt ký máy chá»§ chứa địa chỉ IP cá»§a tất cả các yêu cầu đến máy chá»§ nà y, cho đến khi các nháºt ký đó được lưu giữ, không quá 90 ngà y. </li><li> Giữ lại các địa chỉ IP được liên kết vá»›i ngưá»i dùng đã đăng ký không quá 12 tháng. </li></ul><p> Bạn có thể yêu cầu và tải xuống má»™t kho lưu trữ ná»™i dung cá»§a bạn, bao gồm các bà i đăng, tệp Ä‘Ãnh kèm phương tiện, ảnh hồ sÆ¡ và hình ảnh tiêu Ä‘á». </p><p> Bạn có thể xóa tà i khoản cá»§a mình bất cứ lúc nà o. </p><hr class=\"spacer\"/><h3 id=\"cookies\"> Chúng ta có sá» dụng cookie không? </h3><p> Äúng. Cookies là các tệp nhá» mà má»™t trang web hoặc nhà cung cấp dịch vụ cá»§a nó chuyển và o ổ cứng máy tÃnh cá»§a bạn thông qua trình duyệt Web (nếu bạn cho phép). Những cookie nà y cho phép trang web nháºn ra trình duyệt cá»§a bạn và , nếu bạn có tà i khoản đã đăng ký, hãy liên kết nó vá»›i tà i khoản đã đăng ký cá»§a bạn. </p><p> Chúng tôi sá» dụng cookie để hiểu và lưu các tùy chá»n cá»§a bạn cho các lần truy cáºp trong tương lai. </p><hr class=\"spacer\" /><h3 id=\"disclose\"> Chúng tôi có được công bố bất cứ thông tin nà o ra bên ngoà i không? </h3><p> Chúng tôi không bán, trao đổi hoặc chuyển nhượng cho các bên ngoà i thông tin nháºn dạng cá nhân cá»§a bạn. Äiá»u nà y không bao gồm các bên thứ ba đáng tin cáºy há»— trợ chúng tôi Ä‘iá»u hà nh trang web cá»§a chúng tôi, tiến hà nh kinh doanh hoặc phục vụ bạn, miá»…n là các bên đó đồng ý giữ bà máºt thông tin nà y. Chúng tôi cÅ©ng có thể tiết lá»™ thông tin cá»§a bạn khi chúng tôi tin rằng việc phát hà nh là phù hợp để tuân thá»§ luáºt pháp, thá»±c thi chÃnh sách trang web cá»§a chúng tôi hoặc bảo vệ quyá»n, tà i sản hoặc an toà n cá»§a chúng tôi hoặc cá»§a ngưá»i khác. </p><p> Ná»™i dung công khai cá»§a bạn có thể được tải xuống bởi các máy chá»§ khác trong mạng. Các bà i đăng công khai và chỉ dà nh cho ngưá»i theo dõi cá»§a bạn được gá»i đến các máy chá»§ nÆ¡i ngưá»i theo dõi cá»§a bạn cư trú và tin nhắn trá»±c tiếp được gá»i đến máy chá»§ cá»§a ngưá»i nháºn, cho đến khi những ngưá»i theo dõi hoặc ngưá»i nháºn đó cư trú trên má»™t máy chá»§ khác vá»›i máy chá»§ nà y. </p><p> Khi bạn cho phép ứng dụng sá» dụng tà i khoản cá»§a mình, tùy thuá»™c và o phạm vi quyá»n bạn phê duyệt, ứng dụng có thể truy cáºp thông tin hồ sÆ¡ công khai, danh sách sau đây, ngưá»i theo dõi, danh sách cá»§a bạn, tất cả bà i đăng và mục yêu thÃch cá»§a bạn. Các ứng dụng không bao giá» có thể truy cáºp địa chỉ e-mail hoặc máºt khẩu cá»§a bạn. </p><hr class=\"spacer\" /><h3 id=\"children\"> Sá» dụng trang web cá»§a trẻ em </h3><p> Nếu máy chá»§ nà y ở EU hoặc EEA: Trang web cá»§a chúng tôi, các sản phẩm và dịch vụ Ä‘á»u hướng đến những ngưá»i Ãt nhất 16 tuổi. Nếu bạn dưới 16 tuổi, theo các yêu cầu cá»§a GDPR ( <a href=\"https://en.wikipedia.org/wiki/General_Data_Protection_Regulation\">Quy định bảo vệ dữ liệu chung</a> ) không sá» dụng trang web nà y. </p><p> Nếu máy chá»§ nà y ở Hoa Kỳ: Trang web cá»§a chúng tôi, các sản phẩm và dịch vụ Ä‘á»u hướng đến những ngưá»i Ãt nhất 13 tuổi. Nếu bạn dưới 13 tuổi, theo các yêu cầu cá»§a COPPA ( <a href=\"https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act\">Äạo luáºt bảo vệ quyá»n riêng tư trá»±c tuyến cá»§a trẻ em</a> ) không sá» dụng trang web nà y. </p><p> Yêu cầu pháp luáºt có thể khác nhau nếu máy chá»§ nà y ở khu vá»±c tà i phán khác. </p><hr class=\"spacer\" /><h3 id=\"changes\"> Thay đổi chÃnh sách bảo máºt cá»§a chúng tôi </h3><p> Nếu chúng tôi quyết định thay đổi chÃnh sách bảo máºt cá»§a mình, chúng tôi sẽ đăng những thay đổi đó trên trang nà y. </p><p> Tà i liệu nà y là CC-BY-SA. Nó được cáºp nháºt lần cuối và o ngà y 7 tháng 3 năm 2018. </p><p> Ban đầu được Ä‘iá»u chỉnh từ <a href=\"https://github.com/discourse/discourse\">chÃnh sách quyá»n riêng tư cá»§a Nghị luáºn</a> . </p> \n" + body_html: | + <h2>ChÃnh sách bảo máºt</h2> + <h3 id="collect">Chúng tôi thu tháºp những thông tin gì?</h3> + + <ul> + <li><em>Thông tin tà i khoản cÆ¡ bản</em>: Nếu bạn đăng ký trên máy chá»§ nà y, bạn phải cung cấp tên ngưá»i dùng, địa chỉ email và máºt khẩu. Bạn cÅ©ng có thể tùy chá»n bổ sung tên hiển thị, mô tả, ảnh đại diện, ảnh bìa. Tên ngưá»i dùng, tên hiển thị, mô tả, ảnh hồ sÆ¡ và ảnh bìa luôn được hiển thị công khai.</li> + <li><em>Tút, lượt theo dõi và ná»™i dung công khai khác</em>: Danh sách những ngưá»i bạn theo dõi được liệt kê công khai, cÅ©ng tương tá»± như danh sách những ngưá»i theo dõi bạn. Khi bạn đăng tút, ngà y giá» và ứng dụng sá» dụng được lưu trữ. Tút có thể chứa tệp Ä‘Ãnh kèm hình ảnh và video. Tút công khai và tút mở sẽ hiển thị công khai. Khi bạn đăng má»™t tút trên trang cá nhân cá»§a bạn, đó là ná»™i dung công khai. Tút cá»§a bạn sẽ gá»i đến những ngưá»i theo dõi cá»§a bạn, đồng nghÄ©a vá»›i việc sẽ có các bản sao được lưu trữ ở máy chá»§ cá»§a há». Khi bạn xóa bà i viết, bản sao từ những ngưá»i theo dõi cá»§a bạn cÅ©ng bị xóa theo. Hà nh động chia sẻ hoặc thÃch má»™t tút luôn luôn là công khai.</li> + <li><em>Tin nhắn và tút dà nh cho ngưá»i theo dõi</em>: Tất cả tút được lưu trữ và xá» lý trên máy chá»§. Các tút dà nh cho ngưá»i theo dõi được gá»i đến những ngưá»i theo dõi và những ngưá»i được gắn thẻ trong tút. Còn các tin nhắn chỉ được gá»i đến cho ngưá»i nháºn. Äiá»u đó có nghÄ©a là chúng được gá»i đến các máy chá»§ khác nhau và có các bản sao được lưu trữ ở đó. Chúng tôi đỠnghị chỉ cho những ngưá»i được á»§y quyá»n truy cáºp và o đó, nhưng không phải máy chá»§ nà o cÅ©ng là m như váºy. Do đó, Ä‘iá»u quan trá»ng là phải xem xét kỹ máy chá»§ cá»§a ngưá»i theo dõi cá»§a bạn. Bạn có thể thiết láºp tá»± mình phê duyệt và từ chối ngưá»i theo dõi má»›i trong cà i đặt. <em>Xin lưu ý rằng quản trị viên máy chá»§ cá»§a bạn và bất kỳ máy chá»§ cá»§a ngưá»i nháºn nà o cÅ©ng có thể xem các tin nhắn</em>. Ngưá»i nháºn tin nhắn có thể chụp mà n hình, sao chép hoặc chia sẻ lại chúng. <em>Không nên chia sẻ bất kỳ thông tin rá»§i ro nà o trên Mastodon.</em></li> + <li> <em>Äịa chỉ IP và siêu dữ liệu khác</em>: Khi bạn đăng nháºp, chúng tôi ghi nhá»› địa chỉ IP đăng nháºp cÅ©ng như tên trình duyệt cá»§a bạn. Tất cả các phiên đăng nháºp sẽ để bạn xem xét và há»§y bá» trong phần cà i đặt. Äịa chỉ IP sá» dụng được lưu trữ tối Ä‘a 12 tháng. Chúng tôi cÅ©ng có thể giữ lại nháºt ký máy chá»§ bao gồm địa chỉ IP cá»§a những lượt đăng ký tà i khoản trên máy chá»§ cá»§a chúng tôi. </li> + </ul><hr class="spacer" /> + <h3 id="use"> Chúng tôi sá» dụng thông tin cá»§a bạn để là m gì? </h3> + <p> Bất kỳ thông tin nà o chúng tôi thu tháºp từ bạn là : </p> + <ul> + <li>Äể cung cấp các chức năng cốt lõi cá»§a Mastodon. Sau khi đăng nháºp, bạn má»›i có thể tương tác vá»›i ná»™i dung cá»§a ngưá»i khác và đăng ná»™i dung cá»§a riêng bạn. Và dụ: bạn có thể theo dõi ngưá»i khác để xem các tút cá»§a há» trong bảng tin cá»§a bạn.</li> + <li>Äể há»— trợ kiểm duyệt. Và dụ so sánh địa chỉ IP cá»§a bạn vá»›i các địa chỉ đã biết khác để xác định hacker hoặc spammer.</li> + <li>Äịa chỉ email bạn cung cấp chỉ được sá» dụng để gá»i các thông báo quan trá»ng, trả lá»i các câu há»i cÅ©ng như yêu cầu khác từ chÃnh bạn.</li> + </ul> + <hr class="spacer" /> + <h3 id="protect">Chúng tôi bảo vệ thông tin cá»§a bạn như thế nà o? </h3> + <p>Chúng tôi thá»±c hiện nhiá»u biện pháp để duy trì sá»± an toà n khi bạn nháºp, gá»i hoặc truy cáºp thông tin cá nhân cá»§a bạn. Má»™t và i trong số đó như là kiểm soát phiên đăng nháºp cá»§a bạn, lưu lượng giữa các ứng dụng và API, bảo máºt bằng SSL và băm nhá» máºt khẩu nhá» thuáºt toán má»™t chiá»u mạnh mẽ. Bạn có thể kÃch hoạt xác thá»±c hai yếu tố để tiếp tục truy cáºp an toà n và o tà i khoản cá»§a mình.</p> + <hr class="spacer" /> + <h3 id="data-retention">Chúng tôi lưu trữ dữ liệu như thế nà o?</h3> + <p>Chúng tôi tiến hà nh:</p> + <ul> + <li>Giữ lại nháºt ký máy chá»§ chứa địa chỉ IP cá»§a tất cả các yêu cầu đến máy chá»§ nà y, cho đến khi các nháºt ký đó bị xóa Ä‘i trong vòng 90 ngà y.</li> + <li>Giữ lại các địa chỉ IP được liên kết vá»›i ngưá»i dùng đã đăng ký trong vòng 12 tháng.</li> + </ul> + <p>Bạn có thể tải xuống má»™t bản sao lưu trữ ná»™i dung cá»§a bạn, bao gồm các tút, tệp Ä‘Ãnh kèm phương tiện, ảnh đại diện và ảnh bìa.</p> + <p> Bạn có thể xóa tà i khoản cá»§a mình bất cứ lúc nà o.</p> + <hr class="spacer"/> + <h3 id="cookies">Chúng tôi có sá» dụng cookie không?</h3> + <p>Có. Cookie là các tệp nhá» mà má»™t trang web hoặc nhà cung cấp dịch vụ internet chuyển và o ổ cứng máy tÃnh cá»§a bạn thông qua trình duyệt Web (nếu bạn cho phép). Những cookie nà y cho phép trang web nháºn ra trình duyệt cá»§a bạn và nếu bạn có tà i khoản đã đăng ký, nó sẽ liên kết vá»›i tà i khoản đã đăng ký cá»§a bạn.</p> + <p> Chúng tôi sá» dụng cookie để hiểu và lưu các tùy chá»n cá»§a bạn cho các lần truy cáºp trong tương lai.</p> + <hr class="spacer" /> + <h3 id="disclose">Chúng tôi có tiết lá»™ bất cứ thông tin nà o ra ngoà i không?</h3> + <p>Chúng tôi không bán, trao đổi hoặc chuyển nhượng thông tin nháºn dạng cá nhân cá»§a bạn cho bên thứ ba. Trừ khi bên thứ ba đó Ä‘ang há»— trợ chúng tôi Ä‘iá»u hà nh Mastodon, tiến hà nh kinh doanh hoặc phục vụ bạn, miá»…n là các bên đó đồng ý giữ bà máºt thông tin nà y. Chúng tôi cÅ©ng có thể tiết lá»™ thông tin cá»§a bạn nếu việc công bố là để tuân thá»§ luáºt pháp, thá»±c thi quy tắc máy chá»§ cá»§a chúng tôi hoặc bảo vệ quyá»n, tà i sản hợp pháp hoặc sá»± an toà n cá»§a chúng tôi hoặc bất kỳ ai.</p> + <p>Ná»™i dung công khai cá»§a bạn có thể được tải xuống bởi các máy chá»§ khác trong mạng liên hợp. Các tút công khai hay dà nh cho ngưá»i theo dõi được gá»i đến các máy chá»§ nÆ¡i ngưá»i theo dõi cá»§a bạn là thà nh viên và tin nhắn được gá»i đến máy chá»§ cá»§a ngưá»i nháºn, cho đến khi những ngưá»i theo dõi hoặc ngưá»i nháºn đó chuyển sang má»™t máy chá»§ khác.</p> + <p>Nếu bạn cho phép má»™t ứng dụng sá» dụng tà i khoản cá»§a mình, tùy thuá»™c và o phạm vi quyá»n bạn phê duyệt, ứng dụng có thể truy cáºp thông tin trang cá nhân, danh sách ngưá»i theo dõi, danh sách cá»§a bạn, tất cả tút và lượt thÃch cá»§a bạn. Các ứng dụng không bao giá» có thể truy cáºp địa chỉ e-mail hoặc máºt khẩu cá»§a bạn.</p> + <hr class="spacer" /> + <h3 id="children">Cấm trẻ em sá» dụng</h3> + <p>Nếu máy chá»§ nà y ở EU hoặc EEA: Trang web cá»§a chúng tôi, các sản phẩm và dịch vụ Ä‘á»u hướng đến những ngưá»i trên 16 tuổi. Nếu bạn dưới 16 tuổi, theo yêu cầu cá»§a GDPR (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">Quy định bảo vệ dữ liệu chung</a>) thì không được sá» dụng trang web nà y. </p> + <p>Nếu máy chá»§ nà y ở Hoa Kỳ: Trang web cá»§a chúng tôi, các sản phẩm và dịch vụ Ä‘á»u hướng đến những ngưá»i trên 13 tuổi. Nếu bạn dưới 13 tuổi, theo yêu cầu cá»§a COPPA (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">Äạo luáºt bảo vệ quyá»n riêng tư trá»±c tuyến cá»§a trẻ em</a>) thì không được sá» dụng trang web nà y.</p> + <p>Quy định pháp luáºt có thể khác biệt nếu máy chá»§ nà y ở khu vá»±c địa lý khác.</p> + <hr class="spacer" /> + <h3 id="changes">Cáºp nháºt thay đổi</h3> + <p>Nếu có thay đổi chÃnh sách bảo máºt, chúng tôi sẽ đăng những thay đổi đó ở mục nà y.</p> + <p>Tà i liệu nà y phát hà nh dưới hình thức CC-BY-SA và được cáºp nháºt lần cuối và o ngà y 7 tháng 3 năm 2018.</p> + <p>Chỉnh sá»a và hoà n thiện từ <a href="https://github.com/discourse/discourse">Discourse</a>.</p> title: "%{instance} Äiá»u khoản dịch vụ và chÃnh sách bảo máºt" themes: contrast: Mastodon (Äá»™ tương phản cao) @@ -1159,24 +1284,23 @@ vi: mastodon-light: Mastodon (Sáng) time: formats: - default: lúc %H:%M %b %d năm%_Y + default: "%d.%m.%Y %H:%M" month: "%B %Y" two_factor_authentication: - code_hint: Nháºp mã được tạo bởi ứng dụng xác thá»±c cá»§a bạn để xác nháºn - description_html: Nếu bạn kÃch hoạt <strong>xác thá»±c hai bước</strong>, mã xác thá»±c đăng nháºp sẽ được tạo ra từ Ä‘iện thoại cá»§a bạn. + add: Thêm disable: Vô hiệu hóa - enable: KÃch hoạt + disabled_success: Äã vô hiệu hóa xác thá»±c hai bước + edit: Sá»a enabled: Äã kÃch hoạt xác thá»±c hai bước enabled_success: Xác thá»±c hai bước được kÃch hoạt thà nh công generate_recovery_codes: Tạo mã khôi phục - instructions_html: "<strong>Quét mã QR nà y và o Google Authenticator hoặc ứng dụng TOTP tương tá»± trên Ä‘iện thoại cá»§a bạn</strong>. Từ giá» trở Ä‘i, ứng dụng đó sẽ tạo mã thông báo mà bạn sẽ phải nháºp khi đăng nháºp." lost_recovery_codes: Mã khôi phục cho phép bạn lấy lại quyá»n truy cáºp và o tà i khoản cá»§a mình nếu bạn mất Ä‘iện thoại. Nếu bạn bị mất mã khôi phục, bạn có thể tạo lại chúng ở đây. Mã khôi phục cÅ© cá»§a bạn sẽ bị vô hiệu. - manual_instructions: 'Nếu bạn không thể quét mã QR và cần nháºp thá»§ công, đây là mã bà máºt:' + methods: Phương pháp xác thá»±c + otp: Ứng dụng xác thá»±c recovery_codes: Mã phục hồi dá»± phòng recovery_codes_regenerated: Mã khôi phục được phục hồi thà nh công - recovery_instructions_html: Nếu bạn bị mất Ä‘iện thoại, hãy sá» dụng má»™t trong các mã khôi phục bên dưới để lấy lại quyá»n truy cáºp và o tà i khoản cá»§a mình. <strong>Giữ mã khôi phục an toà n</strong>. Và dụ, bạn có thể in chúng ra giấy. - setup: Thiết láºp - wrong_code: Mã vừa nháºp không hợp lệ! Thá»i gian máy chá»§ và thá»i gian thiết bị có đúng không? + recovery_instructions_html: Nếu bạn bị mất Ä‘iện thoại, hãy dùng má»™t trong các mã khôi phục bên dưới để lấy lại quyá»n truy cáºp và o tà i khoản cá»§a mình. <strong>Giữ mã khôi phục an toà n</strong>. Và dụ, bạn có thể in chúng ra giấy. + webauthn: Khóa bảo máºt user_mailer: backup_ready: explanation: Bạn đã yêu cầu sao lưu toà n bá»™ tà i khoản Mastodon cá»§a mình. Bây giá» có thể tải vá»! @@ -1190,20 +1314,23 @@ vi: title: Äăng nháºp warning: explanation: - disable: Nếu tà i khoản cá»§a bạn bị đình chỉ, dữ liệu tà i khoản cá»§a bạn vẫn còn nguyên, nhưng bạn không thể thá»±c hiện bất kỳ hà nh động nà o cho đến khi được mở khóa. - silence: Nếu tà i khoản cá»§a bạn bị tạm ẩn, bạn có thể bị loại khá»i các bảng tin công khai, chỉ những ngưá»i đã theo dõi bạn má»›i thấy tút cá»§a bạn. Tuy nhiên, những ngưá»i khác vẫn có thể tiếp tục theo dõi bạn. - suspend: Tà i khoản cá»§a bạn đã bị vô hiệu hóa. Tất cả tút và táºp tin đã tải lên cá»§a bạn sẽ bị xóa khá»i máy chá»§ nà y lẫn các máy chá»§ nÆ¡i bạn có ngưá»i theo dõi. + disable: Bạn bị cấm đăng nháºp tà i khoản. Tuy nhiên, trang cá nhân và dữ liệu cá»§a bạn vẫn sẽ được giữ nguyên. + sensitive: Ảnh và video tải lên cá»§a bạn sẽ bị đánh dấu là nhạy cảm. + silence: Bạn vẫn có thể dùng tà i khoản cá»§a bạn. Tuy nhiên, chỉ có những ngưá»i Ä‘ang theo dõi bạn má»›i có thể thấy tút cá»§a bạn. Bạn sẽ bị loại khá»i danh sách cá»§a má»™t số ngưá»i. Những ngưá»i má»›i khác vẫn có thể theo dõi bạn bình thưá»ng. + suspend: Tà i khoản cá»§a bạn đã bị vô hiệu hóa. Tất cả tút và táºp tin mà bạn đã tải lên sẽ không thể truy cáºp được nữa. Bạn vẫn có thể đăng nháºp để yêu cầu tải vá» bản sao dữ liệu cá»§a bạn. Tuy nhiên, chúng tôi sẽ giữ lại má»™t và i dữ liệu để ngăn ngừa bạn trốn tránh trách nhiệm. get_in_touch: Bạn có thể trả lá»i e-mail nà y để liên hệ vá»›i đội ngÅ© cá»§a %{instance}. - review_server_policies: Xem lại chÃnh sách máy chá»§ + review_server_policies: Xem lại quy tắc cá»§a máy chá»§ statuses: 'Cụ thể, cho:' subject: disable: Tà i khoản %{acct} cá»§a bạn đã bị vô hiệu hóa none: Cảnh báo cho %{acct} + sensitive: Ảnh và video tải lên cá»§a %{acct} sẽ bị đánh dấu là nhạy cảm silence: Tà i khoản %{acct} cá»§a bạn đã bị tạm ẩn suspend: Tà i khoản %{acct} cá»§a bạn đã bị vô hiệu hóa title: disable: Tà i khoản bị đóng băng none: Cảnh báo + sensitive: Ảnh và video cá»§a bạn sẽ bị đánh dấu nhạy cảm silence: Tà i khoản bị tạm ẩn suspend: Toà i khoản bị vô hiệu hóa welcome: @@ -1215,18 +1342,20 @@ vi: full_handle: Tên đầy đủ cá»§a bạn full_handle_hint: Äây cÅ©ng là địa chỉ được dùng để tương tác vá»›i tất cả má»i ngưá»i. review_preferences_action: Tùy chỉnh giao diện - review_preferences_step: Tùy chỉnh má»i thứ! Chẳng hạn như chá»n loại email nà o bạn muốn nháºn hoặc trạng thái tút mà bạn muốn sá» dụng mặc định. Hãy tắt tá»± động phát GIF nếu bạn hay bị chóng mặt. + review_preferences_step: Tùy chỉnh má»i thứ! Chẳng hạn như chá»n loại email nà o bạn muốn nháºn hoặc trạng thái đăng tút mặc định mà bạn muốn dùng. Hãy tắt tá»± động phát GIF nếu bạn dá»… bị chóng mặt. subject: Chà o mừng đến vá»›i Mastodon - tip_federated_timeline: Mạng liên kết là má»™t dạng "liên hợp quốc" cá»§a Mastodon. Hiểu má»™t cách đơn giản, nó là những ngưá»i bạn đã theo dõi từ các máy chá»§ khác. - tip_following: Theo mặc định, bạn sẽ theo dõi (các) quản trị viên máy chá»§ cá»§a bạn. Äể tìm những ngưá»i thú vị hÆ¡n, hãy xem qua bảng tin và mạng liên kết. + tip_federated_timeline: Mạng liên hợp là má»™t dạng "liên hợp quốc" cá»§a Mastodon. Hiểu má»™t cách đơn giản, nó là những ngưá»i bạn đã theo dõi từ các máy chá»§ khác. + tip_following: Theo mặc định, bạn sẽ theo dõi (các) quản trị viên máy chá»§ cá»§a bạn. Äể tìm những ngưá»i thú vị hÆ¡n, hãy xem qua cá»™ng đồng và thế giá»›i. tip_local_timeline: Bảng tin là nÆ¡i hiện lên những tút công khai cá»§a thà nh viên %{instance}. Há» là những ngưá»i hà ng xóm trá»±c tiếp cá»§a bạn! tip_mobile_webapp: Nếu trình duyệt trên Ä‘iện thoại di động cá»§a bạn thêm Mastodon và o mà n hình chÃnh, bạn có thể nháºn được thông báo đẩy. Nó hoạt động gần giống như má»™t app Ä‘iện thoại! tips: Mẹo title: Xin chà o %{name}! users: + blocked_email_provider: Dịch vụ email nà y đã bị cấm follow_limit_reached: Bạn chỉ có thể theo dõi tối Ä‘a %{limit} ngưá»i generic_access_help_html: Gặp trục trặc vá»›i tà i khoản? Liên hệ %{email} để được trợ giúp invalid_email: Äịa chỉ email không hợp lệ + invalid_email_mx: Äịa chỉ email không tồn tại invalid_otp_token: Mã xác thá»±c hai bước không hợp lệ invalid_sign_in_token: Mã an toà n không hợp lệ otp_lost_help_html: Nếu bạn mất quyá»n truy cáºp và o cả hai, bạn có thể đăng nháºp bằng %{email} @@ -1236,3 +1365,20 @@ vi: verification: explanation_html: 'Bạn có thể <strong>xác minh mình là chá»§ sở hữu cá»§a các trang web ở đầu trang cá nhân cá»§a bạn</strong>. Äể xác minh, trang web <strong>phải</strong> chèn mã <code>rel="me"</code>. Ná»™i dung văn bản cá»§a liên kết không quan trá»ng. Äây là má»™t và dụ:' verification: Xác minh + webauthn_credentials: + add: Thêm khóa bảo máºt má»›i + create: + error: Có vấn đỠkhi thêm khóa bảo máºt. Xin thá» lại. + success: Äã thêm khóa bảo máºt má»›i thà nh công. + delete: Xóa + delete_confirmation: Bạn có chắc chắn muốn xóa khóa bảo máºt nà y? + description_html: Nếu bạn kÃch hoạt <strong>khóa bảo máºt</strong>, bạn sẽ cần dùng má»™t trong những khóa bảo máºt đó má»—i khi đăng nháºp. + destroy: + error: Có vấn đỠkhi xóa khóa bảo máºt. Xin thá» lại. + success: Äã xóa khóa bảo máºt thà nh công. + invalid_credential: Khóa bảo máºt không hợp lệ + nickname_hint: Nháºp tên má»›i cho khóa bảo máºt cá»§a bạn + not_enabled: Bạn chưa kÃch hoạt WebAuthn + not_supported: Trình duyệt cá»§a bạn không há»— trợ khóa bảo máºt + otp_required: Äể dùng khóa bảo máºt, trước tiên hãy kÃch hoạt xác thá»±c hai bước. + registered_on: Äăng ký và o %{date} diff --git a/config/locales/zgh.yml b/config/locales/zgh.yml new file mode 100644 index 0000000000000000000000000000000000000000..0123836ecfd294f9c0e85d7b20d3987ea4b875c6 --- /dev/null +++ b/config/locales/zgh.yml @@ -0,0 +1,157 @@ +--- +zgh: + about: + about_this: âµ–â´¼ + api: API + contact: ⴰⵎⵢⴰⵡⴰⴹ + learn_more: ⵙⵙⵠⵓⴳⴳⴰⵔ + status_count_after: + one: â´°â´·â´·â´°â´· + other: â´°â´·â´·â´°â´·âµ + unavailable_content_description: + domain: ⴰⵎⴰⴽⴽⴰⵢ + what_is_mastodon: ⵎⴰ'ⵢⴷ ⵉⴳⴰⵠⵎⴰⵙⵜⵔⴷⵓⵎ? + accounts: + follow: ⴹⴼⵕ + followers: + one: ⴰⵎⴹⴼⴰⵕ + other: ⵉⵎⴹⴼⴰⵕⵠ+ media: ⵉⵙâµâµ–ⵎⵉⵙⵠ+ never_active: ⵓⵙⴰⵔ + roles: + bot: ⴰⴱⵓⵜ + group: ⵜⴰⵔⴰⴱⴱⵓⵜ + unfollow: ⴽⴽⵙ ⴰⴹⴼⴼⵓⵕ + admin: + account_moderation_notes: + delete: ⴽⴽⵙ + accounts: + change_email: + label: âµ™âµâ´¼âµ ⵉⵎⴰⵢⵠ+ submit: âµ™âµâ´¼âµ ⵉⵎⴰⵢⵠ+ confirm: âµ™âµâµœâµŽ + delete: ⴽⴽⵙ ⵉⴼⵙⴽⴰ + deleted: ⵉⵜⵜⵡⴰⴽⴽⵙ + domain: ⵉⴳⵔ + edit: âµ™âµâ´¼âµ + email: ⵉⵎⴰⵢⵠ+ email_status: â´°â´·â´·â´°â´· ⵠⵢⵉâµâ´°âµ¢âµ + followers: ⵉⵎⴹⴼⴰⵕⵠ+ location: + all: ⵎⴰⵕⵕⴰ + local: ⴰⴷⵖⴰⵔⴰⵠ+ moderation: + all: ⵎⴰⵕⵕⴰ + public: ⴰⴳⴷⵓⴷⴰⵠ+ reject: ⴰⴳⵢ + roles: + user: ⵓâµâµ™âµ™âµ“ⵎⵔⵙ + title: ⵉⵎⵉⴹⴰâµâµ + web: ⵡⵉⴱ + action_logs: + action_types: + update_status: ⵙⴷⵖⵉ â´°â´·â´·â´°â´· + announcements: + live: ⵓⵙⵔⵉⴷ + custom_emojis: + by_domain: ⵉⴳⵔ + copy: âµ™âµâµ–âµ + delete: ⴽⴽⵙ + emoji: ⵉⵎⵓⵊⵉ + domain_blocks: + domain: ⵉⴳⵔ + email_domain_blocks: + add_new: âµ”âµâµ“ ⴰⵎⴰⵢâµâµ“ + delete: ⴽⴽⵙ + instances: + moderation: + all: ⵎⴰⵕⵕⴰ + ip_blocks: + delete: ⴽⴽⵙ + expires_in: + '1209600': 2 weeks + '15778476': 6 ⵡⴰⵢⵢⵓⵔⵠ+ '2629746': ⴰⵢⵢⵓⵔ + '31556952': ⴰⵙⴳⴳⵯⴰⵙ + '86400': ⴰⵙⵙ + '94670856': 3 ⵉⵙⴳⴳⵯⴰⵙⵠ+ relays: + delete: ⴽⴽⵙ + status: â´°â´·â´·â´°â´· + reports: + notes: + delete: ⴽⴽⵙ + status: â´°â´·â´·â´°â´· + settings: + site_title: ⵉⵙⵎ ⵠⵓⵎⴰⴽⴽⴰⵢ + title: ⵜⵉⵙⵖⴰⵠⵠⵡⴰⵙⵉⵜ + statuses: + batch: + delete: ⴽⴽⵙ + media: + title: ⵉⵙâµâµ–ⵎⵉⵙⵠ+ with_media: âµ™ ⵉⵙâµâµ–ⵎⵉⵙⵠ+ tags: + name: ⵀⴰⵛⵟⴰⴳ + title: ⵉⵀⴰⵛⵟⴰⴳⵠ+ warning_presets: + delete: ⴽⴽⵙ + application_mailer: + view_profile: ⵙⴽⵠⵉⴼⵔⵙ + auth: + change_password: ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ + forgot_password: ⵜⴻⵜⵜⵓⴷ ⵜⴰⴳⵓⵔⵉ ⵠⵓⵣⵔⴰⵢ âµâµâ´½? + login: ⴽⵛⵎ + logout: ⴼⴼⵖ + or_log_in_with: âµâµ– ⴽⵛⵎ âµ™ + register: ⵣⵎⵎⴻⵎ + status: + account_status: â´°â´·â´·â´°â´· ⵠⵓⵎⵉⴹⴰⵠ+ authorize_follow: + follow: ⴹⴼⵕ + title: ⴹⴼⵕ %{acct} + deletes: + proceed: ⴽⴽⵙ ⴰⵎⵉⴹⴰⵠ+ errors: + '400': The request you submitted was invalid or malformed. + '403': You don't have permission to view this page. + '404': The page you are looking for isn't here. + '406': This page is not available in the requested format. + '410': The page you were looking for doesn't exist here anymore. + '422': + '429': Too many requests + '500': + '503': The page could not be served due to a temporary server failure. + exports: + archive_takeout: + date: ⴰⵣⵎⵣ + filters: + index: + delete: ⴽⴽⵙ + footer: + more: ⵓⴳⴳⴰⵔ… + generic: + all: ⵎⴰⵕⵕⴰ + copy: âµ™âµâµ–âµ + delete: ⴽⴽⵙ + invites: + expires_in: + '1800': 30 ⵜⵓⵙⴷⵉⴷⵉⵠ+ '21600': 6 ⵜⵙⵔⴰⴳⵉⵠ+ '3600': ⵜⴰⵙⵔⴰⴳⵜ + '43200': 12 ⵜⵙⵔⴰⴳⵉⵠ+ '604800': ⵉⵎⴰâµâ´°âµ™âµ™ + '86400': ⴰⵙⵙ + expires_in_prompt: ⵓⵙⴰⵔ + notification_mailer: + mention: + action: ⵔⴰⵔ + relationships: + remove_selected_follows: ⴽⴽⵙ ⴰⴹⴼⴼⵓⵕ ⵉ ⵉâµâµ™âµ™âµŽâµ”ⵙⵠⵜⵜⵓⵙⵜⵢâµâµ‰âµ + settings: + account: ⴰⵎⵉⴹⴰⵠ+ account_settings: ⵜⵉⵙⵖⴰⵠⵠⵓⵎⵉⴹⴰⵠ+ back: ⴰⵖⵓⵠⵖⵔ ⵎⴰⵙⵜⵓⴷⵓⵠ+ edit_profile: âµ™âµâ´¼âµ ⵉⴼⵔⵙ + notifications: ⵜⵉâµâµ–ⵎⵉⵙⵉⵠ+ profile: ⵉⴼⵔⵙ diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 3d62230d88ee6def9cc6b587cfe97a431d697326..25e6869557b92635c6859c18c0cd090dfb572757 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -21,7 +21,9 @@ zh-CN: federation_hint_html: 在%{instance} 上拥有账å·åŽï¼Œä½ å¯ä»¥å…³æ³¨ä»»ä½• Mastodon æœåŠ¡å™¨æˆ–å…¶ä»–æœåŠ¡å™¨ä¸Šçš„äººã€‚ get_apps: å°è¯•移动应用 hosted_on: 一个在 %{domain} 上è¿è¡Œçš„ Mastodon 实例 - instance_actor_flash: è¿™ä¸ªè´¦å·æ˜¯ä¸ªè™šæ‹Ÿå¸å·ï¼Œä¸ä»£è¡¨ä»»ä½•用户,åªç”¨æ¥ä»£è¡¨æœåŠ¡å™¨æœ¬èº«ã€‚å®ƒç”¨äºŽå’Œå…¶å®ƒæœåŠ¡å™¨äº’é€šï¼Œæ‰€ä»¥ä¸åº”该被å°ç¦ï¼Œé™¤éžä½ 想å°ç¦æ•´ä¸ªå®žä¾‹ã€‚但是想å°ç¦æ•´ä¸ªå®žä¾‹çš„æ—¶å€™ï¼Œä½ 应该用域åå°ç¦ã€‚ + instance_actor_flash: 'è¿™ä¸ªè´¦å·æ˜¯ä¸ªè™šæ‹Ÿå¸å·ï¼Œä¸ä»£è¡¨ä»»ä½•用户,åªç”¨æ¥ä»£è¡¨æœåŠ¡å™¨æœ¬èº«ã€‚å®ƒç”¨äºŽå’Œå…¶å®ƒæœåŠ¡å™¨äº’é€šï¼Œæ‰€ä»¥ä¸åº”该被å°ç¦ï¼Œé™¤éžä½ 想å°ç¦æ•´ä¸ªå®žä¾‹ã€‚但是想å°ç¦æ•´ä¸ªå®žä¾‹çš„æ—¶å€™ï¼Œä½ 应该用域åå°ç¦ã€‚ + +' learn_more: 了解详情 privacy_policy: éšç§æ”¿ç– see_whats_happening: 看一看现在在å‘生什么 @@ -38,7 +40,7 @@ zh-CN: reason: åŽŸå› rejecting_media: æ¥è‡ªè¿™äº›æœåŠ¡å™¨çš„åª’ä½“æ–‡ä»¶å°†ä¸ä¼šè¢«å¤„ç†æˆ–å˜å‚¨ï¼Œç¼©ç•¥å›¾ä¹Ÿä¸ä¼šæ˜¾ç¤ºï¼Œéœ€è¦æ‰‹åŠ¨ç‚¹å‡»æ‰“å¼€åŽŸå§‹æ–‡ä»¶ã€‚ rejecting_media_title: 被过滤的媒体文件 - silenced: æ¥è‡ªè¿™äº›æœåŠ¡å™¨ä¸Šçš„å¸–åå°†ä¸ä¼šå‡ºçŽ°åœ¨å…¬å…±æ—¶é—´çº¿å’Œä¼šè¯ä¸ï¼›æ¤å¤–,除éžä½ 关注了这些æœåŠ¡å™¨ä¸Šçš„ç”¨æˆ·ï¼Œå¦åˆ™è¿™äº›ç”¨æˆ·çš„互动ä¸ä¼šäº§ç”Ÿé€šçŸ¥ã€‚ + silenced: æ¥è‡ªè¿™äº›æœåŠ¡å™¨ä¸Šçš„å¸–åå°†ä¸ä¼šå‡ºçŽ°åœ¨å…¬å…±æ—¶é—´è½´å’Œä¼šè¯ä¸ï¼Œé€šçŸ¥åŠŸèƒ½ä¹Ÿä¸ä¼šæé†’这些用户的动æ€ï¼›åªæœ‰ä½ 关注了这些用户,æ‰ä¼šæ”¶åˆ°ç”¨æˆ·äº’动的通知消æ¯ã€‚ silenced_title: å·²éšè—çš„æœåС噍 suspended: 这些æœåŠ¡å™¨çš„æ•°æ®å°†ä¸ä¼šè¢«å¤„ç†ã€å˜å‚¨æˆ–者交æ¢ï¼Œæœ¬ç«™ä¹Ÿå°†æ— 法和æ¥è‡ªè¿™äº›æœåŠ¡å™¨çš„ç”¨æˆ·äº’åŠ¨æˆ–è€…äº¤æµã€‚ suspended_title: å·²å°ç¦çš„æœåŠ¡å™¨ @@ -55,6 +57,7 @@ zh-CN: followers: other: 关注者 following: æ£åœ¨å…³æ³¨ + instance_actor_flash: 这个账户是虚拟账户,用æ¥ä»£è¡¨æœåŠ¡å™¨è‡ªèº«ï¼Œä¸ä»£è¡¨ä»»ä½•实际用户。它用于互通功能,ä¸åº”该å°ç¦ã€‚ joined: åŠ å…¥äºŽ %{date} last_active: 最近活动 link_verified_on: æ¤é“¾æŽ¥çš„æ‰€æœ‰æƒå·²åœ¨ %{date} 检查 @@ -92,6 +95,7 @@ zh-CN: add_email_domain_block: å°ç¦ç”µå邮箱域å approve: 批准 approve_all: 批准全部 + approved_msg: æˆåŠŸæ‰¹å‡† %{username} 的注册申请 are_you_sure: ä½ ç¡®å®šå—? avatar: å¤´åƒ by_domain: 域å @@ -105,8 +109,10 @@ zh-CN: confirm: 确认 confirmed: 已确认 confirming: ç¡®è®¤ä¸ + delete: åˆ é™¤æ•°æ® deleted: å·²åˆ é™¤ demote: é™ä»» + destroyed_msg: "%{username} 的数æ®å·²è¿›å…¥ç‰å¾…队列,å³å°†è¢«åˆ 除" disable: åœç”¨ disable_two_factor_authentication: åœç”¨åŒé‡è®¤è¯ disabled: å·²åœç”¨ @@ -117,10 +123,12 @@ zh-CN: email_status: 电å邮件地å€çŠ¶æ€ enable: å¯ç”¨ enabled: å·²å¯ç”¨ + enabled_msg: æˆåŠŸå¯ç”¨ %{username} çš„å¸å· followers: 关注者 follows: æ£åœ¨å…³æ³¨ header: 个人资料页横幅图片 inbox_url: 收件箱(Inbox)URL + invite_request_text: åŠ å…¥ç†ç”± invited_by: 邀请者为 ip: IP åœ°å€ joined: åŠ å…¥äºŽ @@ -132,17 +140,19 @@ zh-CN: login_status: ç™»å½•çŠ¶æ€ media_attachments: 媒体文件 memorialize: è®¾ç½®ä¸ºè¿½æ‚¼å¸æˆ· + memorialized: 被悼念 + memorialized_msg: æˆåŠŸå°† %{username} 转æ¢ä¸ºæ‚¼å¿µå¸å· moderation: active: 活跃 all: 全部 pending: å¾…å®¡æ ¸ silenced: å·²éšè— suspended: å·²å°ç¦ - title: 叿ˆ·çŠ¶æ€ + title: ç®¡ç† moderation_notes: 管ç†å‘˜å¤‡æ³¨ most_recent_activity: 最åŽä¸€æ¬¡æ´»è·ƒçš„æ—¶é—´ most_recent_ip: 最åŽä¸€æ¬¡æ´»è·ƒçš„ IP åœ°å€ - no_account_selected: å› ä¸ºæ²¡æœ‰å¸å·è¢«é€‰æ‹©ï¼Œæ‰€ä»¥æ²¡æœ‰æ›´æ”¹ + no_account_selected: å› ä¸ºæ²¡æœ‰é€‰ä¸ä»»ä½•å¸å·ï¼Œæ‰€ä»¥æ²¡æœ‰æ›´æ”¹ no_limits_imposed: æ— é™åˆ¶ not_subscribed: 未订阅 pending: å¾…å®¡æ ¸ @@ -152,10 +162,14 @@ zh-CN: public: å…¬å¼€é¡µé¢ push_subscription_expires: PuSH 订阅过期时间 redownload: 刷新个人资料 + redownloaded_msg: æˆåŠŸä»Žæ¥æºå¤„刷新 %{username} 的用户资料 reject: æ‹’ç» reject_all: æ‹’ç»å…¨éƒ¨ + rejected_msg: æˆåŠŸæ‹’ç» %{username} 的注册申请 remove_avatar: åˆ é™¤å¤´åƒ remove_header: åˆ é™¤æ¨ªå¹…å›¾ç‰‡ + removed_avatar_msg: æˆåŠŸåˆ é™¤ %{username} çš„å¤´åƒ + removed_header_msg: æˆåŠŸåˆ é™¤äº† %{username} 的横幅图片 resend_confirmation: already_confirmed: 该用户已被确认 send: é‡å‘确认邮件 @@ -172,6 +186,8 @@ zh-CN: search: æœç´¢ search_same_email_domain: 其他具有相åŒç”µå邮箱域å的用户 search_same_ip: 具有相åŒIP的其他用户 + sensitive: æ•æ„Ÿå†…容 + sensitized: å·²æ ‡è®°ä¸ºæ•æ„Ÿå†…容 shared_inbox_url: 公用收件箱(Shared Inbox)URL show: created_reports: è¿™ä¸ªå¸æˆ·æäº¤çš„举报 @@ -181,13 +197,19 @@ zh-CN: statuses: 嘟文 subscribe: 订阅 suspended: å·²å°ç¦ + suspension_irreversible: 该å¸å·çš„æ•°æ®å·²è¢«ä¸å¯é€†è½¬åœ°åˆ 除。您å¯ä»¥å–消暂åœè¯¥å¸å·ä»¥ä½¿å…¶å¯ç”¨ï¼Œä½†å®ƒä¸ä¼šæ¢å¤ä»¥å‰æ‹¥æœ‰çš„任何数æ®ã€‚ + suspension_reversible_hint_html: å¸å·å·²å°ç¦ï¼Œæ•°æ®å°†åœ¨ %{date} å®Œå…¨åˆ é™¤ã€‚ 在æ¤ä¹‹å‰ï¼Œå¸å·ä»å¯æ¢å¤ï¼Œå¹¶ä¸”没有任何ä¸è‰¯å½±å“。 如果您想立å³ç§»é™¤è¯¥å¸å·çš„æ‰€æœ‰æ•°æ®ï¼Œå¯ä»¥åœ¨ä¸‹é¢è¿›è¡Œã€‚ time_in_queue: å·²ç»ç‰å¾…了 %{time} title: 用户 unconfirmed_email: 待验è¯çš„电åé‚®ä»¶åœ°å€ + undo_sensitized: åŽ»é™¤æ•æ„Ÿå†…å®¹æ ‡è®° undo_silenced: 解除éšè— undo_suspension: 解除å°ç¦ + unsilenced_msg: æˆåŠŸè§£é™¤ %{username} çš„å¸å·é™åˆ¶ unsubscribe: å–æ¶ˆè®¢é˜… + unsuspended_msg: å·²æˆåŠŸå–æ¶ˆå°ç¦ %{username} çš„å¸å· username: 用户å + view_domain: æŸ¥çœ‹åŸŸåæ‘˜è¦ warn: è¦å‘Š web: ç«™å†…é¡µé¢ whitelisted: å…许跨站交互 @@ -202,12 +224,14 @@ zh-CN: create_domain_allow: å…许新域å create_domain_block: å°ç¦æ–°åŸŸå create_email_domain_block: å°ç¦ç”µå邮箱域å + create_ip_block: 新建 IP 规则 demote_user: 给用户é™èŒ destroy_announcement: åˆ é™¤å…¬å‘Š destroy_custom_emoji: åˆ é™¤è‡ªå®šä¹‰è¡¨æƒ…ç¬¦å· destroy_domain_allow: 解除域åå…许 destroy_domain_block: 解除域åå°ç¦ destroy_email_domain_block: 解除电å邮箱域åå°ç¦ + destroy_ip_block: åˆ é™¤ IP 规则 destroy_status: åˆ é™¤å˜Ÿæ–‡ disable_2fa_user: ç¦ç”¨åŒé‡è®¤è¯ disable_custom_emoji: ç¦ç”¨è‡ªå®šä¹‰è¡¨æƒ…ç¬¦å· @@ -220,13 +244,16 @@ zh-CN: reopen_report: é‡å¼€ä¸¾æŠ¥ reset_password_user: é‡ç½®å¯†ç resolve_report: 处ç†ä¸¾æŠ¥ + sensitive_account: å°†ä½ å¸å·ä¸çš„åª’ä½“æ ‡è®°ä¸ºæ•æ„Ÿå†…容 silence_account: éšè—用户 suspend_account: å°ç¦ç”¨æˆ· unassigned_report: å–æ¶ˆä¸¾æŠ¥çš„æŒ‡æ´¾ + unsensitive_account: åŽ»é™¤ä½ å¸å·ä¸åª’ä½“çš„æ•æ„Ÿå†…å®¹æ ‡è®° unsilence_account: 解除账å·éšè— unsuspend_account: 解除账å·å°ç¦ update_announcement: 更新公告 update_custom_emoji: æ›´æ–°è‡ªå®šä¹‰è¡¨æƒ…ç¬¦å· + update_domain_block: 更新域åå±è”½ update_status: 更新嘟文 actions: assigned_to_self_report: "%{name} 接管了举报 %{target}" @@ -238,12 +265,14 @@ zh-CN: create_domain_allow: "%{name} å…许了和域å %{target} 的跨站交互" create_domain_block: "%{name} å±è”½äº†åŸŸå %{target}" create_email_domain_block: "%{name} å±è”½äº†ç”µå邮件域å %{target}" + create_ip_block: "%{name} 为 IP %{target} 创建了规则" demote_user: "%{name} 对用户 %{target} 进行了é™ä»»æ“作" destroy_announcement: "%{name} åˆ é™¤äº†å…¬å‘Š %{target}" destroy_custom_emoji: "%{name} 销æ¯äº†è‡ªå®šä¹‰è¡¨æƒ… %{target}" destroy_domain_allow: "%{name} æ‹’ç»äº†å’Œ %{target} 跨站交互" destroy_domain_block: "%{name} 解除了对域å %{target} çš„å±è”½" destroy_email_domain_block: "%{name} 解除了对电å邮件域å %{target} çš„å±è”½" + destroy_ip_block: "%{name} åˆ é™¤äº† IP %{target} 的规则" destroy_status: "%{name} åˆ é™¤äº† %{target} 的嘟文" disable_2fa_user: "%{name} åœç”¨äº†ç”¨æˆ· %{target} çš„åŒé‡è®¤è¯" disable_custom_emoji: "%{name} åœç”¨äº†è‡ªå®šä¹‰è¡¨æƒ… %{target}" @@ -256,13 +285,16 @@ zh-CN: reopen_report: "%{name} é‡å¼€äº†ä¸¾æŠ¥ %{target}" reset_password_user: "%{name} é‡ç½®äº†ç”¨æˆ· %{target} 的密ç " resolve_report: "%{name} 处ç†äº†ä¸¾æŠ¥ %{target}" + sensitive_account: "%{name} å°† %{target} çš„åª’ä½“æ ‡è®°ä¸ºæ•æ„Ÿå†…容" silence_account: "%{name} éšè—了用户 %{target}" suspend_account: "%{name} å°ç¦äº†ç”¨æˆ· %{target}" unassigned_report: "%{name} 放弃了举报 %{target} 的接管" + unsensitive_account: "%{name} 去除了 %{target} åª’ä½“çš„æ•æ„Ÿå†…å®¹æ ‡è®°" unsilence_account: "%{name} 解除了用户 %{target} çš„éšè—状æ€" unsuspend_account: "%{name} 解除了用户 %{target} çš„å°ç¦çжæ€" update_announcement: "%{name} 更新了公告 %{target}" update_custom_emoji: "%{name} 更新了自定义表情 %{target}" + update_domain_block: "%{name} 更新了对 %{target} 的域åå±è”½" update_status: "%{name} 刷新了 %{target} 的嘟文" deleted_status: "ï¼ˆå˜Ÿæ–‡å·²åˆ é™¤ï¼‰" empty: 没有找到日志 @@ -365,7 +397,9 @@ zh-CN: noop: æ— silence: 自动éšè— suspend: 自动å°ç¦ - title: æ·»åŠ åŸŸåå±è”½ + title: 新增域åå±è”½ + obfuscate: 混淆域å + obfuscate_hint: 如果å¯ç”¨äº†åŸŸå列表公开é™åˆ¶ï¼Œå°±éƒ¨åˆ†æ··æ·†åˆ—表ä¸çš„域å private_comment: ç§å¯†è¯„论 private_comment_hint: 给这一域åé™åˆ¶æ·»åŠ å¤‡æ³¨ï¼Œä¾›ç›‘å¯Ÿå‘˜å†…éƒ¨ä½¿ç”¨ public_comment: 公开评论 @@ -391,7 +425,7 @@ zh-CN: view: 查看域åå±è”½ email_domain_blocks: add_new: æ·»åŠ æ–°æ¡ç›® - created_msg: 电å邮件域åå±è”½æ·»åŠ æˆåŠŸ + created_msg: æˆåŠŸå±è”½ç”µå邮件域å delete: åˆ é™¤ destroyed_msg: 电å邮件域åå±è”½åˆ 除æˆåŠŸ domain: 域å @@ -404,6 +438,7 @@ zh-CN: instances: by_domain: 域å delivery_available: 坿Е递 + empty: æš‚æ— åŸŸå。 known_accounts: other: "%{count} ä¸ªå·²çŸ¥å¸æˆ·" moderation: @@ -426,6 +461,21 @@ zh-CN: expired: 已失效 title: ç›é€‰ title: 邀请用户 + ip_blocks: + add_new: 新建规则 + created_msg: æˆåŠŸæ·»åŠ æ–° IP 规则 + delete: åˆ é™¤ + expires_in: + '1209600': 两周 + '15778476': 6个月 + '2629746': 1个月 + '31556952': 1å¹´ + '86400': 1天 + '94670856': 3å¹´ + new: + title: 创建新 IP 规则 + no_ip_block_selected: å› ä¸ºæ²¡æœ‰ IP 规则被选ä¸ï¼Œæ‰€ä»¥æ²¡æœ‰æ›´æ”¹ + title: IP 规则 pending_accounts: title: 待处ç†çš„叿ˆ· (%{count}) relationships: @@ -463,6 +513,8 @@ zh-CN: comment: none: 没有 created_at: 举报时间 + forwarded: å·²è½¬å‘ + forwarded_to: 转å‘举报至 %{domain} mark_as_resolved: æ ‡è®°ä¸ºâ€œå·²å¤„ç†â€ mark_as_unresolved: æ ‡è®°ä¸ºâ€œæœªå¤„ç†â€ notes: @@ -506,9 +558,10 @@ zh-CN: domain_blocks_rationale: title: 显示ç†ç”± enable_bootstrap_timeline_accounts: + desc_html: è®©æ–°ç”¨æˆ·è‡ªåŠ¨å…³æ³¨æŒ‡å®šç”¨æˆ·ï¼Œè¿™æ ·ï¼Œä»–ä»¬çš„ä¸»é¡µæ—¶é—´çº¿å°±ä¸ä¼šåœ¨ä¸€å¼€å§‹çš„æ—¶å€™ç©ºç©ºè¡è¡ title: 开坿–°ç”¨æˆ·é»˜è®¤å…³æ³¨åŠŸèƒ½ hero: - desc_html: 用于在首页展示。推è分辨率 600×100px 以上。未指定的情况下将默认使用本站缩略图 + desc_html: 将用于在首页展示。推è使用分辨率 600×100px 以上的图片。如未设置,将默认使用本站缩略图。 title: 主题图片 mascot: desc_html: 用于在首页展示。推è分辨率 293×205px 以上。未指定的情况下将使用默认å‰ç¥¥ç‰©ã€‚ @@ -517,7 +570,7 @@ zh-CN: desc_html: æˆªè‡³ç›®å‰æœ¬æœåŠ¡å™¨åœ¨è”邦宇宙ä¸å·²å‘现的域å title: 公开已知实例的列表 preview_sensitive_media: - desc_html: 始终在站外链接预览ä¸å±•ç¤ºç¼©ç•¥å›¾ï¼Œæ— è®ºåª’ä½“å†…å®¹æ˜¯å¦æ ‡è®°ä¸ºæ•感 + desc_html: æ— è®ºåª’ä½“æ–‡ä»¶æ˜¯å¦æ ‡è®°ä¸ºæ•感内容,站外链接预览始终呈现为缩略图。 title: 在 OpenGraph é¢„è§ˆä¸æ˜¾ç¤ºæ•感媒体内容 profile_directory: desc_html: å…许用户被å‘现 @@ -532,6 +585,9 @@ zh-CN: min_invite_role: disabled: 没有人 title: å…许å‘é€é‚€è¯·çš„用户组 + require_invite_text: + desc_html: å½“æ³¨å†Œéœ€è¦æ‰‹åŠ¨æ‰¹å‡†æ—¶ï¼Œå°†â€œä½ ä¸ºä»€ä¹ˆæƒ³è¦åŠ å…¥ï¼Ÿâ€è®¾ä¸ºå¿…填项 + title: è¦æ±‚æ–°ç”¨æˆ·å¡«å†™ç”³è¯·æ³¨å†Œçš„åŽŸå› registrations_mode: modes: approved: æ³¨å†Œæ—¶éœ€è¦æ‰¹å‡† @@ -623,7 +679,7 @@ zh-CN: body_remote: æ¥è‡ª %{domain} 的用户举报了用户 %{target} subject: æ¥è‡ª %{instance} 的用户举报(#%{id}) new_trending_tag: - body: '今日的çƒé—¨è¯é¢˜ #%{name} 之剿œªç»å®¡æ ¸ã€‚ç›´åˆ°ä½ å…许之å‰è¿™ä¸ªè¯é¢˜å°†ä¸ä¼šå…¬å¼€æ˜¾ç¤ºï¼Œæ´»ç€å°±ä¿æŒåŽŸæ ·è®©å®ƒçŸ³æ²‰å¤§æµ·ã€‚' + body: '今日的çƒé—¨è¯é¢˜ #%{name} 之剿œªç»å®¡æ ¸ã€‚ç›´åˆ°ä½ å…许之å‰è¿™ä¸ªè¯é¢˜å°†ä¸ä¼šå…¬å¼€æ˜¾ç¤ºï¼Œæˆ–è€…å°±ä¿æŒåŽŸæ ·è®©å®ƒçŸ³æ²‰å¤§æµ·ã€‚' subject: 在 %{instance} 有新è¯é¢˜ (#%{name}) å¾…å®¡æ ¸ aliases: add_new: 创建别å @@ -671,8 +727,11 @@ zh-CN: prefix_sign_up: 现在就注册 Mastodonï¼ suffix: 注册一个å¸å·ï¼Œä½ å°±å¯ä»¥å…³æ³¨åˆ«äººã€å‘布嘟文ã€å¹¶å’Œå…¶å®ƒä»»ä½•MastodonæœåŠ¡å™¨ä¸Šçš„ç”¨æˆ·äº¤æµï¼Œè€Œä¸”è¿˜æœ‰å…¶å®ƒæ›´å¤šåŠŸèƒ½ï¼ didnt_get_confirmation: 没有收到确认邮件? + dont_have_your_security_key: 没有您的安全密钥? forgot_password: 忘记密ç ? invalid_reset_password_token: 密ç é‡ç½®ä»¤ç‰Œæ— æ•ˆæˆ–å·²è¿‡æœŸã€‚è¯·é‡æ–°å‘èµ·é‡ç½®å¯†ç 请求。 + link_to_otp: 输入从手机ä¸èŽ·å¾—çš„ä¸¤æ¥éªŒè¯ä»£ç 或æ¢å¤ä»£ç + link_to_webauth: 使用您的安全密钥设备 login: 登录 logout: 登出 migrate_account: è¿ç§»åˆ°å¦ä¸€ä¸ªå¸æˆ· @@ -697,7 +756,9 @@ zh-CN: functional: 您的å¸å·å¯ä»¥æ£å¸¸ä½¿ç”¨äº†ã€‚ pending: 工作人员æ£åœ¨å®¡æ ¸æ‚¨çš„申请。这需è¦èŠ±ç‚¹æ—¶é—´ã€‚åœ¨ç”³è¯·è¢«æ‰¹å‡†åŽï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç”µå邮件。 redirecting_to: æ‚¨çš„å¸æˆ·æ— æ•ˆï¼Œå› ä¸ºå®ƒå·²è¢«è®¾ç½®ä¸ºè·³è½¬åˆ° %{acct} + too_fast: è¡¨å•æäº¤è¿‡å¿«ï¼Œè¯·é‡è¯•。 trouble_logging_in: 登录有问题? + use_security_key: 使用安全密钥 authorize_follow: already_following: ä½ å·²ç»åœ¨å…³æ³¨æ¤ç”¨æˆ·äº† already_requested: ä½ å·²ç»å‘那个账户å‘é€è¿‡å…³æ³¨è¯·æ±‚了 @@ -722,6 +783,7 @@ zh-CN: date: formats: default: "%Yå¹´%m月%dæ—¥" + with_month_name: "%Yå¹´%m月%dæ—¥" datetime: distance_in_words: about_x_hours: "%{count}æ—¶" @@ -786,6 +848,7 @@ zh-CN: request: è¯·æ±‚ä½ çš„å˜æ¡£ size: å¤§å° blocks: å±è”½çš„用户 + bookmarks: ä¹¦ç¾ csv: CSV domain_blocks: 域åå±è”½ lists: 列表 @@ -852,6 +915,8 @@ zh-CN: status: 验è¯çŠ¶æ€ view_proof: æŸ¥çœ‹è¯æ˜Ž imports: + errors: + over_rows_processing_limit: 包å«è¡Œæ•°è¶…过了 %{count} modes: merge: åˆå¹¶ merge_long: ä¿ç•™çŽ°æœ‰è®°å½•å¹¶æ·»åŠ æ–°çš„è®°å½• @@ -861,6 +926,7 @@ zh-CN: success: æ•°æ®ä¸Šä¼ æˆåŠŸï¼Œæ£åœ¨å¤„ç†ä¸ types: blocking: å±è”½åˆ—表 + bookmarks: ä¹¦ç¾ domain_blocking: 域åå±è”½åˆ—表 following: 关注列表 muting: éšè—列表 @@ -978,6 +1044,14 @@ zh-CN: quadrillion: Q thousand: K trillion: T + otp_authentication: + code_hint: 输入认è¯åº”用生æˆçš„代ç 以确认æ“作 + description_html: 如果您使用身份验è¯åº”用å¯ç”¨äº† <strong>åŒé‡èº«ä»½éªŒè¯</strong>, 登录将需è¦ç”¨åˆ°æ‚¨çš„æ‰‹æœºï¼Œå®ƒå°†ç”Ÿæˆæ‚¨éœ€è¦çš„令牌。 + enable: å¯ç”¨ + instructions_html: "<strong>请使用 Google 身份验è¯å™¨æˆ–å…¶ä»–çš„TOTPåŒé‡è®¤è¯æ‰‹æœºåº”ç”¨æ‰«ææ¤å¤„çš„äºŒç»´ç </strong>。å¯ç”¨åŒé‡è®¤è¯åŽï¼Œåœ¨ç™»å½•æ—¶ï¼Œä½ éœ€è¦è¾“入该应用生æˆçš„代ç 。" + manual_instructions: å¦‚æžœä½ æ— æ³•æ‰«æäºŒç»´ç ,请手动输入下列文本: + setup: 设置 + wrong_code: 输入的认è¯ç æ— æ•ˆï¼è¯·ç¡®è®¤æœåŠ¡å™¨æ—¶é—´ä¸Žè®¾å¤‡æ—¶é—´æ˜¯å¦æ£ç¡®ï¼Ÿ pagination: newer: æ›´æ–° next: 下一页 @@ -1006,6 +1080,7 @@ zh-CN: relationships: activity: å¸å·æ´»åЍ dormant: ä¼‘çœ + follow_selected_followers: 关注选ä¸çš„关注者 followers: 关注者 following: æ£åœ¨å…³æ³¨ invited: 已邀请 @@ -1102,6 +1177,7 @@ zh-CN: profile: 个人资料 relationships: å…³æ³¨ç®¡ç† two_factor_authentication: åŒé‡è®¤è¯ + webauthn_authentication: 安全密钥 spam_check: spam_detected: 这是一个自动报告。已检测到垃圾信æ¯ã€‚ statuses: @@ -1134,6 +1210,8 @@ zh-CN: other: "%{count} 票" vote: 投票 show_more: 显示更多 + show_newer: 显示更新内容 + show_older: 显示更早内容 show_thread: æ˜¾ç¤ºå…¨éƒ¨å¯¹è¯ sign_in_to_participate: ç™»å½•ä»¥åŠ å…¥å¯¹è¯ title: "%{name}:“%{quote}â€" @@ -1239,24 +1317,23 @@ zh-CN: mastodon-light: Mastodon(亮色主题) time: formats: - default: "%Yå¹´%-m月%dæ—¥ %H:%M" - month: "%Y å¹´ %B" + default: "%Yå¹´%m月%dæ—¥ %H:%M" + month: "%Yå¹´%m月" two_factor_authentication: - code_hint: 输入认è¯å™¨ç”Ÿæˆçš„代ç 以确认æ“作 - description_html: å¯ç”¨<strong>åŒé‡è®¤è¯</strong>åŽï¼Œä½ 需è¦è¾“入手机认è¯å™¨ç”Ÿæˆçš„ä»£ç æ‰èƒ½ç™»å½•. + add: æ·»åŠ disable: åœç”¨ - enable: å¯ç”¨ + disabled_success: åŒé‡èº«ä»½éªŒè¯æˆåŠŸç¦ç”¨ + edit: 编辑 enabled: åŒé‡è®¤è¯å·²å¯ç”¨ enabled_success: åŒé‡è®¤è¯å¯ç”¨æˆåŠŸ generate_recovery_codes: ç”Ÿæˆæ¢å¤ä»£ç - instructions_html: "<strong>请使用 Google 身份验è¯å™¨æˆ–å…¶ä»– TOTP åŒé‡è®¤è¯æ‰‹æœºåº”ç”¨æ‰«ææ¤å¤„çš„äºŒç»´ç </strong>。å¯ç”¨åŒé‡è®¤è¯åŽï¼Œä½ 需è¦è¾“入该应用生æˆçš„ä»£ç æ¥ç™»å½•ä½ çš„å¸æˆ·ã€‚" lost_recovery_codes: å¦‚æžœä½ çš„æ‰‹æœºä¸æ…Žä¸¢å¤±ï¼Œä½ å¯ä»¥ä½¿ç”¨æ¢å¤ä»£ç æ¥é‡æ–°è޷得坹叿ˆ·çš„访问æƒã€‚å¦‚æžœä½ é—失了æ¢å¤ä»£ç ,å¯ä»¥åœ¨æ¤å¤„釿–°ç”Ÿæˆã€‚之å‰ä½¿ç”¨çš„æ¢å¤ä»£ç 将会失效。 - manual_instructions: å¦‚æžœä½ æ— æ³•æ‰«æäºŒç»´ç ,请手动输入下列文本: + methods: åŒé‡è®¤è¯ + otp: 身份验è¯åº”用 recovery_codes: 备份æ¢å¤ä»£ç recovery_codes_regenerated: æ¢å¤ä»£ç 釿–°ç”ŸæˆæˆåŠŸ recovery_instructions_html: å¦‚æžœä½ çš„æ‰‹æœºæ— æ³•ä½¿ç”¨ï¼Œä½ å¯ä»¥ä½¿ç”¨ä¸‹åˆ—ä»»æ„一个æ¢å¤ä»£ç æ¥é‡æ–°è޷得坹叿ˆ·çš„访问æƒã€‚<strong>请妥善ä¿ç®¡å¥½ä½ çš„æ¢å¤ä»£ç </strong>ï¼ˆä¾‹å¦‚ï¼Œä½ å¯ä»¥å°†å®ƒä»¬æ‰“å°å‡ºæ¥ï¼Œç„¶åŽå’Œå…¶ä»–é‡è¦çš„æ–‡ä»¶æ”¾åœ¨ä¸€èµ·ï¼‰ã€‚ - setup: 设置 - wrong_code: 输入的认è¯ç æ— æ•ˆï¼è¯·ç¡®è®¤æœåŠ¡å™¨æ—¶é—´ä¸Žè®¾å¤‡æ—¶é—´æ˜¯å¦æ£ç¡®ï¼Ÿ + webauthn: 安全密钥 user_mailer: backup_ready: explanation: ä½ è¯·æ±‚äº†ä¸€ä»½ Mastodon 叿ˆ·çš„å®Œæ•´å¤‡ä»½ã€‚çŽ°åœ¨ä½ å¯ä»¥ä¸‹è½½äº†ï¼ @@ -1271,6 +1348,7 @@ zh-CN: warning: explanation: disable: è™½ç„¶æ‚¨çš„å¸æˆ·è¢«å†»ç»“ï¼Œæ‚¨çš„å¸æˆ·æ•°æ®ä»ç„¶å®Œæ•´ï¼›ä½†æ˜¯æ‚¨æ— 法在解é”剿‰§è¡Œä»»ä½•æ“作。 + sensitive: ä½ ä¸Šä¼ çš„åª’ä½“æ–‡ä»¶å’Œåª’ä½“é“¾æŽ¥å°†è¢«è§†ä½œæ•æ„Ÿå†…容。 silence: å½“æ‚¨çš„å¸æˆ·å—陿—¶ï¼Œåªæœ‰å·²ç»å…³æ³¨è¿‡ä½ 的人æ‰ä¼šè¿™å°æœåŠ¡å™¨ä¸Šçœ‹åˆ°ä½ çš„å˜Ÿæ–‡ï¼Œå¹¶ä¸”æ‚¨ä¼šè¢«æŽ’é™¤åœ¨å„ç§å…¬å…±åˆ—表之外。但是,其他人ä»ç„¶å¯ä»¥æ‰‹åŠ¨å…³æ³¨ä½ ã€‚ suspend: æ‚¨çš„å¸æˆ·å·²è¢«å°ç¦ï¼Œæ‰€æœ‰çš„å˜Ÿæ–‡å’Œæ‚¨ä¸Šä¼ çš„åª’ä½“æ–‡ä»¶éƒ½å·²ç»ä»Žè¯¥æœåŠ¡å™¨å’Œæ‚¨çš„å…³æ³¨è€…çš„æœåŠ¡å™¨ä¸Šåˆ é™¤å¹¶ä¸”ä¸å¯æ¢å¤ã€‚ get_in_touch: 您å¯å›žå¤è¯¥é‚®ä»¶ä»¥è”ç³» %{instance} 的工作人员。 @@ -1279,11 +1357,13 @@ zh-CN: subject: disable: æ‚¨çš„å¸æˆ· %{acct} 已被冻结 none: 对 %{acct} çš„è¦å‘Š + sensitive: ä½ çš„å¸å· %{acct} 所å‘å¸ƒçš„åª’ä½“å·²è¢«æ ‡è®°ä¸ºæ•æ„Ÿå†…容 silence: æ‚¨çš„å¸æˆ· %{acct} å·²ç»å—é™ suspend: æ‚¨çš„å¸æˆ· %{acct} 已被å°ç¦ã€‚ title: disable: è´¦å·å·²å†»ç»“ none: è¦ç¤º + sensitive: ä½ çš„åª’ä½“è¢«æ ‡è®°ä¸ºæ•æ„Ÿå†…容 silence: 叿ˆ·å—é™ suspend: è´¦å·è¢«å°ç¦ welcome: @@ -1304,9 +1384,11 @@ zh-CN: tips: å°è´´å£« title: "%{name}ï¼Œæ¬¢è¿Žä½ çš„åŠ å…¥ï¼" users: + blocked_email_provider: 您ä¸èƒ½ä½¿ç”¨æ¥è‡ªæ¤æä¾›å•†çš„邮箱 follow_limit_reached: 您ä¸èƒ½å…³æ³¨è¶…过 %{limit} 个人 generic_access_help_html: 登录账å·å‡ºçŽ°é—®é¢˜ï¼Ÿä½ å¯ä»¥å‘ %{email} 寻求帮助 invalid_email: 输入的电åé‚®ä»¶åœ°å€æ— 效 + invalid_email_mx: 用戶邮箱似乎ä¸å˜åœ¨ invalid_otp_token: 输入的åŒé‡è®¤è¯ä»£ç æ— æ•ˆ invalid_sign_in_token: æ— æ•ˆå®‰å…¨ç otp_lost_help_html: å¦‚æžœä½ ä¸æ…Žä¸¢å¤±äº†æ‰€æœ‰çš„代ç ,请è”ç³» %{email} 寻求帮助 @@ -1316,3 +1398,20 @@ zh-CN: verification: explanation_html: 您å¯ä»¥ <strong>验è¯è‡ªå·±æ˜¯ä¸ªäººèµ„料元数æ®ä¸çš„æŸä¸ªé“¾æŽ¥çš„æ‰€æœ‰è€…</strong>。 为æ¤ï¼Œè¢«é“¾æŽ¥ç½‘站必须包å«ä¸€ä¸ªåˆ°æ‚¨çš„ Mastodon ä¸»é¡µçš„é“¾æŽ¥ã€‚é“¾æŽ¥ä¸ <strong>å¿…é¡»</strong> 包括 <code>rel="me"</code> 属性。链接的文本内容å¯ä»¥éšæ„填写。例如: verification: éªŒè¯ + webauthn_credentials: + add: æ·»åŠ æ–°çš„å®‰å…¨å¯†é’¥ + create: + error: æ·»åŠ æ‚¨çš„å®‰å…¨å¯†é’¥æ—¶å‡ºé”™ã€‚è¯·é‡è¯•。 + success: 您的安全密钥已æˆåŠŸæ·»åŠ ã€‚ + delete: åˆ é™¤ + delete_confirmation: 您确认è¦åˆ 除这个安全密钥å—? + description_html: 如果您å¯ç”¨ <strong>安全密钥身份验è¯</strong>ï¼Œç™»å½•å°†éœ€è¦æ‚¨ä½¿ç”¨æ‚¨çš„安全密钥。 + destroy: + error: åˆ é™¤æ‚¨çš„å®‰å…¨å¯†é’¥æ—¶å‡ºé”™ã€‚è¯·é‡è¯•。 + success: 您的安全密钥已æˆåŠŸåˆ é™¤ã€‚ + invalid_credential: æ— æ•ˆçš„å®‰å…¨å¯†é’¥ + nickname_hint: 输入您新安全密钥的昵称 + not_enabled: 您尚未å¯ç”¨ WebAuthn + not_supported: æ¤æµè§ˆå™¨ä¸æ”¯æŒå®‰å…¨å¯†é’¥ + otp_required: è¦ä½¿ç”¨å®‰å…¨å¯†é’¥ï¼Œè¯·å…ˆå¯ç”¨ä¸¤æ¥éªŒè¯ã€‚ + registered_on: 注册于 %{date} diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 4dcdee999daaa5c1a4c3f7cf3012e575ad5a9c88..9fcee79f1130763116e9a7266350117763eee449 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -1,120 +1,136 @@ --- zh-HK: about: - about_hashtag_html: 這些是包å«ã€Œ<strong>#%{hashtag}</strong>ã€æ¨™ç±¤çš„å…¬é–‹æ–‡ç« ã€‚åªè¦ä½ 有任何 Mastodon æœå‹™ç«™ã€æˆ–者è¯ç›Ÿç¶²ç«™çš„用戶,便å¯ä»¥èˆ‡ä»–們互動。 - about_mastodon_html: Mastodon(è¬è±¡ï¼‰æ˜¯<em>自由ã€é–‹æº</em>的社交網絡。æœå‹™ç«™<em>å„自ç¨ç«‹è€Œäº’連</em>,é¿å…å–®ä¸€å•†æ¥æ©Ÿæ§‹å£Ÿæ–·ã€‚æ‰¾ä½ æ‰€ä¿¡ä»»çš„æœå‹™ç«™ï¼Œå»ºç«‹å¸³è™Ÿï¼Œä½ å³å¯èˆ‡ä»»ä½•æœå‹™ç«™ä¸Šçš„用戶æºé€šï¼Œäº«å—無縫的<em>網絡交æµ</em>。 + about_hashtag_html: 這些是包å«ã€Œ<strong>#%{hashtag}</strong>ã€æ¨™ç±¤çš„å…¬é–‹æ–‡ç« ã€‚åªè¦ä½ 是任何è¯ç›Ÿç¶²ç«™çš„用戶,便å¯ä»¥èˆ‡ä»–們互動。 + about_mastodon_html: Mastodon(è¬è±¡ï¼‰æ˜¯å±¬æ–¼æœªä¾†çš„社交網絡︰無廣告煩擾ã€ç„¡ä¼æ¥ç›£æŽ§ã€è¨è¨ˆè¬›é“義ã€åˆ†æ•£ç„¡å¤§å°ï¼ç«‹å³é‡å¥ªå€‹äººè³‡æ–™çš„æŽ§åˆ¶æ¬Šï¼Œä½¿ç”¨ Mastodon å§ï¼ about_this: 關於本æœå‹™ç«™ active_count_after: æ´»èº active_footnote: æ¯æœˆæ´»èºä½¿ç”¨è€… (MAU) administered_by: 管ç†è€…: api: API - apps: è¡Œå‹•æ‡‰ç”¨ç¨‹å¼ + apps: 手機 App apps_platforms: 在 iOSã€Android 和其他平å°ä½¿ç”¨ Mastodon browse_directory: ä¾èˆˆè¶£ç€è¦½å€‹äººè³‡æ–™ç›®éŒ„å’ŒéŽæ¿¾å™¨ - browse_local_posts: ç€è¦½é€™å°ä¼ºæœå™¨ä¸å…¬é–‹å˜Ÿæ–‡çš„ç›´æ’ä¸²æµ - browse_public_posts: 在 Mastodon ç€è¦½å…¬é–‹å˜Ÿæ–‡çš„峿™‚ä¸²æµ + browse_local_posts: ç€è¦½é€™å€‹ä¼ºæœå™¨çš„å…¬é–‹æ–‡ç« å³æ™‚ä¸²æµ + browse_public_posts: 在 Mastodon ç€è¦½å…¬é–‹æ–‡ç« çš„å³æ™‚ä¸²æµ contact: è¯çµ¡ contact_missing: 未è¨å®š - contact_unavailable: 未公開 + contact_unavailable: ä¸é©ç”¨ discover_users: 探索使用者 - documentation: 文件 - federation_hint_html: ä½ åªéœ€è¦æ“有 %{instance} 的帳戶,就å¯ä»¥è¿½è¹¤éš¨ä¾¿ä¸€å° Mastodon 伺æœå™¨ä¸Šçš„人ç‰ç‰ã€‚ - get_apps: å˜—è©¦è¡Œå‹•æ‡‰ç”¨ç¨‹å¼ - hosted_on: 在 %{domain} é‹ä½œçš„ Mastodon æœå‹™ç«™ + documentation: 說明文件 + federation_hint_html: ä½ åªéœ€è¦æ“有 %{instance} 的帳戶,就å¯ä»¥è¿½è¹¤ä»»ä½• Mastodon æœå‹™ç«™ä¸Šçš„äººï¼ + get_apps: 嘗試使用手機 App + hosted_on: 在 %{domain} é‹ä½œçš„ Mastodon 伺æœå™¨ + instance_actor_flash: | + 這個帳戶是代表伺æœå™¨ï¼Œè€Œéžä»£è¡¨ä»»ä½•個人用戶的虛擬帳號。 + æ¤å¸³æˆ¶æ˜¯ç‚ºè¯ç›Ÿå”定而è¨ã€‚除éžä½ 想å°éŽ–æ•´å€‹ä¼ºæœå™¨çš„話,å¦å‰‡è«‹ä¸è¦å°éŽ–é€™å€‹å¸³æˆ¶ã€‚å¦‚æžœä½ æƒ³å°éŽ–ä¼ºæœå™¨ï¼Œè«‹ä½¿ç”¨ç¶²åŸŸå°éޖ以é”åˆ°ç›¸åŒæ•ˆæžœã€‚ learn_more: 了解更多 privacy_policy: éš±ç§æ¬Šæ”¿ç– see_whats_happening: 看看發生什麼事 server_stats: 伺æœå™¨çµ±è¨ˆï¼š source_code: æºä»£ç¢¼ status_count_after: - other: æ¢å˜Ÿæ–‡ - status_count_before: 他們共發佈了 + other: ç¯‡æ–‡ç« + status_count_before: 共發佈了 tagline: 關注朋å‹ä¸¦æŽ¢ç´¢æ–°æœ‹å‹ terms: ä½¿ç”¨æ¢æ¬¾ - unavailable_content: 無法å–得的內容 + unavailable_content: å—é™åˆ¶çš„伺æœå™¨ unavailable_content_description: domain: 伺æœå™¨ reason: åŽŸå› - rejecting_media: 䏿œƒè™•ç†æˆ–儲å˜é€™äº›ä¼ºæœå™¨çš„åª’é«”æª”æ¡ˆï¼Œä¹Ÿä¸æœƒé¡¯ç¤ºç¸®åœ–ï¼Œéœ€è¦æ‰‹å‹•點é¸åŽŸå§‹æª”ï¼š - rejecting_media_title: éŽæ¿¾çš„媒體 - silenced_title: éœéŸ³çš„伺æœå™¨ - suspended_title: æš«åœçš„伺æœå™¨ + rejecting_media: 這些伺æœå™¨çš„åª’é«”æª”æ¡ˆå°‡ä¸æœƒè¢«è™•ç†æˆ–儲å˜ï¼Œæˆ‘å€‘äº¦ä¸æœƒå±•示其縮圖。請手動點擊以觀看原始檔: + rejecting_media_title: 被篩é¸çš„媒體檔案 + silenced: 除éžä½ 已經關注個別使用者,å¦å‰‡ä¾†è‡ªé€™äº›ä¼ºæœå™¨çš„æ–‡ç« 和通知將會被隱è—。 + silenced_title: å·²éœéŸ³çš„伺æœå™¨ + suspended: 來自這些伺æœå™¨çš„æ‰€æœ‰æ•¸æ“šå°‡ä¸æœƒè¢«è™•ç†ã€‚ä½ å°‡ä¸å¯èƒ½è¯çµ¡ä¾†è‡ªé€™äº›ä¼ºæœå™¨çš„使用者。 + suspended_title: å·²åœæ¬Šçš„伺æœå™¨ + unavailable_content_html: Mastodon é€šå¸¸è®“ä½ ç€è¦½å…¶ä»–社交è¯ç›Ÿç¶²ç«™çš„æ‰€æœ‰å…§å®¹ï¼Œä½†æ˜¯å°æ–¼é€™å€‹ç‰¹å®šç¶²ç«™ï¼Œæœ‰é€™äº›ç‰¹åˆ¥çš„例外è¦å‰‡ã€‚ user_count_after: other: ä½ä½¿ç”¨è€… - user_count_before: 這è£å…±è¨»å†Šæœ‰ - what_is_mastodon: Mastodon 是甚麼? + user_count_before: 本站共有 + what_is_mastodon: Mastodon (è¬è±¡ï¼‰æ˜¯ç”šéº¼ï¼Ÿ accounts: choices_html: "%{name} çš„é¸æ“‡ï¼š" + endorsements_hint: ä½ å¯ä»¥æŽ¨è–¦æ£åœ¨é—œæ³¨çš„äººï¼Œä»–å€‘æœƒè¢«é¡¯ç¤ºåœ¨ä½ çš„å€‹äººé é¢ã€‚ + featured_tags_hint: ä½ å¯ä»¥æŽ¨è–¦ä¸åŒæ¨™ç±¤ï¼Œå®ƒå€‘也會在æ¤è™•出ç¾ã€‚ follow: 關注 followers: other: 關注者 following: æ£åœ¨é—œæ³¨ - joined: åŠ å…¥æ–¼ %{date} + instance_actor_flash: 這個帳戶是çµç›Ÿç”¨çš„æœ¬ä¼ºæœå™¨çš„虛擬象徵,並ä¸ä»£è¡¨ä»»ä½•個別用戶。請ä¸è¦æŠŠå¸³è™Ÿåœæ¬Šã€‚ + joined: æ–¼ %{date} åŠ å…¥ last_active: ä¸Šæ¬¡æ´»èºæ™‚é–“ link_verified_on: æ¤é€£çµçš„æ‰€æœ‰æ¬Šå·²åœ¨ %{date} æª¢æŸ¥éŽ media: 媒體 moved_html: "%{name} 已經轉移到 %{new_profile_link}:" network_hidden: æ¤ä¿¡æ¯ä¸å¯ç”¨ never_active: æ°¸ä¸ - nothing_here: 暫時未有內容å¯ä»¥é¡¯ç¤ºã€‚ + nothing_here: 暫時未有內容å¯ä»¥é¡¯ç¤ºï¼ people_followed_by: "%{name} 關注的人" people_who_follow: 關注 %{name} 的人 + pin_errors: + following: ä½ åªèƒ½æŽ¨è–¦ä½ æ£åœ¨é—œæ³¨çš„使用者。 posts: - other: 嘟文 - posts_tab_heading: 嘟文 - posts_with_replies: æ–‡ç« å’Œå›žè¦† - reserved_username: æ¤ç”¨æˆ¶å已被ä¿ç•™ + other: æ–‡ç« + posts_tab_heading: æ–‡ç« + posts_with_replies: 包å«å›žè¦†çš„æ–‡ç« + reserved_username: 這個使用者å稱已被ä¿ç•™ roles: admin: 管ç†å“¡ bot: 機械人 group: 群組 - moderator: 監察員 + moderator: æ¿ä¸» unavailable: 無法å–得個人檔案 unfollow: å–æ¶ˆé—œæ³¨ admin: account_actions: action: 執行動作 - title: 在 %{acct} 執行管ç†å“¡å‹•作 + title: 在 %{acct} åŸ·è¡Œç®¡ç†æ“作 account_moderation_notes: - create: 記錄 - created_msg: 管ç†è¨˜éŒ„已新增 + create: åŠ å…¥ç®¡ç†ç´€éŒ„ + created_msg: 已新增管ç†ç´€éŒ„ delete: 刪除 - destroyed_msg: 管ç†è¨˜éŒ„已被刪除 + destroyed_msg: 管ç†ç´€éŒ„已被刪除 accounts: - add_email_domain_block: 將電åéƒµä»¶ç¶²åŸŸåŠ å…¥é»‘åå–® + add_email_domain_block: å°éŽ–é›»éƒµç¶²åŸŸ approve: æ ¸å‡† approve_all: 全部批准 + approved_msg: æˆåŠŸå¯©æ ¸äº†%{username} 的新帳號申請 are_you_sure: ä½ ç¢ºå®šå—Žï¼Ÿ avatar: é åƒ by_domain: 域å change_email: changed_msg: 帳號電郵更新æˆåŠŸï¼ current_email: ç¾æ™‚電郵 - label: 改變電郵 + label: 更改電郵 new_email: 新的電郵 submit: 改變電郵 title: 改變 %{username} 的電郵 confirm: 確定 confirmed: 已確定 confirming: 確定 + delete: 刪除資料 deleted: 已刪除 - demote: é™ä»» + demote: 陿¬Š + destroyed_msg: å³å°‡åˆªé™¤ %{username} 的數據 disable: åœç”¨ - disable_two_factor_authentication: åœç”¨é›™é‡èªè‰ - disabled: å·²åœç”¨ + disable_two_factor_authentication: 關閉雙é‡èªè‰ + disabled: å·²å‡çµ display_name: 顯示å稱 domain: 域å edit: 編輯 email: é›»éƒµåœ°å€ - email_status: 电åé‚®ä»¶çŠ¶æ€ - enable: 啟用 + email_status: 電郵狀態 + enable: 解除å‡çµ enabled: 已啟用 + enabled_msg: æˆåŠŸè§£é™¤ %{username} 帳號的å‡çµ followers: 關注者 follows: æ£åœ¨é—œæ³¨ - header: é–‹é + header: 個人資料é é ‚åœ–ç‰‡ inbox_url: 收件箱(Inbox)URL + invite_request_text: åŠ å…¥çš„åŽŸå› invited_by: 邀請者 - ip: IP ä½åŸŸ + ip: IP ä½å€ joined: å·²åŠ å…¥ location: all: 全部 @@ -124,125 +140,179 @@ zh-HK: login_status: 登入狀態 media_attachments: 媒體檔案 memorialize: è¨å®šç‚ºè¿½æ‚¼å¸³æˆ¶ + memorialized: 被悼念的 + memorialized_msg: æˆåŠŸå°‡%{username} 的帳號變為紀念帳號 moderation: active: æ´»èº all: 全部 - pending: ç‰å¾…ä¸ + pending: 處ç†ä¸ silenced: 被éœéŸ³çš„ - suspended: è¢«åœæ¬Šçš„ + suspended: å·²åœæ¬Š title: ç®¡ç†æ“作 - moderation_notes: 管ç†è¨˜éŒ„ - most_recent_activity: 最新活動 - most_recent_ip: 最新 IP ä½åŸŸ - no_account_selected: 未é¸å–ä»»ä½•å¸³è™Ÿï¼Œå› æ¤æœªè®Šæ›´ + moderation_notes: 管ç†å‚™è¨» + most_recent_activity: 最近活動 + most_recent_ip: 最近的 IP ä½å€ + no_account_selected: å› æœªé¸æ“‡å¸³è™Ÿè€Œæœªæœ‰ä»»ä½•變更 no_limits_imposed: 未å—é™åˆ¶ not_subscribed: 未訂閱 pending: ç‰å¾…å¯©æ ¸ä¸ - perform_full_suspension: å®Œå…¨åœæ¬Š - promote: å‡ä»» + perform_full_suspension: å·²åœæ¬Š + promote: æå‡æ¬Šé™ protocol: å”è° - public: 公共 + public: 公開 push_subscription_expires: PuSH è¨‚é–±éŽæœŸ - redownload: æ›´æ–°é åƒ + redownload: æ›´æ–°é é¢ + redownloaded_msg: æˆåŠŸé‡æ–°è¼‰å…¥ %{username} 的個人資料é é¢ reject: 拒絕 reject_all: 全部拒絕 - remove_avatar: å–æ¶ˆé åƒ - remove_header: 移除開é + rejected_msg: æˆåŠŸæ‹’çµ•äº† %{username} 的新帳號申請 + remove_avatar: 刪除é åƒ + remove_header: 移除é é¢é ‚端 + removed_avatar_msg: æˆåŠŸåˆªé™¤ %{username} çš„é åƒ + removed_header_msg: æˆåŠŸåˆªé™¤ %{username} çš„é é¢é ‚端圖片 resend_confirmation: - already_confirmed: 该用户已被确认 - send: é‡å‘确认邮件 - success: 确认电å邮件æˆåŠŸå‘é€ï¼ + already_confirmed: 這個使用者先å‰å·²ç¶“被確èªéŽ + send: é‡å¯„確èªéƒµä»¶ + success: 確èªé›»éƒµç™¼é€æˆåŠŸï¼ reset: é‡è¨ reset_password: é‡è¨å¯†ç¢¼ resubscribe: 釿–°è¨‚é–± - role: 身份 + role: æ¬Šé™ roles: admin: 管ç†å“¡ - moderator: 監察員 - staff: 管ç†äººå“¡ - user: 普通用戶 - search: æœç´¢ - search_same_email_domain: 其他有åŒå€‹é›»å郵件網域的使用者 - search_same_ip: 其他有åŒå€‹ IP 的使用者 + moderator: 管ç†å“¡ + staff: 工作人員 + user: 普通使用者 + search: æœå°‹ + search_same_email_domain: 其他有相åŒé›»éƒµç¶²åŸŸçš„使用者 + search_same_ip: å…¶ä»–æœ‰ç›¸åŒ IP ä½å€çš„使用者 + sensitive: æ•æ„Ÿå†…容 + sensitized: å·²æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹ shared_inbox_url: 公共收件箱(Shared Inbox)URL show: - created_reports: æ¤ç”¨æˆ¶æ‰€æèˆ‰å ±çš„紀錄 - targeted_reports: æ¤ç”¨æˆ¶è¢«èˆ‰å ±çš„紀錄 + created_reports: èˆ‰å ±ç´€éŒ„ + targeted_reports: è¢«å…¶ä»–äººèˆ‰å ±çš„ç´€éŒ„ silence: éœéŸ³ silenced: å·²éœéŸ³ statuses: æ–‡ç« subscribe: 訂閱 suspended: å·²åœæ¬Š - time_in_queue: æ£åœ¨ä½‡åˆ—ç‰å¾… %{time} - title: 用戶 + suspension_irreversible: 已永久刪除æ¤å¸³è™Ÿçš„æ•¸æ“šã€‚ä½ å¯ä»¥å–消æ¤å¸³è™Ÿçš„åœæ¬Šç‹€æ…‹ï¼Œä½†å¸³è™Ÿçš„資料已被永久刪除。 + suspension_reversible_hint_html: æ¤å¸³æˆ¶å·²è¢«åœæ¬ŠåŠæ‰€æœ‰æ•¸æ“šå°‡æœƒæ–¼ %{date} 被刪除。在æ¤ä¹‹å‰ï¼Œä½ ä»å¯ä»¥å®Œå…¨å›žå¾©å¸³è™Ÿã€‚å¦‚æžœä½ æƒ³å³æ™‚刪除æ¤å¸³æˆ¶çš„資料,å¯ä»¥åœ¨ä¸‹é¢é€²è¡Œæ“作。 + time_in_queue: æŽ’éšŠä¸ %{time} + title: 帳號 unconfirmed_email: 未確èªçš„電郵 + undo_sensitized: å–æ¶ˆæ•感狀態 undo_silenced: 解除éœéŸ³ undo_suspension: è§£é™¤åœæ¬Š + unsilenced_msg: æˆåŠŸå–æ¶ˆå° %{username} 帳號的é™åˆ¶ unsubscribe: å–æ¶ˆè¨‚é–± - username: 用戶å稱 + unsuspended_msg: æˆåŠŸå–æ¶ˆå° %{username} å¸³è™Ÿçš„åœæ¬Šæ“作 + username: 使用者å稱 + view_domain: æŸ¥çœ‹åŸŸåæ¦‚è¦ warn: è¦å‘Š - web: 用戶é é¢ - whitelisted: å·²åŠ å…¥ç™½åå–® + web: é é¢ + whitelisted: å®¹è¨±äº’å‚³æ–‡ç« action_logs: action_types: - assigned_to_self_report: æŒ‡æ´¾å›žå ± - change_email_user: 變更使用者的電åä¿¡ç®±ä½å€ + assigned_to_self_report: æŒ‡æ´¾èˆ‰å ± + change_email_user: 更改使用者的電郵 confirm_user: 確èªä½¿ç”¨è€… - create_account_warning: 建立è¦å‘Š + create_account_warning: 新增è¦å‘Š create_announcement: 建立公告 - create_custom_emoji: å»ºç«‹è‡ªè¨‚é¡æ–‡å— - create_domain_allow: 建立å…許網域 - create_domain_block: 建立阻擋網域 + create_custom_emoji: 新增自訂的 Emoji + create_domain_allow: 新增å…許的域å + create_domain_block: å°éŽ–åŸŸå + create_email_domain_block: å°éŽ–é›»éƒµåŸŸå + create_ip_block: 新增IPè¦å‰‡ + demote_user: 將帳號é™ç´š + destroy_announcement: 刪除公告 + destroy_custom_emoji: 刪除自定的 Emoji 表情符號 + destroy_domain_allow: 刪除å…許的域å + destroy_domain_block: 刪除已å°éŽ–çš„åŸŸå + destroy_email_domain_block: 刪除已å°éŽ–çš„é›»éƒµåŸŽå + destroy_ip_block: 刪除 IP è¦å‰‡ + destroy_status: åˆªé™¤æ–‡ç« + disable_2fa_user: åœç”¨å…©æ¥é©Ÿé©—è‰ + disable_custom_emoji: åœç”¨è‡ªå®šçš„ Emoji 表情符號 + disable_user: åœç”¨å¸³è™Ÿ + enable_custom_emoji: 啟用自定的 Emoji 表情符號 + enable_user: 啟用帳號 + memorialize_account: 把帳號è¨å®šç‚ºæ‚¼å¿µå¸³è™Ÿ + promote_user: æå‡å¸³è™Ÿæ¬Šé™ + remove_avatar_user: 刪除é åƒ + reopen_report: é‡é–‹èˆ‰å ±å€‹æ¡ˆ + reset_password_user: é‡è¨å¯†ç¢¼ + resolve_report: è§£æ±ºèˆ‰å ±å€‹æ¡ˆ + sensitive_account: æŠŠä½ çš„å¸³è™Ÿçš„åª’é«”è¨å®šç‚ºæ•感內容 + silence_account: 把帳號éœéŸ³ + suspend_account: æŠŠå¸³è™Ÿåœæ¬Š + unassigned_report: å–æ¶ˆæŒ‡æ´¾èˆ‰å ± + unsensitive_account: å–æ¶ˆæŠŠä½ 帳號的媒體è¨å®šç‚ºæ•感內容 + unsilence_account: å–æ¶ˆå¸³è™Ÿçš„éœéŸ³ç‹€æ…‹ + unsuspend_account: å–æ¶ˆå¸³è™Ÿçš„åœæ¬Šç‹€æ…‹ + update_announcement: 更新公告 + update_custom_emoji: 更新自定的 Emoji 表情符號 + update_domain_block: 更新域å阻隔 + update_status: æ›´æ–°æ–‡ç« actions: assigned_to_self_report: "%{name} 指派了 %{target} çš„èˆ‰å ±çµ¦è‡ªå·±" - change_email_user: "%{name} 改變了用戶 %{target} 的電郵地å€" - confirm_user: "%{name} 確èªäº†ç”¨æˆ¶ %{target} 的電郵地å€" - create_account_warning: "%{name} å·²å° %{target} é€å‡ºè¦å‘Š" - create_announcement: "%{name} 建立了新公告 %{target}" - create_custom_emoji: "%{name} åŠ å…¥è‡ªè¨‚è¡¨æƒ…ç¬¦è™Ÿ %{target}" - create_domain_allow: "%{name} å°‡ %{target} ç¶²åŸŸåŠ å…¥é»‘å單了" - create_domain_block: "%{name} 阻隔了網域 %{target}" - create_email_domain_block: "%{name} 阻隔了電郵網域 %{target}" - demote_user: "%{name} 把用戶 %{target} é™ä»»" + change_email_user: "%{name} 改變了使用者 %{target} 的電郵地å€" + confirm_user: "%{name} 確èªäº†ä½¿ç”¨è€… %{target} 的電郵地å€" + create_account_warning: "%{name} å·²è¦å‘Šäº† %{target}" + create_announcement: "%{name} 新增了公告 %{target}" + create_custom_emoji: "%{name} åŠ å…¥äº†æ–°çš„ Emoji %{target}" + create_domain_allow: "%{name} å’Œ %{target} 網域çµç›Ÿäº†" + create_domain_block: "%{name} å°éŽ–äº†ç¶²åŸŸ %{target}" + create_email_domain_block: "%{name} å°éŽ–äº†é›»éƒµç¶²åŸŸ %{target}" + create_ip_block: "%{name} 已經è¨å®šäº†é‡å° IP %{target} çš„è¦å‰‡" + demote_user: "%{name} 把使用者 %{target} 陿¬Š" destroy_announcement: "%{name} 刪除了公告 %{target}" - destroy_custom_emoji: "%{name} ç ´å£žäº† %{target} 表情符號" - destroy_domain_allow: "%{name} 從白åå–®ä¸ç§»é™¤äº† %{target} 網域" - destroy_domain_block: "%{name} å–æ¶ˆäº†å°ç¶²åŸŸ %{target} 的阻隔" - destroy_email_domain_block: "%{name} å–æ¶ˆäº†å°é›»éƒµç¶²åŸŸ %{target} 的阻隔" + destroy_custom_emoji: "%{name} 刪除了 Emoji %{target}" + destroy_domain_allow: "%{name} ç¦æ¢äº†èˆ‡ %{target} 網域進行訊æ¯è¯ç¶²" + destroy_domain_block: "%{name} å–æ¶ˆäº†å°ç¶²åŸŸ %{target} çš„å°éŽ–" + destroy_email_domain_block: "%{name} å–æ¶ˆäº†å°é›»éƒµç¶²åŸŸ %{target} çš„å°éŽ–" + destroy_ip_block: "%{name} 已經刪除了 IP %{target} çš„è¦å‰‡" destroy_status: "%{name} 刪除了 %{target} çš„æ–‡ç« " - disable_2fa_user: "%{name} åœç”¨äº†ç”¨æˆ¶ %{target} 的雙é‡èªè‰" - disable_custom_emoji: "%{name} åœç”¨äº†è‡ªè¨‚表情符號 %{target}" - disable_user: "%{name} 把用戶 %{target} è¨å®šç‚ºç¦æ¢ç™»å…¥" - enable_custom_emoji: "%{name} 啟用了自訂表情符號 %{target}" - enable_user: "%{name} 把用戶 %{target} è¨å®šç‚ºå…許登入" + disable_2fa_user: "%{name} åœç”¨äº†ä½¿ç”¨è€… %{target} 的雙é‡èªè‰" + disable_custom_emoji: "%{name} åœç”¨äº† Emoji %{target}" + disable_user: "%{name} 把使用者 %{target} è¨å®šç‚ºç¦æ¢ç™»å…¥" + enable_custom_emoji: "%{name} 啟用了 Emoji %{target}" + enable_user: "%{name} 把使用者 %{target} è¨å®šç‚ºå…許登入" memorialize_account: "%{name} 把 %{target} è¨å®šç‚ºè¿½æ‚¼å¸³æˆ¶" - promote_user: "%{name} å°ç”¨æˆ¶ %{target} 进行了å‡ä»»æ“作" + promote_user: "%{name} å°æå‡äº†ä½¿ç”¨è€… %{target} 的權é™" remove_avatar_user: "%{name} å–æ¶ˆäº† %{target} çš„é åƒ" - reopen_report: "%{name} é‡é–‹ %{target} çš„èˆ‰å ±" - reset_password_user: "%{name} é‡è¨äº†ç”¨æˆ¶ %{target} 的密碼" - resolve_report: "%{name} 處ç†äº† %{target}ã€€çš„èˆ‰å ±" - silence_account: "%{name} éœéŸ³äº†ç”¨æˆ¶ %{target}" - suspend_account: "%{name} åœæ¬Šäº†ç”¨æˆ¶ %{target}" + reopen_report: "%{name} é‡é–‹ %{target} çš„èˆ‰å ±å€‹æ¡ˆ" + reset_password_user: "%{name} é‡è¨äº†ä½¿ç”¨è€… %{target} 的密碼" + resolve_report: "%{name} 處ç†äº† %{target} çš„èˆ‰å ±å€‹æ¡ˆ" + sensitive_account: "%{name} å°‡ %{target} çš„åª’é«”æª”æ¡ˆåˆ—ç‚ºæ•æ„Ÿ" + silence_account: "%{name} éœéŸ³äº†å¸³è™Ÿ %{target}" + suspend_account: "%{name} 將帳號 %{target} åœæ¬Š" unassigned_report: "%{name} å–æ¶ˆæŒ‡æ´¾ %{target} çš„èˆ‰å ±" + unsensitive_account: "%{name} å–æ¶ˆå°‡ %{target} 的媒體檔案的è¨ç‚ºæ•感" unsilence_account: "%{name} å–æ¶ˆäº†ç”¨æˆ¶ %{target} çš„éœéŸ³ç‹€æ…‹" - unsuspend_account: "%{name} å–æ¶ˆäº†ç”¨æˆ¶ %{target} çš„åœæ¬Šç‹€æ…‹" + unsuspend_account: "%{name} å–æ¶ˆäº†å¸³è™Ÿ %{target} çš„åœæ¬Šç‹€æ…‹" update_announcement: "%{name} 更新了公告 %{target}" - update_custom_emoji: "%{name} 更新了自訂表情符號 %{target}" - update_status: "%{name} 刷新了 %{target} çš„æ–‡ç« " - deleted_status: "(已刪除嘟文)" + update_custom_emoji: "%{name} 更新了 Emoji 表情符號 %{target}" + update_domain_block: "%{name} æ›´æ–°äº†å° %{target} 的域å阻隔" + update_status: "%{name} 更新了 %{target} çš„æ–‡ç« " + deleted_status: "ï¼ˆå·²åˆªé™¤æ–‡ç« ï¼‰" + empty: 找ä¸åˆ°ä»»ä½•日誌。 + filter_by_action: æŒ‰å‹•ä½œç¯©é¸ + filter_by_user: æŒ‰å¸³è™Ÿç¯©é¸ title: ç‡Ÿé‹æ—¥èªŒ announcements: destroyed_msg: æˆåŠŸåˆªé™¤å…¬å‘Šï¼ edit: title: 編輯公告 empty: 找ä¸åˆ°å…¬å‘Šã€‚ - live: ç›´æ’ + live: 在線 new: create: 建立公告 title: 新增公告 published_msg: æˆåŠŸç™¼å¸ƒå…¬å‘Šï¼ scheduled_for: 排定 %{time} - scheduled_msg: å…¬å‘Šå·²æŽ’å®šå…¬é–‹ï¼ + scheduled_msg: å…¬å‘Šå·²æŽ’ç¨‹ï¼ title: 公告 unpublished_msg: æˆåŠŸå–æ¶ˆç™¼å¸ƒå…¬å‘Šï¼ updated_msg: æˆåŠŸæ›´æ–°å…¬å‘Šï¼ @@ -251,7 +321,7 @@ zh-HK: by_domain: 網域 copied_msg: æˆåŠŸå°‡è¡¨æƒ…è¤‡è£½åˆ°æœ¬åœ° copy: 複製 - copy_failed_msg: 無法將表情複製到本地 + copy_failed_msg: 無法將表情符號複製到本地 create_new_category: 建立新分類 created_msg: 已新增表情符號 delete: 刪除 @@ -259,20 +329,22 @@ zh-HK: disable: åœç”¨ disabled: å·²åœç”¨ disabled_msg: å·²åœç”¨è¡¨æƒ…符號 - emoji: emoji + emoji: Emoji 表情符號 enable: 啟用 enabled: 已啟用 enabled_msg: 已啟用表情符號 image_hint: PNG æ ¼å¼ï¼Œæœ€å¤§ 50KB - list: 列表 - listed: 已顯示 + list: 列出 + listed: 已列出 new: - title: åŠ å…¥æ–°çš„è‡ªè¨‚è¡¨æƒ…ç¬¦è™Ÿ + title: åŠ å…¥æ–°çš„è‡ªè¨‚ Emoji 表情符號 + not_permitted: ä½ ç„¡æ¬ŠåŸ·è¡Œæ¤æ“作 overwrite: 覆蓋 shortcode: çŸä»£ç¢¼ shortcode_hint: 至少 2 個å—元,åªèƒ½ä½¿ç”¨å—æ¯ã€æ•¸å—和下劃線 - title: 自訂 emoji + title: 自訂 Emoji 表情符號 uncategorized: 未分類 + unlist: éš±è— unlisted: å·²éš±è— update_failed_msg: 無法更新表情符號 updated_msg: 已更新表情符號 @@ -281,26 +353,26 @@ zh-HK: authorized_fetch_mode: å®‰å…¨æ¨¡å¼ backlog: 未處ç†å·¥ä½œæ•¸ config: è¨å®š - feature_deletions: 帳戶刪除 + feature_deletions: 刪除帳號功能 feature_invites: é‚€è«‹é€£çµ feature_profile_directory: 個人資料目錄 feature_registrations: 註冊 - feature_relay: è¯é‚¦ä¸ç¹¼ç«™ + feature_relay: è¯ç¶²ä¸ç¹¼ç«™ feature_spam_check: é˜²åžƒåœ¾è¨Šæ¯ feature_timeline_preview: 時間軸é 覽 features: 功能 hidden_service: 與隱密æœå‹™äº’連 - open_reports: å¾…è™•ç†æª¢èˆ‰æ•¸ + open_reports: 未處ç†çš„èˆ‰å ±å€‹æ¡ˆæ•¸ pending_tags: ç‰å¾…å¯©æ ¸çš„ä¸»é¡Œæ¨™ç±¤ pending_users: ç‰å¾…å¯©æ ¸çš„ä½¿ç”¨è€… recent_users: æœ€è¿‘åŠ å…¥çš„ä½¿ç”¨è€… search: 全文æœå°‹ single_user_mode: å–®ä¸€ä½¿ç”¨è€…æ¨¡å¼ - software: 軟體 + software: 軟件 space: 儲å˜ç©ºé–“ç”¨é‡ title: å„€è¡¨æ¿ total_users: 總使用者數 - trends: 趨勢 + trends: 近期æµè¡Œ week_interactions: 本週互動次數 week_users_active: 本週活èºä½¿ç”¨è€…數 week_users_new: 本週新使用者數 @@ -311,22 +383,30 @@ zh-HK: destroyed_msg: 網域已æˆåŠŸå¾žç™½å單移除 undo: 從白å單移除 domain_blocks: - add_new: 新增 - created_msg: æ£è™•ç†åŸŸå阻隔 + add_new: 新增域å阻隔è¦å‰‡ + created_msg: æ£è™•ç†é˜»éš”域å的請求 destroyed_msg: 已撤銷域å阻隔 domain: 域å阻隔 + edit: 更改域å阻隔 + existing_domain_block_html: ä½ å·²ç¶“å° %{name} æ–½åŠ äº†æ›´åš´æ ¼çš„é™åˆ¶ï¼Œä½ 需è¦å…ˆå°ä»–<a href="%{unblock_url}">å–æ¶ˆå°éŽ–</a>。 new: create: 新增域å阻隔 - hint: "「域å阻隔ã€ä¸æœƒéš”絕該域å用戶的用戶進入本站資料庫,而是會在時候自動套用特定的審批æ“作。" + hint: "「域å阻隔ã€ä¸æœƒéš”絕該域åå¸³è™Ÿé€²å…¥æœ¬ç«™è³‡æ–™åº«ï¼Œä½†æ˜¯æœƒåœ¨ç¬¦åˆæ¢ä»¶çš„帳號進入資料庫後,自動å°å®ƒå€‘套用特定審批æ“作。" severity: - desc_html: "「<strong>自動éœéŸ³</strong>ã€ä»¤è©²åŸŸåä¸‹ç”¨æˆ¶çš„æ–‡ç« ï¼Œè¨ç‚ºåªå°é—œæ³¨è€…顯示,沒有關注的人會看ä¸åˆ°ã€‚ 「<strong>自動刪除</strong>ã€æœƒåˆªé™¤å°‡è©²åŸŸåä¸‹ç”¨æˆ¶çš„æ–‡ç« ã€åª’體檔案和個人資料。「<strong>ç„¡</strong>ã€å‰‡æœƒæ‹’絕接收來自該域å的媒體檔案。" + desc_html: "「<strong>自動éœéŸ³</strong>ã€ä»¤è©²åŸŸåä¸‹å¸³è™Ÿçš„æ–‡ç« ï¼Œè¢«è¨ç‚ºåªå°é—œæ³¨è€…顯示,沒有關注的人會看ä¸åˆ°ã€‚ 「<strong>自動刪除</strong>ã€æœƒåˆªé™¤å°‡è©²åŸŸåä¸‹ç”¨æˆ¶çš„æ–‡ç« ã€åª’體檔案和個人資料。「<strong>ç„¡</strong>ã€å‰‡æœƒæ‹’絕接收來自該域å的媒體檔案。" noop: ç„¡ silence: 自動éœéŸ³ suspend: 自動刪除 title: 新增域å阻隔 + obfuscate: 混淆域åå稱 + obfuscate_hint: 如果已經啟用了網域廣告列表é™åˆ¶ï¼Œåœ¨åˆ—表部份混淆網域å稱 + private_comment: ç§äººç•™è¨€ + private_comment_hint: è«‹æä¾›æ›´å¤šæœ‰é—œæ¤åŸŸåé™åˆ¶çš„資訊以供管ç†å“¡ä½œå…§éƒ¨åƒè€ƒã€‚ + public_comment: 公開留言 + public_comment_hint: å¦‚æžœä½ å·²ç¶“å•Ÿç”¨åŸŸåé™åˆ¶åˆ—表的公告,請為一般大眾æä¾›æ›´å¤šæœ‰é—œæ¤åŸŸåé™åˆ¶çš„資訊。 reject_media: 拒絕媒體檔案 reject_media_hint: 刪除本地緩å˜çš„媒體檔案,å†ä¹Ÿä¸åœ¨æœªä¾†ä¸‹è¼‰é€™å€‹ç«™é»žçš„æª”案。和自動刪除無關 - reject_reports: 拒絕檢舉 + reject_reports: 拒絕檢舉個案 reject_reports_hint: 忽略所有來自æ¤ç«™é»žçš„æª¢èˆ‰ã€‚èˆ‡åœæ¬Šç„¡é—œ rejecting_media: 拒絕媒體檔案 rejecting_reports: æ‹’çµ•æª¢èˆ‰ä¸ @@ -335,66 +415,120 @@ zh-HK: suspend: å·²åœæ¬Š show: affected_accounts: - other: 將影響到資料庫ä¸çš„ %{count} 個帳戶 + other: 將影響到資料庫ä¸çš„ %{count} 個帳號 retroactive: - silence: å°æ¤åŸŸåçš„æ‰€æœ‰ç”¨æˆ¶å–æ¶ˆéœéŸ³ - suspend: å°æ¤åŸŸåçš„æ‰€æœ‰ç”¨æˆ¶å–æ¶ˆé™¤å + silence: å°æ¤åŸŸåçš„æ‰€æœ‰å¸³è™Ÿå–æ¶ˆéœéŸ³ + suspend: å°æ¤åŸŸåçš„æ‰€æœ‰å¸³è™Ÿå–æ¶ˆé™¤å title: 撤銷 %{domain} 的域å阻隔 undo: 撤銷 - undo: 撤銷 + undo: 撤銷域å阻隔 + view: 顯示æ£è¢«é˜»éš”的網域 email_domain_blocks: - add_new: åŠ å…¥æ–°é …ç›® + add_new: 新增 created_msg: 已新增電郵網域阻隔 delete: 刪除 destroyed_msg: 已刪除電郵網域阻隔 domain: 網域 + empty: ç¾æ™‚並沒有電郵域å被阻隔。 + from_html: ç”±%{domain} new: create: 新增網域 title: 新增電郵網域阻隔 title: 電郵網域阻隔 instances: + by_domain: 域å + delivery_available: å¯å‚³é€ + empty: 找ä¸åˆ°åŸŸå。 + known_accounts: + other: "%{count} 已知的帳號" moderation: all: 全部 limited: é™åˆ¶ title: 版主 + private_comment: ç§äººç•™è¨€ + public_comment: 公開留言 title: 已知æœå‹™ç«™ - total_followed_by_us: é–‹å§‹é—œæ³¨ä½ + total_blocked_by_us: 被我們å°éŽ– + total_followed_by_them: 被他們關注 + total_followed_by_us: 被我們關注 + total_reported: é—œæ–¼ä»–å€‘çš„èˆ‰å ± + total_storage: 媒體附件 invites: + deactivate_all: 全部åœç”¨ filter: all: 全部 available: å¯ç”¨ expired: 已失效 title: ç¯©é¸ - title: 邀請用戶 + title: 邀請 + ip_blocks: + add_new: 新增è¦å‰‡ + created_msg: æˆåŠŸæ–°å¢ž IP è¦å‰‡ + delete: 刪除 + expires_in: + '1209600': 2 週 + '15778476': 6 個月 + '2629746': 1 個月 + '31556952': 1 å¹´ + '86400': 1 æ—¥ + '94670856': 3 å¹´ + new: + title: 新增 IP è¦å‰‡ + no_ip_block_selected: å› æœªé¸æ“‡ IP è¦å‰‡è€Œæœªæœ‰ä»»ä½•變更。 + title: IP è¦å‰‡ + pending_accounts: + title: 待處ç†å¸³æˆ¶ï¼ˆ%{count}) + relationships: + title: "%{acct} 的關係" relays: - description_html: "<strong>è¯é‚¦ä¸ç¹¼ç«™</strong> 是種ä¸ç¹¼ä¼ºæœå™¨ï¼Œæœƒåœ¨è¨‚閱並推é€è‡³æ¤ä¸ç¹¼ç«™çš„伺æœå™¨ä¹‹é–“交æ›å¤§é‡çš„公開嘟文。<strong>ä¸ç¹¼ç«™ä¹Ÿèƒ½å”助å°åž‹æˆ–ä¸åž‹ä¼ºæœå™¨å¾žè¯é‚¦ä¸æŽ¢ç´¢å…§å®¹</strong>ï¼Œè€Œç„¡é ˆæœ¬åœ°ä½¿ç”¨è€…æ‰‹å‹•é—œæ³¨é 端伺æœå™¨çš„其他使用者。" - disabled: åœç”¨ + add_new: 新增ä¸ç¹¼ + delete: 刪除 + description_html: "<strong>è¯ç›Ÿä¸ç¹¼ç«™</strong>是一種ä¸ç¹¼ä¼ºæœå™¨ï¼Œæœƒåœ¨è¨‚閱並推é€è‡³æ¤ä¸ç¹¼ç«™çš„伺æœå™¨ä¹‹é–“交æ›å¤§é‡çš„公開嘟文。<strong>ä¸ç¹¼ç«™ä¹Ÿèƒ½å”助å°åž‹æˆ–ä¸åž‹ä¼ºæœå™¨å¾žè¯é‚¦ä¸æŽ¢ç´¢å…§å®¹</strong>ï¼Œè€Œç„¡é ˆæœ¬åœ°ä½¿ç”¨è€…æ‰‹å‹•é—œæ³¨é 端伺æœå™¨çš„其他使用者。" + disable: åœç”¨ + disabled: å·²åœç”¨ enable: 啟用 + enable_hint: å•Ÿç”¨å¾Œï¼Œä½ çš„ä¼ºæœå™¨å°‡è¨‚閱該ä¸ç¹¼çš„æ‰€æœ‰å…¬é–‹æ–‡ç« ,並將會æ¤ä¼ºæœå™¨çš„å…¬é–‹æ–‡ç« ç™¼é€çµ¦å®ƒã€‚ + enabled: 已啟用 + inbox_url: ä¸ç¹¼ URL + pending: æ£åœ¨ç‰å¾…ä¸ç¹¼è¨±å¯ + save_and_enable: 儲å˜ä¸¦å•Ÿç”¨ + setup: 建立ä¸ç¹¼é€šè¨Š + signatures_not_enabled: ä¸ç¹¼ä¸æœƒåœ¨å®‰å…¨æ¨¡å¼æˆ–有é™è¯ç›Ÿæ¨¡å¼è¢«é–‹å•“的情æ³ä¸‹æ£å¸¸é‹ä½œ + status: 狀態 + title: ä¸ç¹¼ report_notes: - created_msg: èˆ‰å ±ç†è¨˜å·²å»ºç«‹ã€‚ - destroyed_msg: èˆ‰å ±ç†è¨˜å·²åˆªé™¤ã€‚ + created_msg: èˆ‰å ±å‚™è¨»å·²å»ºç«‹ï¼ + destroyed_msg: èˆ‰å ±å‚™è¨»å·²åˆªé™¤ï¼ reports: + account: + notes: + other: "%{count} 則備註" + reports: + other: "%{count} å‰‡èˆ‰å ±" action_taken_by: æ“作執行者 are_you_sure: ä½ ç¢ºèªå—Žï¼Ÿ assign_to_self: 指派給自己 - assigned: æŒ‡æ´¾è² è²¬äºº + assigned: 指派版主 + by_target_domain: è¢«èˆ‰å ±å¸³è™Ÿçš„åŸŸå comment: none: 沒有 created_at: 日期 + forwarded: 已轉寄 + forwarded_to: 已轉寄到 %{domain} mark_as_resolved: 標示為「已處ç†ã€ mark_as_unresolved: 標示為「未處ç†ã€ notes: - create: 建立ç†è¨˜ - create_and_resolve: 建立ç†è¨˜ä¸¦æ¨™ç¤ºç‚ºã€Œå·²è™•ç†ã€ - create_and_unresolve: 建立ç†è¨˜ä¸¦æ¨™ç¤ºç‚ºã€Œæœªè™•ç†ã€ + create: 建立備註 + create_and_resolve: 標示為「已處ç†ã€ä¸¦ç•™ä¸‹å‚™è¨» + create_and_unresolve: 標示為「未處ç†ã€ä¸¦ç•™ä¸‹å‚™è¨» delete: 刪除 placeholder: 記錄已執行的動作,或其他相關的更新…… - reopen: é‡é–‹èˆ‰å ± + reopen: é‡é–‹èˆ‰å ±å€‹æ¡ˆ report: 'èˆ‰å ± #%{id}' reported_account: èˆ‰å ±ç”¨æˆ¶ reported_by: èˆ‰å ±è€… resolved: å·²è™•ç† - resolved_msg: èˆ‰å ±å·²è™•ç†ã€‚ + resolved_msg: èˆ‰å ±å€‹æ¡ˆå·²è¢«è™•ç†ï¼ status: 狀態 title: èˆ‰å ± unassign: å–æ¶ˆæŒ‡æ´¾ @@ -402,41 +536,58 @@ zh-HK: updated_at: æ›´æ–° settings: activity_api_enabled: - desc_html: æœ¬ç«™ç”¨æˆ¶ç™¼ä½ˆçš„æ–‡ç« ï¼Œä»¥åŠæœ¬ç«™çš„æ´»èºç”¨æˆ¶å’Œä¸€é€±å…§æ–°ç”¨æˆ¶æ•¸ - title: 公開用戶活èºåº¦çš„統計數據 + desc_html: æœ¬ç«™çš„æ–‡ç« æ•¸é‡ã€æ´»èºä½¿ç”¨è€…數é‡ã€åŠæ¯é€±æ–°è¨»å†Šä½¿ç”¨è€…æ•¸é‡ + title: 公佈使用者活èºåº¦çš„統計數據 bootstrap_timeline_accounts: - desc_html: 以åŠå½¢é€—號分隔多個用戶å。åªèƒ½åŠ å…¥ä¾†è‡ªæœ¬ç«™ä¸”æœªé–‹å•Ÿä¿è·çš„帳號。如果留空,則默èªé—œæ³¨æœ¬ç«™æ‰€æœ‰ç®¡ç†å“¡ã€‚ - title: 新用戶默èªé—œæ³¨ + desc_html: 以åŠå½¢é€—號分隔多個使用者å稱。åªèƒ½åŠ å…¥ä¾†è‡ªæœ¬ç«™ä¸”æœªé–‹å•Ÿä¿è·çš„帳號。如果留空,則默èªé—œæ³¨æœ¬ç«™æ‰€æœ‰ç®¡ç†å“¡ã€‚ + title: 新使用者é è¨é—œæ³¨çš„å°åƒ contact_information: email: è¼¸å…¥ä¸€å€‹å…¬é–‹çš„é›»éƒµåœ°å€ - username: 輸入用戶å稱 + username: 輸入使用者å稱 + custom_css: + desc_html: é€éŽ CSS 自訂æ¯ä¸€é 的外觀 + title: 自訂 CSS + default_noindex: + desc_html: 影響所有未自行è¨å®šçš„帳號 + title: é è¨å¸³è™Ÿä¸åœ¨æœå°‹å¼•擎索引之內 domain_blocks: all: 給任何人 disabled: 給沒有人 title: 顯示å°éŽ–çš„ç¶²åŸŸ + users: 所有已登入的帳號 + domain_blocks_rationale: + title: é¡¯ç¤ºåŽŸå› äºˆ enable_bootstrap_timeline_accounts: - title: 啟用新使用者的é è¨è¿½è¹¤ + desc_html: 自動為新用戶追隨é è¨çš„帳號,為他們的首é å‹•æ…‹å¢žåŠ ä¸€é»žè‰²å½© + title: 啟用「新使用者é è¨é—œæ³¨ã€åŠŸèƒ½ hero: desc_html: 在首é é¡¯ç¤ºã€‚æŽ¨è–¦æœ€å° 600x100px。如果留空,就會默èªç‚ºæœå‹™ç«™ç¸®åœ– title: 主題圖片 + mascot: + desc_html: 在ä¸åŒé é¢é¡¯ç¤ºã€‚æŽ¨è–¦æœ€å° 293×205px。如果留空,就會默èªç‚ºä¼ºæœå™¨ç¸®åœ–。 + title: 縮圖 peers_api_enabled: desc_html: ç¾æ™‚本æœå‹™ç«™åœ¨ç¶²çµ¡ä¸å·²ç™¼ç¾çš„域å title: 公開已知æœå‹™ç«™çš„列表 preview_sensitive_media: + desc_html: 在其他é é¢é 覽的連çµå°‡æœƒåœ¨æ•感媒體的情æ³ä¸‹é¡¯ç¤ºç¸®åœ– title: 在 OpenGraph é 覽ä¸é¡¯ç¤ºæ•感媒體 profile_directory: - desc_html: å…許能探索使用者 + desc_html: å…許使用者被æœå°‹ title: 啟用個人資料目錄 registrations: closed_message: desc_html: ç•¶æœ¬ç«™æš«åœæŽ¥å—註冊時,會顯示這個訊æ¯ã€‚<br/> å¯ä½¿ç”¨ HTML title: æš«åœè¨»å†Šè¨Šæ¯ deletion: - desc_html: å…許所有人刪除自己的帳戶 - title: é–‹æ”¾åˆªé™¤å¸³æˆ¶çš„æ¬Šé™ + desc_html: å…許所有人刪除自己的帳號 + title: 容許刪除帳號 min_invite_role: disabled: 沒有人 title: å…許發é€é‚€è«‹çš„身份 + require_invite_text: + desc_html: 如果已è¨å®šç‚ºæ‰‹å‹•å¯©æ ¸æ³¨å†Šï¼Œè«‹æŠŠã€ŒåŠ å…¥çš„åŽŸå› ã€è¨å®šç‚ºå¿…å¡«é …ç›®ã€‚ + title: è¦æ±‚新用戶填寫注冊申請 registrations_mode: modes: approved: è¨»å†Šéœ€è¦æ ¸å‡† @@ -444,11 +595,11 @@ zh-HK: open: 任何人皆能註冊 title: è¨»å†Šæ¨¡å¼ show_known_fediverse_at_about_page: - desc_html: 如果開啟,就會在時間軸é è¦½é¡¯ç¤ºè·¨ç«™æ–‡ç« ï¼Œå¦å‰‡å°±åªæœƒé¡¯ç¤ºæœ¬ç«™æ–‡ç« 。 - title: 在時間軸é è¦½é¡¯ç¤ºè·¨ç«™æ–‡ç« + desc_html: 如果åœç”¨ï¼Œå°‡æœƒåªåœ¨æœ¬ç«™çš„æ¡è¿Žé é¡¯ç¤ºæœ¬ç«™çš„æ–‡ç« ã€‚ + title: 在訪客é è¦½æœ¬ç«™çš„æ™‚é–“è»¸ä¸Šï¼Œé¡¯ç¤ºè·¨ç«™æ–‡ç« show_staff_badge: - desc_html: 在個人資料é 上顯示管ç†äººå“¡æ¨™èªŒ - title: 顯示管ç†äººå“¡æ¨™èªŒ + desc_html: 在個人資料é 上顯示工作人員標誌 + title: 顯示工作人員標誌 site_description: desc_html: 在首é 顯示,åŠåœ¨ meta 標籤使用作網站介紹。<br/> ä½ å¯ä»¥åœ¨æ¤ä½¿ç”¨ <code><a></code> å’Œ <code><em></code> ç‰ HTML 標籤。 title: 本站介紹 @@ -456,12 +607,14 @@ zh-HK: desc_html: 本站詳細資訊é 的內文<br/>ä½ å¯ä»¥åœ¨æ¤ä½¿ç”¨ HTML title: 本站詳細資訊 site_short_description: + desc_html: "顯示在å´é‚Šæ¬„å’Œç¶²é æ¨™ç±¤(meta tags)。以一å¥è©±æè¿°Mastodon是甚麼,有甚麼令這個伺æœå™¨è„«\U000294D9而出。" title: 伺æœå™¨çŸæè¿° site_terms: desc_html: å¯ä»¥å¡«å¯«è‡ªå·±çš„éš±ç§æ¬Šæ”¿ç–ã€ä½¿ç”¨æ¢æ¬¾æˆ–其他法律文本。å¯ä»¥ä½¿ç”¨ HTML 標籤 title: è‡ªè¨‚ä½¿ç”¨æ¢æ¬¾ site_title: 本站å稱 spam_check_enabled: + desc_html: Mastodonå¯ä»¥è‡ªå‹•èˆ‰å ±ç”¢ç”Ÿé‡è¤‡çš„垃圾內容的帳號,ä¸éŽæœªå¿…準確。 title: è‡ªå‹•é˜²å»£å‘Šè¨Šæ¯ thumbnail: desc_html: 用於在 OpenGraph å’Œ API ä¸é¡¯ç¤ºé è¦½åœ–ã€‚æŽ¨è–¦å¤§å° 1200×630px @@ -470,7 +623,11 @@ zh-HK: desc_html: 在主é 顯示本站時間軸 title: 時間軸é 覽 title: 網站è¨å®š + trendable_by_default: + desc_html: 影響之å‰ä¸¦æœªç¦æ¢çš„æ¨™ç±¤ + title: 容許標籤ä¸éœ€è¦å¯©æ ¸ä¾†æˆç‚ºä»ŠæœŸæµè¡Œ trends: + desc_html: å…¬é–‹åœ°é¡¯ç¤ºå·²å¯©æ ¸çš„æ¨™ç±¤ç‚ºä»ŠæœŸæµè¡Œ title: 趨勢主題標籤 site_uploads: delete: 刪除上傳的檔案 @@ -490,14 +647,17 @@ zh-HK: title: å¸³æˆ¶æ–‡ç« with_media: 嫿œ‰åª’體檔案 tags: + accounts_today: 今日特殊使用 + accounts_week: 今週特殊使用 + breakdown: æ ¹æ“šä¾†æºå‰–æžæ˜¯æ—¥ç”¨é‡ context: 上下文 directory: åœ¨ç›®éŒ„ä¸ in_directory: ç›®éŒ„ä¸æœ‰ %{count} 個 last_active: ä¸Šæ¬¡æ´»èº most_popular: 最熱門 most_recent: 最近 - name: Hashtag - review: å¯©æ ¸å˜Ÿæ–‡ + name: 主題標籤 + review: å¯©æ ¸æ–‡ç« reviewed: å·²å¯©æ ¸ title: 主題標籤 trending_right_now: 最新趨勢 @@ -508,53 +668,100 @@ zh-HK: warning_presets: add_new: 新增 delete: 刪除 + edit_preset: è¨å®šè¦å‘Šé è¨ + title: 管ç†è¦å‘Šé è¨ admin_mailer: + new_pending_account: + body: ä»¥ä¸‹æ˜¯æ–°å¸³æˆ¶çš„è³‡è¨Šã€‚ä½ å¯ä»¥å¯©æ ¸é€™é …申請。 + subject: 在 %{instance} ä¸Šæœªå¯©æ ¸çš„æ–°ç”¨æˆ¶(%{username}) new_report: - body: "%{reporter} èˆ‰å ±äº†ç”¨æˆ¶ %{target}" - body_remote: 來自 %{domain} çš„ç”¨æˆ¶èˆ‰å ±äº†ç”¨æˆ¶ %{target} - subject: 來自 %{instance} çš„ç”¨æˆ¶èˆ‰å ±ï¼ˆ#%{id}) + body: "%{reporter} èˆ‰å ±äº† %{target}" + body_remote: 來自 %{domain} çš„äººèˆ‰å ±äº† %{target} + subject: é‡å° %{instance} çš„èˆ‰å ±ï¼ˆ#%{id}) + new_trending_tag: + body: '今天æµè¡Œä½¿ç”¨æœªè¢«å¯©æ ¸çš„ #%{name} ä¸»é¡Œæ¨™ç±¤ã€‚åœ¨ä½ å…許之å‰ï¼Œå®ƒä¸æœƒè¢«å…¬é–‹åœ°é¡¯ç¤ºï¼Œä½ 亦å¯ä»¥ç„¡è¦–它使它ä¸å†æ±¡æŸ“ä½ çš„çœ¼ç›ã€‚' + subject: 在 %{instance} ä¸Šæœªå¯©æ ¸çš„ä¸»é¡Œæ¨™ç±¤ (%{name}) + aliases: + add_new: 建立別å (Alias) + created_msg: æˆåŠŸå»ºç«‹åˆ¥å (alias)ã€‚ä½ å¯ä»¥å¾žèˆŠå¸³è™Ÿé–‹å§‹è½‰ç§»ã€‚ + deleted_msg: æˆåŠŸåˆªé™¤åˆ¥å (alias)ã€‚ä½ å°‡ä¸å¯ä»¥ç”±èˆŠå¸³è™Ÿè½‰ç§»åˆ°ç•¶å‰å¸³è™Ÿã€‚ + empty: ä½ æ²’æœ‰åˆ¥å (alias)。 + hint_html: å¦‚æžœä½ æƒ³ç”±å¦ä¸€å€‹å¸³æˆ¶è½‰ç§»åˆ°æ¤å¸³è™Ÿï¼Œä½ å¯ä»¥åœ¨æ¤è™•創建別å (alias)ï¼Œç„¶å¾Œç³»çµ±å®¹è¨±ä½ å°‡é—œæ³¨è€…ç”±èˆŠå¸³æˆ¶è½‰ç§»åˆ°æ¤å¸³è™Ÿã€‚æ¤æ“作是<strong>無害且å¯ä»¥é‚„原的</strong>。 <strong>帳號é·ç§»ç¨‹åºï¼Œéœ€è¦åœ¨èˆŠå¸³è™Ÿå•Ÿå‹•</strong>。 + remove: å–æ¶ˆé€£çµåˆ¥å (Alias) appearance: + advanced_web_interface: 進階網é ä»‹é¢ + advanced_web_interface_hint: å¦‚æžœä½ æƒ³å–„ç”¨æ•´å€‹èž¢å¹•é—Šåº¦ï¼Œä½ å¯ä»¥å•Ÿç”¨ã€Œé€²éšŽç¶²é 介é¢ã€ï¼Œåœ¨ç•«é¢ä¸Šé…置多個ä¸åŒçš„æ¬„ç›®ï¼Œè®“ä½ èƒ½æ ¹æ“šéœ€è¦ï¼ŒåŒæ™‚查看盡å¯èƒ½å¤šçš„ä¿¡æ¯ï¼Œæ”¯æ´çš„æ¬„ä½åŒ…括:主é ã€é€šçŸ¥ã€å…¶ä»–站點和任何的列表和標籤。 + animations_and_accessibility: 動畫和輔助功能 + confirmation_dialogs: 確èªå°è©±æ¡† + discovery: 探索 localization: body: Mastodon 是由志願者翻è¯çš„。 guide_link: https://crowdin.com/project/mastodon guide_link_text: æ¯å€‹äººéƒ½èƒ½è²¢ç»ã€‚ + sensitive_content: æ•æ„Ÿå…§å®¹ + toot_layout: ç™¼æ–‡ä»‹é¢ application_mailer: - notification_preferences: 更改電郵首é¸é … + notification_preferences: 更改電郵è¨å®š salutation: "%{name}:" settings: 修改電郵è¨å®šï¸°%{link} view: 進入ç€è¦½ï¸° view_profile: 檢視個人資料é view_status: æª¢è¦–æ–‡ç« applications: - created: 已建立應用 - destroyed: 已刪除應用 + created: å·²å»ºç«‹æ‡‰ç”¨ç¨‹å¼ + destroyed: å·²åˆªé™¤æ‡‰ç”¨ç¨‹å¼ invalid_url: 所æä¾›çš„ç¶²å€ä¸æ£ç¢º regenerate_token: é‡è¨ token token_regenerated: å·²é‡è¨ token warning: è¦å‘Šï¼Œä¸è¦æŠŠå®ƒåˆ†äº«çµ¦ä»»ä½•äººï¼ your_token: token auth: + apply_for_account: 請求邀請 change_password: 密碼 - delete_account: 刪除帳戶 - delete_account_html: å¦‚æžœä½ æƒ³åˆªé™¤ä½ çš„å¸³æˆ¶ï¼Œè«‹<a href="%{path}">點擊這裡繼續</a>ã€‚ä½ éœ€è¦ç¢ºèªä½ çš„æ“作。 + checkbox_agreement_html: æˆ‘åŒæ„ <a href="%{rules_path}" target="_blank">的伺æœå™¨è¦å‰‡</a> å’Œ<a href="%{terms_path}" target="_blank">æœå‹™æ¢æ¬¾</a> + checkbox_agreement_without_rules_html: æˆ‘åŒæ„ <a href="%{terms_path}" target="_blank">æœå‹™æ¢æ¬¾</a> + delete_account: 刪除帳號 + delete_account_html: å¦‚æžœä½ æƒ³åˆªé™¤ä½ çš„å¸³è™Ÿï¼Œè«‹<a href="%{path}">點擊這裡繼續</a>ã€‚ä½ éœ€è¦ç¢ºèªä½ çš„æ“作。 + description: + prefix_invited_by_user: "@%{name} é‚€è«‹ä½ åŠ å…¥é€™å€‹ Mastodon æœå‹™ç«™ï¼" + prefix_sign_up: ç«‹å³è¨»å†Š Mastodonï¼ + suffix: 有了一個帳戶,就å¯ä»¥å¾žä»»ä½•Mastodonæœå‹™å™¨é—œæ³¨ä»»ä½•人,發佈更新並與任何Mastodonæœå‹™å™¨çš„用戶交æµï¼ didnt_get_confirmation: æ²’æœ‰æ”¶åˆ°ç¢ºèªæŒ‡ç¤ºé›»éƒµï¼Ÿ + dont_have_your_security_key: 找ä¸åˆ°å®‰å…¨å¯†é‘°ï¼Ÿ forgot_password: 忘記了密碼? invalid_reset_password_token: 密碼é‡ç½® token ç„¡æ•ˆæˆ–å·²éŽæœŸã€‚è«‹é‡æ–°é‡è¨å¯†ç¢¼ã€‚ + link_to_otp: 請輸入兩æ¥ä®•èªè‰ç¢¼æˆ–æ¢å¾©ç¢¼ + link_to_webauth: ä½¿ç”¨ä½ çš„å®‰å…¨å¯†é‘°è£ç½® login: 登入 logout: 登出 migrate_account: 轉移到å¦ä¸€å€‹å¸³è™Ÿ migrate_account_html: 想è¦å°‡é€™å€‹å¸³è™ŸæŒ‡å‘å¦ä¸€å€‹å¸³è™Ÿå¯<a href="%{path}">到這裡è¨å®š</a>。 or_log_in_with: 或登入於 providers: + cas: CAS saml: SAML register: 登記 + registration_closed: "%{instance} 䏦䏿ޥ嗿–°æˆå“¡è«‹æ±‚" resend_confirmation: é‡ç™¼ç¢ºèªæŒ‡ç¤ºé›»éƒµ reset_password: é‡è¨å¯†ç¢¼ security: 登入資訊 set_new_password: è¨å®šæ–°å¯†ç¢¼ + setup: + email_below_hint_html: 如果下é¢çš„電郵地å€ä¸æ£ç¢ºï¼Œä½ å¯åœ¨æ¤ä¿®æ”¹ï¼Œç„¶å¾ŒæŽ¥æ”¶é›»éƒµé€²è¡Œç¢ºèªã€‚ + email_settings_hint_html: 確èªé›»éƒµå·²ç™¼é€è‡³ %{email}。電郵地å€ä¸æ£ç¢ºçš„è©±ï¼Œä½ å¯ä»¥åœ¨å¸³æˆ¶è¨ç½®ä¸é€²è¡Œæ›´æ”¹ã€‚ + title: è¨å®š + status: + account_status: å¸³æˆ¶æ–‡ç« + confirming: æ£åœ¨ç‰å¾…確èªé›»éƒµåœ°å€ã€‚ + functional: ä½ çš„å¸³æˆ¶å¯ä»¥æ£å¸¸ä½¿ç”¨ã€‚ + pending: 管ç†å“¡æ£åœ¨è™•ç†ä½ 的申請。å¯èƒ½æœƒéœ€è¦ä¸€é»žæ™‚間處ç†ã€‚æˆ‘å€‘å°‡æœƒåœ¨ç”³è«‹è¢«æ‰¹æº–çš„æ™‚å€™é¦¬ä¸Šå¯„é›»éƒµçµ¦ä½ ã€‚ + redirecting_to: ä½ çš„å¸³æˆ¶å› ç‚ºæ£åœ¨é‡æ–°å®šå‘到 %{acct},所以暫時被åœç”¨ã€‚ + too_fast: ä½ å¤ªå¿«éžäº¤äº†ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚ + trouble_logging_in: ä¸èƒ½ç™»å…¥ï¼Ÿ + use_security_key: 使用安全密鑰è£ç½® authorize_follow: already_following: ä½ å·²ç¶“é—œæ³¨äº†é€™å€‹å¸³è™Ÿ - already_requested: 您早已å‘該帳戶寄é€è¿½è¹¤è«‹æ±‚ + already_requested: ä½ å…ˆå‰å·²å‘該帳號發é€é—œæ³¨è«‹æ±‚ error: å°ä¸èµ·ï¼Œå°‹æ‰¾é€™å€‹è·¨ç«™ç”¨æˆ¶çš„éŽç¨‹ç™¼ç”ŸéŒ¯èª¤ follow: 關注 follow_request: 關注請求已發é€ç»™ï¼š @@ -564,6 +771,19 @@ zh-HK: return: 顯示個人資料é web: 返回本站 title: 關注 %{acct} + challenge: + confirm: 繼續 + hint_html: "<strong>温馨æç¤º</strong> æˆ‘å€‘åœ¨æœªä¾†ä¸€å°æ™‚內䏿œƒå†è¦æ±‚ä½ å¡«å¯«å¯†ç¢¼ã€‚" + invalid_password: 密碼錯誤 + prompt: 確èªå¯†ç¢¼ä»¥ç¹¼çºŒ + crypto: + errors: + invalid_key: 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„ Ed25519 或 Curve25519 密鑰 + invalid_signature: 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„ Ed25519 ç°½å + date: + formats: + default: "%Yå¹´%b月%dæ—¥" + with_month_name: "%B %d, %Y" datetime: distance_in_words: about_x_hours: "%{count}å°æ™‚å‰" @@ -579,14 +799,33 @@ zh-HK: x_months: "%{count}個月" x_seconds: "%{count}ç§’" deletes: + challenge_not_passed: ä½ å¡«å¯«çš„è³‡æ–™ä¸æ£ç¢º confirm_password: è¼¸å…¥ä½ ç¾åœ¨çš„密碼來驗è‰èº«ä»½ + confirm_username: è«‹å¡«å¯«ä½ çš„ç™»å…¥å稱以確èªç¨‹åº proceed: 刪除帳戶 success_msg: ä½ çš„å¸³æˆ¶å·²ç¶“æˆåŠŸåˆªé™¤ + warning: + before: 在繼續之å‰ï¼Œè«‹ä»”細閱讀以下說明: + caches: 已被其他æœå‹™å™¨ç·©å˜çš„內容å¯èƒ½ä¸æœƒæ¶ˆå¤± + data_removal: ä½ çš„æ–‡ç« å’Œå…¶ä»–è³‡æ–™å°‡è¢«æ°¸ä¹…åˆªé™¤ + email_change_html: ä½ å¯ä»¥åœ¨ä¸åˆªé™¤å¸³æˆ¶çš„æƒ…æ³ä¸‹<a href="%{path}">更改電å郵件地å€</a> + email_contact_html: 如果ä»ç„¶æ²’有é€é”ï¼Œä½ å¯ä»¥é€šéŽé›»å郵件發é€åˆ°<a href="mailto:%{email}">%{email}</a>以ç²å¾—å”助 + email_reconfirmation_html: å¦‚æžœä½ æ²’æœ‰æ”¶åˆ°ç¢ºèªé›»éƒµï¼Œä½ å¯ä»¥<a href="%{path}">è¦æ±‚冿¬¡ç™¼é€å®ƒ</a> + irreversible: ä½ å°‡ç„¡æ³•é‡å•Ÿä½ 的帳戶 + more_details_html: è«‹åƒè¦‹<a href="%{terms_path}">éš±ç§æ”¿ç–</a>以ç€è¦½ç´°ç¯€ã€‚ + username_available: ä½ çš„ç™»å…¥å稱將å¯è¢«å…¶ä»–人使用 + username_unavailable: ä½ çš„ç™»å…¥å稱將ä¸èƒ½è®“其他人使用 + directories: + directory: 個人資料目錄 + explanation: æ ¹æ“šèˆˆè¶£èªè˜æ–°æœ‹å‹ + explore_mastodon: 探索%{title} + domain_validator: + invalid_domain: 䏿˜¯ä¸€å€‹å¯ç”¨åŸŸå errors: - '400': The request you submitted was invalid or malformed. + '400': ä½ çš„è«‹æ±‚ç„¡æ•ˆæˆ–æ ¼å¼ä¸æ£ç¢ºã€‚ '403': ä½ æ²’æœ‰è§€çœ‹æœ¬é 的權é™ã€‚ '404': 找ä¸åˆ°å…§å®¹ã€‚ - '406': This page is not available in the requested format. + '406': ç„¡æ³•æ ¹æ“šçš„æ ¼å¼é¡¯ç¤ºæ¤é é¢ '410': 內容已被刪除。 '422': content: 無法確èªç™»å…¥è³‡è¨Šã€‚æœƒä¸æœƒä½ 阻擋了本站使用 Cookies 的權é™ï¼Ÿ @@ -595,38 +834,100 @@ zh-HK: '500': content: 抱æ‰ï¼Œæˆ‘們的後å°å‡ºéŒ¯äº†ã€‚ title: 這個é 颿œ‰å•題 - '503': The page could not be served due to a temporary server failure. + '503': å› çŸæš«çš„伺æœå™¨éŒ¯èª¤è€Œæœªèƒ½æä¾›æ¤é é¢ noscript_html: 使用 Mastodon ç¶²é 版應用需è¦å•Ÿç”¨ JavaScriptã€‚ä½ ä¹Ÿå¯ä»¥é¸æ“‡é©ç”¨æ–¼ä½ 的平å°çš„ <a href="%{apps_path}">Mastodon 應用</a>。 + existing_username_validator: + not_found: ç„¡æ³•æ‰¾åˆ°ä½æ–¼æœ¬ä¼ºæœå™¨çš„用戶 + not_found_multiple: 無法找到%{usernames} exports: archive_takeout: date: 日期 download: 下載檔案 - hint_html: ä½ å¯ä»¥ä¸‹è¼‰åŒ…å«ä½ çš„<strong>æ–‡ç« å’Œåª’é«”</strong>的檔案。資料以 ActivityPub æ ¼å¼å„²å˜ï¼Œå¯ç”¨æ–¼ç›¸å®¹çš„è»Ÿé«”ã€‚ä½ å¯ä»¥æ¯ä¸ƒå¤©ä¸‹è¼‰ä¸€æ¬¡ã€‚ + hint_html: ä½ å¯ä»¥ä¸‹è¼‰åŒ…å«ä½ çš„<strong>æ–‡ç« å’Œåª’é«”</strong>的檔案。資料以 ActivityPub æ ¼å¼å„²å˜ï¼Œå¯ç”¨æ–¼ç›¸å®¹çš„è»Ÿé«”ã€‚ä½ å¯ä»¥æ¯ 7 天下載一次。 in_progress: 檔案製作ä¸... request: 下載檔案 size: æª”æ¡ˆå¤§å° blocks: è¢«ä½ å°éŽ–çš„ç”¨æˆ¶ + bookmarks: 書籤 csv: CSV + domain_blocks: 域åå°éŽ– lists: 列表 mutes: ä½ æ‰€éœéŸ³çš„用戶 storage: 媒體容é‡å¤§å° + featured_tags: + add_new: 新增 + errors: + limit: ä½ æ‰€æŽ¨è–¦çš„æ¨™ç±¤æ•¸é‡å·²ç¶“é”åˆ°ä¸Šé™ + hint_html: "<strong>甚麼是推薦主題標籤?</strong> å®ƒå€‘æœƒè¢«é¡¯ç¤ºåœ¨ä½ çš„å€‹äººè³‡æ–™é é¢ï¼Œè®“其他人å¯ä»¥æ ¹æ“šæ¨™ç±¤ç€è¦½ä½ çš„å…¬é–‹æ–‡ç« ï¼Œä»¤äººå€‘æ›´æ˜“æ‰¾åˆ°ä½ å‰µä½œæˆ–è€…é•·æœŸä½œå“ï¼" filters: + contexts: + account: 個人資料 + home: 主é 和列表 + notifications: 通知 + public: 公共時間軸 + thread: å°è©± + edit: + title: 編輯篩é¸å™¨ + errors: + invalid_context: 沒有æä¾›å…§æ–‡æˆ–內文無效 + invalid_irreversible: ä¸å¯é€†çš„篩é¸å™¨åªé©ç”¨æ”¾ä¸»é 或通知é é¢ index: - empty: æ‚¨æ²’æœ‰éŽæ¿¾å™¨ã€‚ + delete: 刪除 + empty: ä½ æ²’æœ‰éŽæ¿¾å™¨ã€‚ + title: ç¯©é¸ + new: + title: 新增篩é¸å™¨ footer: + developers: 開發者 more: 更多...... + resources: é …ç›® + trending_now: 今期æµè¡Œ generic: all: 全部 changes_saved_msg: å·²æˆåŠŸå„²å˜ä¿®æ”¹ã€‚ copy: 複製 + delete: 刪除 + no_batch_actions_available: æ¤é 目沒有å¯ç”¨çš„æ‰¹æ¬¡æ“作 + order_by: æŽ’åº save_changes: 儲å˜ä¿®æ”¹ validation_errors: other: æäº¤çš„資料有 %{count} é …å•題 + html_validator: + invalid_markup: 嫿œ‰ç„¡æ•ˆçš„HTML標記:%{error} + identity_proofs: + active: æ´»èº + authorize: 是的,請授權 + authorize_connection_prompt: 授權æ¤åŠ å¯†é€šè¨Šï¼Ÿ + errors: + failed: åŠ å¯†é€šè¨Šå¤±æ•—ã€‚è«‹åœ¨%{provider} é‡è©¦ã€‚ + keybase: + invalid_token: Keybase tokens必定為66個16ä½å…ƒå—ç¬¦çš„ç°½åæª”散列。 + verification_failed: Keybaseä¸èƒ½è˜åˆ¥æ¤ä»¤ç‰Œç‚ºKeybase用戶%{kb_username} 的簽å。請在Keybaseå†è©¦ä¸€æ¬¡ã€‚ + wrong_user: 未能以%{current} 為 %{proving} 建立身份驗è‰ã€‚請登入為%{proving} å†è©¦ä¸€æ¬¡ã€‚ + explanation_html: 在æ¤ä½ 連çµå…¶ä»–網路平å°ï¼ˆå¦‚ Keybaseï¼‰ä¸Šçš„åŠ å¯†èº«ä»½ã€‚è®“å…¶ä»–äººå¯ä»¥åœ¨é‚£äº›å¹³å°ä¸Šï¼Œå‚³é€åŠ å¯†ä¿¡æ¯çµ¦ä½ ,並驗è‰ä½ 的身份。 + i_am_html: 我是 %{service} 上的 %{username} + identity: 身份 + inactive: åœç”¨ + publicize_checkbox: ç™¼è¡¨æ–‡ç« ï¼š + publicize_toot: é©—è‰æˆåŠŸï¼æˆ‘在%{service} 是%{username} :%{url} + remove: åˆªé™¤å¸³è™Ÿçš„é©—è‰ + removed: æˆåŠŸåˆªé™¤èº«ä»½é©—è‰ + status: 確èªç‹€æ…‹ + view_proof: æŸ¥çœ‹è‰æ˜Ž imports: + errors: + over_rows_processing_limit: 包å«è¶…éŽ %{count} 行 + modes: + merge: åˆä½µ + merge_long: ç•™ä¸‹èˆŠæœ‰è¨˜éŒ„ä¸¦æ·»åŠ æ–°çš„è³‡è¨Š + overwrite: 覆蓋 + overwrite_long: 用新記錄覆蓋當å‰è¨˜éŒ„ preface: ä½ å¯ä»¥åœ¨æ¤åŒ¯å…¥ä½ 在其他æœå‹™ç«™æ‰€åŒ¯å‡ºçš„è³‡æ–™æª”ï¼ŒåŒ…æ‹¬ï¸°ä½ æ‰€é—œæ³¨çš„ç”¨æˆ¶ï¼Œè¢«ä½ å°éŽ–çš„ç”¨æˆ¶ã€‚ success: ä½ å·²æˆåŠŸä¸Šè¼‰è³‡æ–™æª”ï¼Œæˆ‘å€‘æ£å°‡è³‡æ–™åŒ¯å…¥ï¼Œè«‹ç¨å€™ types: blocking: è¢«ä½ å°éŽ–çš„ç”¨æˆ¶åå–® + bookmarks: 書籤 + domain_blocking: 域åå°éŽ–åå–® following: ä½ æ‰€é—œæ³¨çš„ç”¨æˆ¶åå–® muting: éœéŸ³åå–® upload: 上載 @@ -658,11 +959,45 @@ zh-HK: media_attachments: validations: images_and_video: ä¸èƒ½åœ¨å·²æœ‰åœ–ç‰‡çš„æ–‡ç« ä¸ŠåŠ å…¥å½±ç‰‡ + not_ready: ç„¡æ³•é™„åŠ å°šæœªè™•ç†å®Œçš„æª”案。 è«‹ç¨å¾Œå†è©¦ï¼ too_many: ä¸å¯ä»¥åŠ å…¥è¶…éŽ 4 個檔案 migrations: acct: 新帳戶的 用戶å@域å + cancel: å–æ¶ˆå®šå‘ + cancel_explanation: å–æ¶ˆé‡æ–°å®šå‘å°‡æœƒé‡æ–°æ¿€æ´»ç•¶å‰å¸³æˆ¶ï¼Œä½†ä¸¦ä¸æœƒé‚„原已移至該帳戶的關注者。 + cancelled_msg: æˆåŠŸå–æ¶ˆå®šå‘。 + errors: + already_moved: 是已經移至的相åŒå¸³æˆ¶ + missing_also_known_as: 䏿˜¯æ¤å¸³æˆ¶çš„別å(alias) + move_to_self: ä¸èƒ½ç§»è‡³ç•¶å‰å¸³æˆ¶ + not_found: 找ä¸åˆ° + on_cooldown: ä½ æ£åœ¨è™•於冷å»ç‹€æ…‹ + followers_count: 轉移時的追隨者 + incoming_migrations: ç”±å¦ä¸€å€‹å¸³è™Ÿè½‰ç§» + incoming_migrations_html: è¦ç”±å…¶ä»–帳戶轉移至當å‰å¸³æˆ¶çš„è©±ï¼Œé¦–å…ˆä½ éœ€è¦ <a href="%{path}">新增帳戶別å(alias)</a>. + moved_msg: ä½ çš„å¸³è™Ÿæ£è¢«è½‰æŽ¥è‡³ %{acct} ï¼Œä½ çš„é—œæ³¨è€…æ£åœ¨åŒæ¥è½‰ç§»è‡³è©²å¸³è™Ÿã€‚ + not_redirecting: ä½ çš„å¸³è™Ÿç¾æ™‚ä¸¦æœªè¢«é‡æ–°å®šå‘。 + on_cooldown: ä½ æœ€è¿‘å·²ç¶“è½‰ç§»éŽå¸³æˆ¶ã€‚æ¤åŠŸèƒ½å°‡åœ¨ %{count} 天後å¯é‡æ–°ä½¿ç”¨ã€‚ + past_migrations: 以往的帳戶轉移 + proceed_with_move: 移動追隨者 + redirected_msg: ä½ çš„å¸³æˆ¶å³å°‡è¢«é‡æ–°å®šå‘至%{acct}。 + redirecting_to: ä½ çš„å¸³æˆ¶æ£è¢«é‡æ–°å®šå‘至%{acct}。 + set_redirect: è¨å®šé‡æ–°å®šå‘ + warning: + backreference_required: æ–°å¸³æˆ¶å¿…é ˆé¦–å…ˆå呿¨™è˜(back-reference)ç•¶å‰å¸³æˆ¶ + before: 在繼續之å‰ï¼Œè«‹ä»”細閱讀以下說明: + cooldown: åœ¨è½‰ç§»å¸³è™Ÿä¹‹å¾Œå°‡æœƒæœ‰ä¸€æ®µå†·å»æ™‚é–“ï¼Œåœ¨å†·å»æ™‚é–“å…§ä½ å°‡ä¸èƒ½å†æ¬¡è½‰ç§»å¸³è™Ÿ + disabled_account: ä½ çš„ç•¶å‰å¸³è™Ÿå°‡ä¸èƒ½å®Œæ•´åœ°é‹ä½œã€‚ä½†ä½ å°‡æœƒæœ‰æ¬ŠåŠ›åŒ¯å‡ºä½ çš„æ•¸æ“šå’Œé‡æ–°å•Ÿç”¨ä½ 的帳號。 + followers: æ¤æ“作將會由當å‰å¸³è™Ÿè½‰ç§»æ‰€æœ‰è¿½éš¨è€…至新帳號 + only_redirect_html: å¦å¤–ï¼Œä½ äº¦å¯<a href="%{path}">åªåœ¨ä½ 的個人資料é 颿”¾ä¸Šé‡æ–°å®šå‘標記</a>. + other_data: 䏦䏿œƒè‡ªå‹•轉移其他數據 + redirect: ä½ çš„ç•¶å‰å¸³è™Ÿçš„個人資料é é¢å°‡æœƒåŠ ä¸Šä¸€å€‹é‡æ–°å®šå‘公告,並會在æœå°‹çµæžœä¸è¢«å‰”除。 moderation: title: ç‡Ÿé‹ + move_handler: + carry_blocks_over_text: æ¤ç”¨æˆ¶å¾ž%{acct} è½‰ç§»ï¼Œè©²å¸³è™Ÿå·²è¢«ä½ å°éŽ–ã€‚ + carry_mutes_over_text: æ¤ç”¨æˆ¶å¾ž%{acct} è½‰ç§»ï¼Œè©²å¸³è™Ÿå·²è¢«ä½ éœéŸ³ã€‚ + copy_account_note_text: æ¤ç”¨æˆ¶å¾ž%{acct} è½‰ç§»ï¼Œé€™æ˜¯ä½ ä¹‹å‰åœ¨è©²å¸³è™Ÿç•™ä¸‹çš„備注: notification_mailer: digest: action: 查看所有通知 @@ -674,9 +1009,9 @@ zh-HK: other: "è‡ªå¾žä¸Šæ¬¡ç™»å…¥ä»¥ä¾†ï¼Œä½ æ”¶åˆ° %{count} 則新的通知 \U0001F418" title: åœ¨ä½ ä¸åœ¨çš„這段時間…… favourite: - body: æ‚¨çš„æ–‡ç« è¢« %{name} æ”¶è—: - subject: "%{name} æ”¶è—äº†ä½ çš„æ–‡ç« " - title: æ–°çš„æ”¶è— + body: ä½ çš„æ–‡ç« è¢« %{name} 喜愛: + subject: "%{name} å–œæ¡ä½ çš„æ–‡ç« " + title: 新的最愛 follow: body: "%{name} é–‹å§‹é—œæ³¨ä½ ï¼" subject: "%{name} ç¾æ£é—œæ³¨ä½ " @@ -692,32 +1027,94 @@ zh-HK: subject: "%{name} åœ¨æ–‡ç« ä¸æåŠä½ " title: æ–°çš„æåŠ reblog: - body: æ‚¨çš„æ–‡ç« è¢« %{name} 轉推: + body: ä½ çš„æ–‡ç« è¢« %{name} 轉推: subject: "%{name} è½‰æŽ¨äº†ä½ çš„æ–‡ç« " title: 新的轉推 + notifications: + email_events: 電郵通知活動 + email_events_hint: 鏿“‡ä½ 想接收通知的活動: + other_settings: 其他通知è¨å®š number: human: decimal_units: format: "%n%u" units: - billion: B - million: M - quadrillion: Q - thousand: K - trillion: T + billion: åå„„ + million: ç™¾è¬ + quadrillion: åƒå…† + thousand: åƒ + trillion: å…† + otp_authentication: + code_hint: è«‹è¼¸å…¥ä½ èªè‰å™¨æ‰€ç”¢ç”Ÿçš„代碼,以確èªè¨å®š + description_html: ç•¶ä½ å•Ÿç”¨<strong>é›™é‡èªè‰</strong>å¾Œï¼Œä½ ç™»å…¥æ™‚å°‡éœ€è¦ä½¿ç”¨ä½ 的手機或其他èªè‰å™¨æ‰€ç”¢ç”Ÿçš„代碼。 + enable: 啟用 + instructions_html: "<strong>è«‹ç”¨ä½ æ‰‹æ©Ÿçš„èªè‰å™¨æ‡‰ç”¨ç¨‹å¼ï¼ˆå¦‚ Google Authenticatorã€Authy),掃æé€™è£çš„QR 圖形碼</strong>。在雙é‡èªè‰å•Ÿç”¨å¾Œï¼Œä½ ç™»å…¥æ™‚å°‡é ˆè¦ä½¿ç”¨æ¤æ‡‰ç”¨ç¨‹å¼ç”¢ç”Ÿçš„èªè‰ç¢¼ã€‚" + manual_instructions: å¦‚æžœä½ ç„¡æ³•æŽƒæ QR 圖形碼,請手動輸入這個文å—密碼︰ + setup: è¨å®š + wrong_code: ä½ è¼¸å…¥çš„èªè‰ç¢¼ä¸¦ä¸æ£ç¢ºï¼å¯èƒ½ä¼ºæœå™¨æ™‚é–“å’Œä½ æ‰‹æ©Ÿä¸ä¸€è‡´ï¼Œè«‹æª¢æŸ¥ä½ 手機的時é˜ï¼Œæˆ–與本站管ç†å“¡è¯çµ¡ã€‚ pagination: newer: 較新 next: 下一é older: 較舊 prev: 上一é truncate: "……" + polls: + errors: + already_voted: ä½ å·²æŠ•ç¥¨ + duplicate_options: 嫿œ‰é‡è¦†é …ç›® + duration_too_long: å¤ªä¹…äº†ï¼ + duration_too_short: æ™‚é–“å¤ªè¿‘äº†ï¼ + expired: æŠ•ç¥¨å·²çµæŸ + invalid_choice: ä½ æ‰€é¸çš„æŠ•票é¸é …ä¸å˜åœ¨ + over_character_limit: ä¸èƒ½å¤šæ–¼ %{max} 個å—符 + too_few_options: 一定è¦å¤šæ–¼ä¸€å€‹é …ç›® + too_many_options: ä¸èƒ½å¤šæ–¼ %{max} å€‹é …ç›® + preferences: + other: å…¶ä»– + posting_defaults: 發佈é è¨å€¼ + public_timelines: 公共時間軸 + reactions: + errors: + limit_reached: å·²é”到å¯ä»¥çµ¦äºˆåæ‡‰æ¥µé™ + unrecognized_emoji: ä¸èƒ½è˜åˆ¥é€™å€‹emoji relationships: + activity: 帳戶活動 + dormant: 潛在 + follow_selected_followers: 關注所é¸çš„追隨者 + followers: 追隨者 + following: æ£åœ¨é—œæ³¨ + invited: 已邀請 + last_active: ä¸Šæ¬¡æ´»èº + most_recent: 最近 + moved: 已轉移 + mutual: å…±åŒ + primary: ä¸»è¦ + relationship: 關係 + remove_selected_domains: 從所é¸ä¼ºæœå™¨æ¸…除所有追隨者 remove_selected_followers: 刪除所é¸é¸é … + remove_selected_follows: å–æ¶ˆé—œæ³¨æ‰€é¸ç”¨æˆ¶ + status: 帳戶帖文 remote_follow: - acct: è«‹è¼¸å…¥ä½ çš„ï¸°ç”¨æˆ¶å稱@æœå‹™é»žåŸŸå + acct: è«‹è¼¸å…¥ä½ æƒ³ä½¿ç”¨çš„ã€Œä½¿ç”¨è€…å稱@域åã€èº«ä»½ missing_resource: ç„¡æ³•æ‰¾åˆ°ä½ ç”¨æˆ¶çš„è½‰æŽ¥ç¶²å€ + no_account_html: æ²’æœ‰å¸³è™Ÿï¼Ÿä½ å¯ä»¥<a href='%{sign_up_path}' target='_blank'>在這è£è¨»å†Š</a> proceed: ä¸‹ä¸€æ¥ prompt: ä½ å¸Œæœ›é—œæ³¨ï¸° + reason_html: "<strong>為甚麼有必è¦åšé€™å€‹æ¥é©Ÿï¼Ÿ</strong>å› ç‚º<code>%{instance}</code>æœªå¿…æ˜¯ä½ è¨»å†Šçš„ä¼ºæœå™¨ï¼Œæ‰€ä»¥æˆ‘們首先需è¦å°‡ä½ å¸¶å›žä½ çš„ä¼ºæœå™¨ã€‚" + remote_interaction: + favourite: + proceed: ä¸‹ä¸€æ¥ + prompt: ä½ è¦æ±‚æŠŠé€™ç¯‡æ–‡ç« åŠ å…¥æœ€æ„›ï¼š + reblog: + proceed: 繼續轉嘟 + prompt: ä½ æƒ³è½‰æŽ¨ï¼š + reply: + proceed: ä¸‹ä¸€æ¥ + prompt: ä½ æƒ³å›žè¦†ï¼š + scheduled_statuses: + over_daily_limit: ä½ å·²ç¶“è¶…è¶Šäº†ç•¶å¤©æŽ’å®šç™¼æ–‡çš„é™é¡ (%{limit}) + over_total_limit: ä½ å·²ç¶“è¶…è¶Šäº†æŽ’å®šç™¼æ–‡çš„é™é¡ (%{limit}) + too_soon: ä¸å¯ä»¥æ”¹è®ŠéŽåŽ»å“¦ï¼Œå˜Ÿæ–‡åªå¯ä»¥æŽ’定在未來 sessions: activity: 最近活動 browser: ç€è¦½å™¨ @@ -744,25 +1141,49 @@ zh-HK: explanation: 這些是ç¾åœ¨æ£ç™»å…¥æ–¼ä½ çš„ Mastodon 帳號的ç€è¦½å™¨ã€‚ ip: IP ä½å€ platforms: + adobe_air: Adobe Air + android: Android + blackberry: Blackberry + chrome_os: ChromeOS + firefox_os: Firefox OS ios: iOS + linux: Linux mac: Mac + other: æœªçŸ¥å¹³å° + windows: Windows + windows_mobile: Windows Mobile + windows_phone: Windows Phone revoke: å–æ¶ˆ revoke_success: 作æ¥éšŽæ®µæˆåŠŸå–æ¶ˆ title: 作æ¥éšŽæ®µ settings: + account: 帳戶 + account_settings: 帳戶è¨å®š + aliases: 帳戶別å(aliases) + appearance: 外觀è¨å®š authorized_apps: æŽˆæ¬Šæ‡‰ç”¨ç¨‹å¼ back: 回到 Mastodon delete: 刪除帳戶 development: 開發 edit_profile: 修改個人資料 export: 匯出 + featured_tags: 推薦的標籤 + identity_proofs: èº«ä»½é©—è‰ import: 匯入 + import_and_export: 匯入åŠåŒ¯å‡º migrate: 帳戶é·ç§» notifications: 通知 preferences: å好è¨å®š + profile: 個人資料 + relationships: 關注åŠè¿½éš¨è€… two_factor_authentication: é›™é‡èªè‰ + webauthn_authentication: 安全鑰匙 + spam_check: + spam_detected: æ¤ç‚ºç³»çµ±çš„è‡ªå‹•å ±å‘Šï¼šå·²ç™¼ç¾åžƒåœ¾è¨Šæ¯ã€‚ statuses: attached: + audio: + other: "%{count} 段影片" description: 附件: %{attached} image: other: "%{count} 幅圖片" @@ -773,7 +1194,7 @@ zh-HK: disallowed_hashtags: other: 包å«ä¸å…許的標籤: %{tags} errors: - in_reply_not_found: 您嘗試回覆的嘟文看起來ä¸å˜åœ¨ã€‚ + in_reply_not_found: ä½ æ‰€å›žè¦†çš„å˜Ÿæ–‡ä¸¦ä¸å˜åœ¨ã€‚ language_detection: è‡ªå‹•åµæ¸¬èªžè¨€ open_in_web: 開啟網é over_character_limit: è¶…éŽäº† %{max} å—çš„é™åˆ¶ @@ -783,8 +1204,16 @@ zh-HK: private: ä¸èƒ½ç½®é ‚éžå…¬é–‹çš„æ–‡ç« reblog: ä¸èƒ½ç½®é ‚轉推 poll: + total_people: + other: "%{count} 人" + total_votes: + other: "%{count} 票" vote: 投票 show_more: 顯示更多 + show_newer: 顯示較新嘟文 + show_older: 顯示較舊嘟文 + show_thread: 顯示討論串 + sign_in_to_participate: ç™»å…¥ä»¥åŠ å…¥è¨Žè«– title: "%{name}:「%{quote}ã€" visibilities: private: 關注者觀看 @@ -797,7 +1226,90 @@ zh-HK: pinned: ç½®é ‚æ–‡ç« reblogged: 轉推 sensitive_content: æ•æ„Ÿå…§å®¹ + tags: + does_not_match_previous_name: 和舊有å稱並ä¸ç¬¦åˆ terms: + body_html: | + <h2>éš±ç§æ¬Šæ”¿ç–</h2> + <h3 id="collect">我們è’集甚麼資訊?</h3> + + <ul> + <li><em>基本帳戶資訊</em>ï¼šå¦‚æžœæ‚¨åœ¨æ¤æœå‹™å™¨ä¸Šè¨»å†Šï¼Œæˆ‘們å¯èƒ½æœƒè¦æ±‚您輸入用戶åã€é›»å郵件地å€å’Œå¯†ç¢¼ã€‚ 您還å¯ä»¥è¼¸å…¥å…¶ä»–個人資料信æ¯ï¼ˆä¾‹å¦‚顯示å稱和自我簡介),並上傳個人資料圖片和標題圖片。 用戶åã€é¡¯ç¤ºå稱ã€è‡ªæˆ‘簡介ã€å€‹äººè³‡æ–™åœ–片和標題圖片會æŒçºŒå…¬é–‹ã€‚</li> + <li><em>帖文,關注和其他公共信æ¯</em>:您的關注和追隨者å單為公開資訊。 在發佈帖文時,我們將會å˜å„²æ—¥æœŸå’Œæ™‚é–“ï¼Œä»¥åŠæ‚¨ç”¨ä»¥ç™¼ä½ˆå¸–文的應用程åºã€‚ 帖文å¯èƒ½åŒ…å«å¤šåª’é«”é™„ä»¶ï¼Œä¾‹å¦‚åœ–ç‰‡å’Œè¦–é »ã€‚ 公開和éžå…¬é–‹(unlisted)的帖文為公開資訊。 您在個人資料上推薦的帖文時也是公開的資訊。 æ‚¨çš„è¿½éš¨è€…æœƒæ”¶åˆ°ä½ çš„å¸–æ–‡ï¼Œåœ¨æŸäº›æƒ…æ³ä¸‹ï¼Œå®ƒå€‘有å¯èƒ½æœƒåœ¨ä¸åŒçš„æœå‹™å™¨äº’ç›¸å‚³éžä¸¦å°‡å„²å˜å‰¯æœ¬ã€‚ æ‚¨åˆªé™¤å¸–æ–‡æ™‚äº¦åŒæ¨£æœƒå‚³éžçµ¦æ‚¨çš„追隨者。 轉發或收è—其他帖文的æ“作始終是公開的。</li> + <li><em>ç§è¨Šå’Œè¿½éš¨è€…é™å®šçš„帖文</em>:所有的帖å都在æœå‹™å™¨ä¸Šè¢«å„²å˜å’Œè™•ç†ã€‚ 追隨者é™å®šçš„帖文將傳éžçµ¦æ‚¨çš„è¿½éš¨è€…å’Œå…¶ä¸æåŠçš„用家,而ç§è¨Šåƒ…會傳éžçµ¦å…¶ä¸æåŠçš„用戶。 在æŸäº›æƒ…æ³ä¸‹ï¼Œå®ƒå€‘有å¯èƒ½æœƒåœ¨ä¸åŒçš„æœå‹™å™¨äº’ç›¸å‚³éžä¸¦å°‡å„²å˜å‰¯æœ¬ã€‚ æˆ‘å€‘å°‡åŠªåŠ›åœ°å°‡è¨ªå•æ¬Šé™åˆ¶ç‚ºåƒ…授權人員,但其他æœå‹™å™¨å¯èƒ½ç„¡æ³•這樣åšã€‚ å› æ¤ï¼Œè«‹æª¢æŸ¥æ‚¨çš„追隨者所屬的æœå‹™å™¨ã€‚ 您å¯ä»¥åœ¨è¨ç½®ä¸é¸æ“‡æ‰‹å‹•批准和拒絕新追隨者。<em>請記ä½ï¼Œæœå‹™å™¨å’Œä»»ä½•接收æœå‹™å™¨çš„æ“ä½œå“¡éƒ½å¯ä»¥æŸ¥çœ‹æ¤é¡žæ¶ˆæ¯</em>,並且收件人å¯ä»¥æˆªå±ï¼Œè¤‡è£½æˆ–以其他方å¼é‡æ–°åˆ†äº«ã€‚ <em>請勿在Mastodon上分享任何å±éšªä¿¡æ¯ã€‚</em> </li> + <li> <em> IP和其他元數據</em>:登錄時,我們會記錄您登錄時使用的IPä½å€ä»¥åŠç€è¦½å™¨æ‡‰ç”¨ç¨‹åºçš„å稱。 您å¯ä»¥åœ¨è¨ç½®ä¸æŸ¥çœ‹å’Œæ’¤æ¶ˆæ‰€æœ‰å·²ç™»éŒ„的作æ¥éšŽæ®µã€‚ 最新上傳的IPä½å€æœ€å¤šå¯ä»¥å„²å˜12個月。 我們還å¯èƒ½ä¿ç•™æœå‹™å™¨æ—¥èªŒï¼Œå…¶ä¸åŒ…æ‹¬å°æˆ‘們æœå‹™å™¨çš„æ¯å€‹è«‹æ±‚çš„IP地ä½ã€‚</li> + </ul> + + <hr class="spacer" /> + + <h3 id="use">您的資訊將會被用在甚麼用途?</h3> + + <p>我們從您那裡收集的任何資訊都å¯èƒ½é€šéŽä»¥ä¸‹æ–¹å¼ä½¿ç”¨ï¼š</p> + + <ul> + <li>æä¾›Mastodonçš„æ ¸å¿ƒåŠŸèƒ½ï¼šæ‚¨åªå¯ä»¥åœ¨ç™»éŒ„後與其他人的內容交æµä¸¦ç™¼ä½ˆè‡ªå·±çš„內容。例如,您å¯ä»¥è¿½éš¨å…¶ä»–人以在自己的個人化主é 䏿Ÿ¥çœ‹ä»–們的帖文。</li> + <li>社å€ç®¡ç†ï¼šä¾‹å¦‚將您的IPä½å€èˆ‡å…¶ä»–已知的IPä½å€é€²è¡Œæ¯”較來鑑定逃é¿å°éŽ–æˆ–å…¶ä»–ä¾µæ¬Šè¡Œç‚ºã€‚</li> + <li>您的電郵地å€ï¼šå¯èƒ½æœƒè¢«ç”¨æ–¼å‘您發é€ä¿¡æ¯ï¼Œæœ‰é—œå…¶ä»–äººèˆ‡æ‚¨äº’å‹•æˆ–å‘æ‚¨ç™¼é€æ¶ˆæ¯çš„通知,並用於ç”複查詢和/或其他請求或å•題。</li> + </ul> + + <hr class="spacer" /> + + <h3 id="protect">我們如何ä¿è·æ‚¨çš„資訊?</h3> + + <p>當您輸入,æäº¤æˆ–è¨ªå•æ‚¨çš„å€‹äººä¿¡æ¯æ™‚,我們會採å–å„種安全措施來ç¶è·æ‚¨çš„個人信æ¯çš„安全。 é™¤å…¶ä»–äº‹é …å¤–ï¼Œæ‚¨çš„ç€è¦½å™¨ä½œæ¥éšŽæ®µä»¥åŠæ‡‰ç”¨ç¨‹åºå’ŒAPI之間的æµé‡å‡ä½¿ç”¨SSL進行ä¿è·ã€‚您的密碼也會以強大的單å‘算法進行散列處ç†ã€‚ 您亦å¯ä»¥å•Ÿç”¨å¤šé‡é©—è‰ï¼Œä»¥é€²ä¸€æ¥å®‰å…¨åœ°è¨ªå•您的帳戶。</p> + + <hr class="spacer" /> + + <h3 id="data-retention">我們的數據ä¿ç•™æ”¿ç–</h3> + + <p>我們會致力:</p> + + <ul> + <li>ä¿ç•™åŒ…å«å°è©²æœå‹™å™¨æ‰€æœ‰è«‹æ±‚çš„IPä½å€çš„æœå‹™å™¨æ—¥èªŒï¼Œè€Œä¿ç•™æ™‚間將䏿œƒè¶…éŽ90天。</li> + <li>ä¿ç•™èˆ‡è¨»å†Šç”¨æˆ¶é—œè¯çš„IPä½å€ä¸è¶…éŽ12個月。</li> + </ul> + + <p>您å¯ä»¥è«‹æ±‚並下載您的內容備份,包括您的帖文,媒體附件,個人資料圖片和標題圖片。</p> + + <p>您亦å¯ä»¥éš¨æ™‚ä¸å¯é€†åœ°åˆªé™¤æ‚¨çš„帳戶。</p> + + <hr class="spacer"/> + + <h3 id="cookies">我們使用cookies嗎?</h3> + + <p>是。 Cookies是站點或其æœå‹™æä¾›å•†é€šéŽWebç€è¦½å™¨ï¼ˆå¦‚æžœå…è¨±ï¼‰å‚³è¼¸åˆ°è¨ˆç®—æ©Ÿç¡¬ç›¤çš„å°æ–‡ä»¶ã€‚ 這些cookiesä½¿ç«™é»žèƒ½å¤ è˜åˆ¥æ‚¨çš„ç€è¦½å™¨ï¼Œä¸¦ä¸”å¦‚æžœæ‚¨å·²ç¶“æ“æœ‰è¨»å†Šå¸³æˆ¶ï¼Œæœƒé€£çµè‡³æ‚¨çš„註冊帳戶。</p> + + <p>我們使用Cookie來了解並ä¿å˜æ‚¨çš„å好,以供將來訪å•。</p> + + <hr class="spacer" /> + + <h3 id="disclose">我們會å¦é€éœ²ä»»ä½•ä¿¡æ¯çµ¦ç¬¬ä¸‰æ–¹æ©Ÿæ§‹ï¼Ÿ</h3> + + <p>æˆ‘å€‘ä¸æœƒå°‡æ‚¨çš„個人身份信æ¯å‡ºå”®ï¼Œäº¤æ˜“或以其他方å¼è½‰è®“給第三方。 這ä¸åŒ…æ‹¬åŒæ„å°é€™äº›ä¿¡æ¯ä¿å¯†çš„é‹ç‡Ÿæ–¹ï¼Œå’Œæˆ‘們開展æ¥å‹™æˆ–為您æä¾›æœå‹™çš„å—ä¿¡ä»»çš„ç¬¬ä¸‰æ–¹ã€‚æˆ‘å€‘æˆ–æœƒåœ¨åŸºæ–¼å°æ³•律的尊é‡ï¼Œæˆ–åœ¨åŸ·è¡Œæˆ‘å€‘çš„ç¶²ç«™æ”¿ç–æˆ–ä¿è·æˆ‘們或其他人的權利ã€è²¡ç”¢æˆ–å®‰å…¨æ™‚é‡‹å‡ºä½ çš„å€‹äººè³‡æ–™ã€‚</p> + + <p>您的公開內容å¯èƒ½æœƒè¢«ç¶²çµ¡ä¸çš„å…¶ä»–æœå‹™å™¨ä¸‹è¼‰ã€‚ åªè¦é€™äº›è¿½éš¨è€…æˆ–æ”¶ä»¶äººä½æ–¼èˆ‡ä¹‹ä¸åŒçš„æœå‹™å™¨ä¸Šï¼Œæ‚¨çš„å…¬é–‹å¸–æ–‡å’Œè¿½éš¨è€…é™å®šå¸–文將傳éžåˆ°æ‚¨çš„追隨者所在的æœå‹™å™¨ï¼Œè€Œç§ä¿¡å°‡å‚³éžçµ¦æ”¶ä»¶äººçš„æœå‹™å™¨ã€‚</p> + + <p>當您授權應用程åºä½¿ç”¨æ‚¨çš„å¸³æˆ¶æ™‚ï¼Œæ ¹æ“šæ‚¨æ‰¹å‡†çš„æ¬Šé™ç¯„åœï¼Œå®ƒå¯èƒ½æœƒè¨ªå•æ‚¨çš„å…¬é–‹è³‡è¨Šï¼Œæ‚¨çš„é—œæ³¨åˆ—è¡¨ï¼Œæ‚¨çš„é—œæ³¨è€…ï¼Œæ‚¨çš„åˆ—è¡¨ï¼Œæ‰€æœ‰å¸–æ–‡ä»¥åŠæ‚¨çš„æ”¶è—夾。 æ‡‰ç”¨ç¨‹åºæ°¸é 無法å–得您的電åéƒµä»¶åœ°å€æˆ–密碼。</p> + + <hr class="spacer" /> + + <h3 id="children">兒童在網站的應用</h3> + + <p>å¦‚æžœæ¤æœå‹™å™¨ä½æ–¼æç›Ÿæˆ–EEAä¸ï¼šæˆ‘們的網站,產å“å’Œæœå‹™åªç‚º16æ²æˆ–以上的人æä¾›æœå‹™ã€‚ 如果您未滿16æ²ï¼Œè«‹æŒ‰ç…§GDPRçš„è¦æ±‚ (<a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">æç›Ÿä¸€èˆ¬è³‡æ–™ä¿è·è¦ç¯„</a>)ä¸ä½¿ç”¨æ¤ç¶²ç«™ã€‚</p> + + <p>å¦‚æžœæ¤æœå‹™å™¨ä½æ–¼ç¾Žåœ‹ï¼šæˆ‘們的網站,產å“å’Œæœå‹™åªç‚º13æ²æˆ–以上的人æä¾›æœå‹™ã€‚ 如果您未滿13æ²ï¼Œè«‹æŒ‰ç…§COPPAçš„è¦æ±‚ (<a href="https://en.wikipedia.org/wiki/Children%27s_Online_Privacy_Protection_Act">å…’ç«¥åœ¨ç·šéš±ç§æ¬Šä¿è·æ³•</a>)ä¸ä½¿ç”¨æ¤ç¶²ç«™ã€‚</p> + + <p>在其他管轄å€å…§ï¼Œæ³•å¾‹è¦æ±‚å¯èƒ½æœƒæœ‰æ‰€ä¸åŒã€‚</p> + + <hr class="spacer" /> + + <h3 id="changes">éš±ç§æ¬Šæ”¿ç–更改</h3> + + <p>è«‹æ ¹æ“šè‹±æ–‡ç‰ˆæœ¬æ‰€æº–ï¼Œæ¤ä¸æ–‡ç‰ˆæœ¬åªç‚ºè‹±æ–‡ç‰ˆéš±ç§æ”¿ç–的翻è¯ç‰ˆæœ¬</p> + + <p>æ¤æ–‡ä»¶ä»¥ CC-BY-SA 授權。英文版本的發佈日期為2018å¹´3月7日。æ¤ä¸æ–‡ç¿»è¯çš„ç¿»è¯æ—¥æœŸç‚º2020å¹´11月28日。</p> + + <p>æœ€åˆæ”¹ç·¨è‡ª <a href="https://github.com/discourse/discourse">Discourseçš„éš±ç§æ¬Šæ”¿ç–</a>.</p> title: "%{instance} ä½¿ç”¨æ¢æ¬¾å’Œéš±ç§æ¬Šæ”¿ç–" themes: contrast: é«˜å°æ¯” @@ -806,47 +1318,100 @@ zh-HK: time: formats: default: "%Yå¹´%-m月%dæ—¥ %H:%M" + month: "%b %Y" two_factor_authentication: - code_hint: è«‹è¼¸å…¥ä½ èªè‰å™¨ç”¢ç”Ÿçš„代碼,以確èªè¨å®š - description_html: ç•¶ä½ å•Ÿç”¨<strong>é›™é‡èªè‰</strong>å¾Œï¼Œä½ ç™»å…¥æ™‚å°‡éœ€è¦ä½¿ä½ æ‰‹æ©Ÿã€æˆ–其他種類èªè‰å™¨ç”¢ç”Ÿçš„代碼。 + add: 新增 disable: åœç”¨ - enable: 啟用 + disabled_success: å·²æˆåŠŸå•Ÿç”¨é›™é‡èªè‰ + edit: 編輯 enabled: é›™é‡èªè‰å·²å•Ÿç”¨ enabled_success: å·²æˆåŠŸå•Ÿç”¨é›™é‡èªè‰ generate_recovery_codes: 產生備用驗è‰ç¢¼ - instructions_html: "<strong>è«‹ç”¨ä½ æ‰‹æ©Ÿçš„èªè‰å™¨æ‡‰ç”¨ç¨‹å¼ï¼ˆå¦‚ Google Authenticatorã€Authy),掃æé€™è£çš„QR 圖形碼</strong>。在雙é‡èªè‰å•Ÿç”¨å¾Œï¼Œä½ ç™»å…¥æ™‚å°‡é ˆè¦ä½¿ç”¨æ¤æ‡‰ç”¨ç¨‹å¼ç”¢ç”Ÿçš„èªè‰ç¢¼ã€‚" lost_recovery_codes: è®“ä½ å¯ä»¥åœ¨éºå¤±é›»è©±æ™‚,使用備用驗è‰ç¢¼ç™»å…¥ã€‚å¦‚æžœä½ éºå¤±äº†å‚™ç”¨é©—è‰ç¢¼ï¼Œå¯ä»¥åœ¨é€™è£ç”¢ç”Ÿä¸€æ‰¹æ–°çš„,舊有的備用驗è‰ç¢¼å°‡æœƒå¤±æ•ˆã€‚ - manual_instructions: å¦‚æžœä½ ç„¡æ³•æŽƒæ QR 圖形碼,請手動輸入這個文å—密碼︰ + methods: é›™é‡èªè‰ + otp: 多é‡èªè‰è»Ÿä»¶ recovery_codes: 備份æ¢å¾©é©—è‰ç¢¼ recovery_codes_regenerated: æˆåŠŸç”¢ç”Ÿæ–°çš„å‚™ç”¨é©—è‰ç¢¼ recovery_instructions_html: å¦‚æžœä½ éºå¤±äº†å®‰è£èªè‰å™¨çš„è£ç½®ï¼ˆå¦‚ï¸°ä½ çš„é›»è©±ï¼‰ï¼Œä½ å¯ä»¥ä½¿ç”¨å‚™ç”¨é©—è‰ç¢¼é€²è¡Œç™»å…¥ã€‚請確ä¿å°‡å‚™ç”¨é©—è‰ç¢¼æ”¶è—穩當,(如列å°å‡ºä¾†ï¼Œå’Œä½ å…¶ä»–é‡è¦æ–‡ä»¶ä¸€èµ·å˜æ”¾ï¼‰ã€‚ - setup: è¨å®š - wrong_code: ä½ è¼¸å…¥çš„èªè‰ç¢¼ä¸¦ä¸æ£ç¢ºï¼å¯èƒ½ä¼ºæœå™¨æ™‚é–“å’Œä½ æ‰‹æ©Ÿä¸ä¸€è‡´ï¼Œè«‹æª¢æŸ¥ä½ 手機的時é˜ï¼Œæˆ–與本站管ç†å“¡è¯çµ¡ã€‚ + webauthn: 安全密鑰 user_mailer: backup_ready: explanation: ä½ è¦æ±‚çš„ Mastodon 帳號完整備份檔案ç¾å·²å°±ç·’,å¯ä¾›ä¸‹è¼‰ã€‚ subject: ä½ çš„å‚™ä»½æª”å·²å¯ä¾›ä¸‹è¼‰ title: 檔案匯出 + sign_in_token: + details: 這是嘗試的詳細資訊 + explanation: æˆ‘å€‘ç™¼ç¾æœ‰äººå˜—試以未使用éŽçš„ IP ä½å€ç™»å…¥åˆ°ä½ 的帳號。 å¦‚æžœé€™å€‹ç™»å…¥çš„äººæ˜¯ä½ ï¼Œè«‹åœ¨ã€Œç™»å…¥è«‹æ±‚ã€é é¢ä¸Šè¼¸å…¥ä»¥ä¸‹å®‰å…¨ä»£ç¢¼ï¼š + further_actions: å¦‚æžœé€™ä¸æ˜¯ä½ ï¼Œè«‹åˆ°é€™è£æ›´æ”¹ä½ 的密碼,並啟用雙é‡èªè‰ï¼š + subject: 請確èªç™»å…¥è«‹æ±‚ + title: 登入請求 + warning: + explanation: + disable: ä½ ä¸èƒ½ä»¥ä»»ä½•æ–¹å¼ç™»å…¥æˆ–ä½¿ç”¨ä½ çš„å¸³è™Ÿï¼Œä½†ä½ çš„å€‹äººè³‡æ–™é é¢å’Œå…¶ä»–資料ä»ä¿æŒå®Œæ•´ã€‚ + sensitive: ä½ ä¸Šè¼‰çš„åª’é«”æª”æ¡ˆå’Œé€£çµåª’é«”å°‡è¢«æ¨™è¨˜ç‚ºæ•æ„Ÿé …目。 + silence: ä½ ä»ç„¶å¯ä»¥ä½¿ç”¨ä½ çš„å¸³è™Ÿï¼Œä½†åªæœ‰ä½ ç¾æ™‚çš„è¿½éš¨è€…æœƒçœ‹è¦‹ä½ åœ¨æ¤ä¼ºæœå™¨çš„å˜Ÿæ–‡ã€‚ä½ æˆ–å¾žå…¬é–‹å冊ä¸è¢«å‰”除。但是其他人ä»ç„¶å¯ä»¥ä¸»å‹•é—œæ³¨ä½ ã€‚ + suspend: ä½ å°‡ä¸èƒ½ä½¿ç”¨æ‚¨çš„å¸³è™Ÿï¼Œä½ çš„å€‹äººè³‡æ–™é é¢åŠå…¶ä»–資料將ä¸èƒ½å†è¢«å–å¾—ã€‚ä½ ä»å¯åœ¨è³‡æ–™è¢«å®Œå…¨åˆªé™¤å‰è«‹æ±‚ä¸‹è¼‰ä½ çš„æ•¸æ“šï¼Œä½†æˆ‘å€‘ä»æœƒä¿ç•™ä¸€éƒ¨ä»½è³‡æ–™ï¼Œä»¥é˜²æ¢æœ‰äººè¦é¿åœæ¬Šè™•罰。 + get_in_touch: ä½ å¯ä»¥å›žè¦†æ¤é›»éƒµä¾†è·Ÿæˆ‘們(%{instance})è¯çµ¡ + review_server_policies: 審視伺æœå™¨æ”¿ç– + statuses: 特別是: + subject: + disable: ä½ çš„å¸³è™Ÿ %{acct} å·²ç¶“è¢«æ¶·çµ + none: è¦å‘Šå¸³è™Ÿ%{acct} + sensitive: ä½ çš„å¸³è™Ÿ %{acct} çš„åª’é«”å·²è¢«æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹ + silence: ä½ çš„å¸³è™Ÿ %{acct} 已經被é™åˆ¶ + suspend: ä½ çš„å¸³è™Ÿ %{acct} å·²ç¶“è¢«åœæ¬Š + title: + disable: å¸³è™Ÿæ¶·çµ + none: è¦å‘Š + sensitive: ä½ çš„åª’é«”å·²è¢«æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹ + silence: 賬戶已被é™åˆ¶ + suspend: 帳號已åœç”¨ welcome: edit_profile_action: è¨å®šå€‹äººè³‡æ–™ edit_profile_step: ä½ å¯ä»¥è¨å®šä½ 的個人資料,包括上傳é åƒã€æ©«å¹…åœ–ç‰‡ã€æ›´æ”¹é¡¯ç¤ºå稱ç‰ç‰ã€‚å¦‚æžœä½ æƒ³åœ¨æ–°çš„é—œæ³¨è€…é—œæ³¨ä½ ä¹‹å‰å°ä»–å€‘é€²è¡Œå¯©æ ¸ï¼Œä½ ä¹Ÿå¯ä»¥é¸æ“‡ç‚ºä½ 的帳戶è¨ç‚ºã€Œç§äººã€ã€‚ explanation: 䏋颿˜¯å¹¾å€‹å°è²¼å£«ï¼Œå¸Œæœ›å®ƒå€‘èƒ½å¹«åˆ°ä½ final_action: 開始發文 final_step: '開始發文å§ï¼å³ä½¿ä½ ç¾åœ¨æ²’有關注者,其他人ä»ç„¶èƒ½åœ¨æœ¬ç«™æ™‚間軸或者話題標籤ç‰åœ°æ–¹çœ‹åˆ°ä½ çš„å…¬é–‹æ–‡ç« ã€‚è©¦è‘—ç”¨ #introductions 這個話題標籤介紹一下自己å§ã€‚' - full_handle: ä½ çš„å®Œæ•´ç”¨æˆ¶åœ°å€ - full_handle_hint: ä½ éœ€è¦æŠŠé€™å€‹å‘Šè¨´ä½ çš„æœ‹å‹å€‘,這樣他們就能從å¦ä¸€å€‹å¯¦ä¾‹å‘ä½ ç™¼é€ä¿¡æ¯æˆ–è€…é—œæ³¨ä½ ã€‚ - review_preferences_action: 更改首é¸é … - review_preferences_step: è¨˜å¾—èª¿æ•´ä½ çš„å好è¨ç½®ï¼Œæ¯”å¦‚ä½ æƒ³æŽ¥æ”¶ä»€éº¼é¡žåž‹çš„éƒµä»¶ï¼Œæˆ–è€…ä½ æƒ³æŠŠä½ çš„æ–‡ç« å¯è¦‹ç¯„åœé»˜èªè¨å®šç‚ºä»€éº¼ç´šåˆ¥ã€‚å¦‚æžœä½ æ²’æœ‰æšˆè»Šçš„è©±ï¼Œè€ƒæ…®ä¸€ä¸‹å•Ÿç”¨ã€Œè‡ªå‹•æ’æ”¾ GIF å‹•ç•«ã€é€™å€‹é¸é …å§ã€‚ - subject: æ¡è¿Žä¾†åˆ° Mastodon - tip_federated_timeline: 跨站公共時間軸å¯ä»¥è®“ä½ ä¸€çªºæ›´å»£é—Šçš„ Mastodon 網絡。ä¸éŽï¼Œç”±æ–¼å®ƒåªé¡¯ç¤ºä½ çš„é„°å±…å€‘æ‰€è¨‚é–±çš„å…§å®¹ï¼Œæ‰€ä»¥ä¸¦ä¸æ˜¯å…¨éƒ¨ã€‚ - tip_following: é»˜èªæƒ…æ³ä¸‹ï¼Œä½ æœƒè‡ªå‹•é—œæ³¨ä½ æ‰€åœ¨æœå‹™ç«™çš„管ç†å“¡ã€‚想çµäº¤æ›´å¤šæœ‰è¶£çš„人的話,記得多逛逛本站時間軸和跨站公共時間軸哦。 - tip_local_timeline: 本站時間軸å¯ä»¥è®“ä½ ä¸€çªº %{instance} ä¸Šçš„ç”¨æˆ¶ã€‚ä»–å€‘å°±æ˜¯é›¢ä½ æœ€è¿‘çš„é„°å±…ï¼ - tip_mobile_webapp: å¦‚æžœä½ çš„ç§»å‹•è¨å‚™ç€è¦½å™¨å…è¨±ä½ å°‡ Mastodon æ·»åŠ åˆ°ä¸»å±å¹•ï¼Œä½ å°±èƒ½å¤ æŽ¥æ”¶æŽ¨é€æ¶ˆæ¯ã€‚å®ƒå°±åƒæœ¬åœ°æ‡‰ç”¨ä¸€æ¨£å¥½ä½¿ï¼ + full_handle: ä½ çš„å®Œæ•´ Mastodon åœ°å€ + full_handle_hint: 這訊æ¯å°‡é¡¯ç¤ºçµ¦ä½ 朋å‹å€‘,讓他們能從å¦ä¸€å€‹æœå‹™ç«™ç™¼ä¿¡æ¯çµ¦ä½ ï¼Œæˆ–è€…é—œæ³¨ä½ çš„ã€‚ + review_preferences_action: 更改å好è¨å®š + review_preferences_step: è¨˜å¾—èª¿æ•´ä½ çš„å好è¨å®šï¼Œæ¯”å¦‚ä½ æƒ³æŽ¥æ”¶ä»€éº¼é¡žåž‹çš„éƒµä»¶ï¼Œæˆ–è€…ä½ æƒ³æŠŠä½ çš„æ–‡ç« å¯è¦‹ç¯„åœé»˜èªè¨å®šç‚ºä»€éº¼ç´šåˆ¥ã€‚å¦‚æžœä½ æ²’æœ‰æšˆè»Šçš„è©±ï¼Œè€ƒæ…®ä¸€ä¸‹å•Ÿç”¨ã€Œè‡ªå‹•æ’æ”¾ GIF å‹•ç•«ã€é€™å€‹é¸é …å§ã€‚ + subject: æ¡è¿Žä¾†åˆ° Mastodon (è¬è±¡) + tip_federated_timeline: 跨站時間軸å¯ä»¥è®“ä½ ä¸€çªºæ›´å»£é—Šçš„ Mastodon 網絡。ä¸éŽï¼Œç”±æ–¼å®ƒåªé¡¯ç¤ºä½ çš„é„°å±…å€‘æ‰€è¨‚é–±çš„å…§å®¹ï¼Œæ‰€ä»¥ä¸¦ä¸æ˜¯å…¨éƒ¨ã€‚ + tip_following: ä½ æœƒé è¨é—œæ³¨ä½ æœå‹™ç«™çš„管ç†å“¡ã€‚想çµäº¤æ›´å¤šæœ‰è¶£çš„人的話,記得多逛逛本站時間軸和跨站時間軸哦。 + tip_local_timeline: 本站時間軸å¯ä»¥è®“ä½ ä¸€çªº %{instance} æœ¬ç«™ä¸Šçš„ç”¨æˆ¶ã€‚ä»–å€‘å°±æ˜¯é›¢ä½ æœ€è¿‘çš„é„°å±…ï¼ + tip_mobile_webapp: å¦‚æžœä½ çš„ç§»å‹•è¨å‚™ç€è¦½å™¨æ”¯æ´ï¼Œä½ å¯ä»¥å°‡ Mastodon åŠ åˆ°è£ç½®çš„主畫é¢ï¼Œè®“ä½ å¯ä»¥é¸æ“‡æŽ¥æ”¶æŽ¨é€é€šçŸ¥ï¼Œå°±åƒæœ¬æ©Ÿçš„ App ä¸€æ¨£æ–¹ä¾¿ï¼ tips: å°è²¼å£« - title: "%{name},æ¡è¿Žä½ çš„åŠ å…¥ï¼" + title: æ¡è¿Ž %{name} åŠ å…¥ï¼ users: + blocked_email_provider: æ¤é›»éƒµæä¾›å•†ä¸¦ä¸è¢«å…許 + follow_limit_reached: ä½ ä¸èƒ½é—œæ³¨å¤šæ–¼%{limit} 人 + generic_access_help_html: ä¸èƒ½ç™»å…¥ï¼Ÿä½ å¯ä»¥å¯„電郵至 %{email} 尋求å”助 invalid_email: é›»éƒµåœ°å€æ ¼å¼ä¸æ£ç¢º - invalid_otp_token: é›™é‡èªè‰ç¢ºèªç¢¼ä¸æ£ç¢º - otp_lost_help_html: å¦‚æžœä½ ç„¡æ³•è¨ªå•這兩者,å¯ä»¥é€šéŽ %{email} 與我們è¯ç¹« - seamless_external_login: ç”±æ–¼ä½ æ˜¯å¾žå¤–éƒ¨ç³»çµ±ç™»å…¥ï¼Œæ‰€ä»¥ä¸èƒ½è¨å®šå¯†ç¢¼å’Œé›»éƒµã€‚ + invalid_email_mx: æ¤é›»éƒµåœ°å€ä¸å˜åœ¨ + invalid_otp_token: é›™é‡èªè‰ç¢¼ä¸æ£ç¢º + invalid_sign_in_token: 無效的安全碼 + otp_lost_help_html: å¦‚æžœé€™å…©è€…ä½ å‡ç„¡æ³•ç™»å…¥ï¼Œä½ å¯ä»¥è¯ç¹« %{email} + seamless_external_login: å› ç‚ºä½ æ£åœ¨ä½¿ç”¨ç¬¬ä¸‰æ–¹æœå‹™ç™»å…¥ï¼Œæ‰€ä»¥ä¸èƒ½è¨å®šå¯†ç¢¼å’Œé›»éƒµã€‚ signed_in_as: ç›®å‰ç™»å…¥çš„帳戶: + suspicious_sign_in_confirmation: ä½ ä¼¼ä¹Žæœªæ›¾å¾žæ¤è¨å‚™ç™»å…¥ï¼Œè€Œä½ åˆæœ‰ä¸€æ®µæ™‚間沒有登入了。我們剛剛把安全碼傳é€åˆ°ä½ 的電郵地å€ï¼Œè«‹æŸ¥çœ‹ä½ 的電郵信箱,以確èªä½ æ˜¯å¸³è™Ÿæ“æœ‰è€…本人。 + verification: + explanation_html: ä½ å¯ä»¥<strong>èªè‰å€‹äººè³‡æ–™é é¢çš„元數據 (Metadata) é€£çµæ˜¯å±¬æ–¼ä½ çš„</strong>。è¦èªè‰ï¼Œé‚£äº›é€£çµçš„ç›®çš„åœ°ç¶²ç«™å¿…é ˆæœ‰ä¸€æ¢å›žåˆ°ä½ Mastodon 個人é é¢çš„連çµï¼Œè€Œä¸”連çµ<strong>å¿…é ˆ</strong>具有<code>rel="me"</code>屬性。連çµçš„æ–‡å—å…§å®¹éƒ½ä¸æœƒå½±éŸ¿èªè‰ã€‚é€™è£æœ‰ä¸€å€‹ä¾‹å: + verification: é©—è‰ + webauthn_credentials: + add: 新增安全密鑰è£ç½® + create: + error: 新增安全密鑰è£ç½®æ™‚出ç¾äº†å•é¡Œã€‚è«‹é‡æ–°å†è©¦ä¸€æ¬¡ã€‚ + success: ä½ å·²æˆåŠŸå°‡å®‰å…¨å¯†é‘°è£ç½®åŠ å…¥å¸³è™Ÿã€‚ + delete: 刪除 + delete_confirmation: ä½ ç¢ºå®šè¦åˆªé™¤é€™å€‹å®‰å…¨å¯†é‘°è£ç½®å—Žï¼Ÿ + description_html: å¦‚æžœä½ å•Ÿç”¨<strong>安全密鑰驗è‰</strong>çš„è©±ï¼Œç™»å…¥æ™‚ä½ å°‡éœ€è¦ä½¿ç”¨å…¶ä¸ä¸€å€‹å®‰å…¨å¯†é‘°ã€‚ + destroy: + error: 刪除安全密鑰è£ç½®æ™‚出ç¾äº†å•é¡Œã€‚è«‹é‡æ–°å†è©¦ä¸€æ¬¡ã€‚ + success: ä½ å·²æˆåŠŸå°‡å®‰å…¨å¯†é‘°è£ç½®å¾žå¸³è™Ÿç§»é™¤ã€‚ + invalid_credential: 無效的安全密鑰è£ç½® + nickname_hint: è«‹ç‚ºä½ çš„å®‰å…¨å¯†é‘°è£ç½®å‘½å + not_enabled: ä½ é‚„æœªå•Ÿç”¨ WebAuthn + not_supported: 這個ç€è¦½å™¨ä¸¦ä¸æ”¯æ´å®‰å…¨å¯†é‘°è£ç½® + otp_required: 請開啟雙é‡èªè‰ä»¥ä½¿ç”¨å®‰å…¨å¯†é‘°è£ç½® + registered_on: 在 %{date} 注冊 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 96dd012259a091950a3249caa10e0afe6c8b431d..da340a1bc3349836d44a5dbc75f9a310b36c5656 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -21,6 +21,9 @@ zh-TW: federation_hint_html: ä½ åªéœ€è¦æ“有 %{instance} 的帳戶,就å¯ä»¥è¿½è¹¤éš¨ä¾¿ä¸€å° Mastodon 伺æœå™¨ä¸Šçš„人ç‰ç‰ã€‚ get_apps: å˜—è©¦è¡Œå‹•æ‡‰ç”¨ç¨‹å¼ hosted_on: 在 %{domain} é‹ä½œçš„ Mastodon 站點 + instance_actor_flash: '這個帳戶是個用來代表伺æœå™¨è‡ªå·²çš„è™›æ“¬è§’è‰²ï¼Œè€Œä¸æ˜¯å¯¦éš›çš„使用者。它是用來è¯ç›Ÿç”¨çš„ï¼Œé™¤éžæ‚¨æƒ³è¦å°éŽ–æ•´å€‹ç«™å°ï¼Œä¸ç„¶ä¸è©²å°éŽ–å®ƒã€‚ä½†è¦å°éŽ–æ•´å€‹ç«™å°ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨ç¶²åŸŸå°éŽ–åŠŸèƒ½ã€‚ + +' learn_more: 了解詳細 privacy_policy: éš±ç§æ¬Šæ”¿ç– see_whats_happening: 看看發生什麼事 @@ -37,18 +40,24 @@ zh-TW: reason: åŽŸå› rejecting_media: 䏿œƒè™•ç†æˆ–儲å˜é€™äº›ä¼ºæœå™¨çš„åª’é«”æª”æ¡ˆï¼Œä¹Ÿä¸æœƒé¡¯ç¤ºç¸®åœ–ï¼Œéœ€è¦æ‰‹å‹•點é¸åŽŸå§‹æª”ï¼š rejecting_media_title: éŽæ¿¾çš„媒體 + silenced: 這些伺æœå™¨çš„嘟文會被從公開時間軸與å°è©±ä¸éš±è—ï¼Œè€Œä¸”èˆ‡å®ƒå€‘çš„ä½¿ç”¨è€…äº’å‹•ä¸¦ä¸æœƒç”¢ç”Ÿä»»ä½•é€šçŸ¥ï¼Œé™¤éžæ‚¨è¿½è¹¤ä»–們: silenced_title: éœéŸ³çš„伺æœå™¨ + suspended: 來自這些伺æœå™¨çš„è³‡æ–™éƒ½ä¸æœƒè¢«è™•ç†ã€å„²å˜æˆ–交æ›ï¼Œä¹Ÿç„¡æ³•和這些伺æœå™¨ä¸Šçš„使用者互動與æºé€šï¼š suspended_title: æš«åœçš„伺æœå™¨ + unavailable_content_html: Mastodon 一般來說å…許您閱讀並和任何è¯ç›Ÿä¼ºæœå™¨ä¸Šçš„使用者互動。這些伺æœå™¨æ˜¯é€™å€‹ç«™å°è¨ä¸‹çš„例外。 user_count_after: other: ä½ä½¿ç”¨è€… user_count_before: 註冊使用者數 what_is_mastodon: 什麼是 Mastodon? accounts: choices_html: "%{name} çš„é¸æ“‡ï¼š" + endorsements_hint: 推薦您已經關注的人,把他們釘在您的個人é é¢ã€‚ + featured_tags_hint: 您å¯ä»¥æŽ¨è–¦ä¸åŒä¸»é¡Œæ¨™ç±¤ï¼Œå®ƒå€‘也會在æ¤è™•出ç¾ã€‚ follow: 關注 followers: other: 關注者 following: æ£åœ¨é—œæ³¨ + instance_actor_flash: 這個帳號是一個用來代表æ¤ä¼ºæœå™¨çš„虛擬執行者,而éžçœŸå¯¦ä½¿ç”¨è€…。它用途為站點è¯ç›Ÿä¸”䏿‡‰è¢«åœæ¬Šã€‚ joined: åŠ å…¥æ–¼ %{date} last_active: ä¸Šæ¬¡æ´»èºæ™‚é–“ link_verified_on: æ¤é€£çµçš„æ‰€æœ‰æ¬Šå·²åœ¨ %{date} æª¢æŸ¥éŽ @@ -59,6 +68,8 @@ zh-TW: nothing_here: 暫時沒有內容å¯ä¾›é¡¯ç¤º! people_followed_by: "%{name} 關注的人" people_who_follow: 關注 %{name} 的人 + pin_errors: + following: ä½ åªèƒ½æŽ¨è–¦ä½ æ£åœ¨é—œæ³¨çš„使用者。 posts: other: 嘟文 posts_tab_heading: 嘟文 @@ -84,6 +95,7 @@ zh-TW: add_email_domain_block: 將電åéƒµä»¶ç¶²åŸŸåŠ å…¥é»‘åå–® approve: æ ¸å‡† approve_all: 全部批准 + approved_msg: æˆåŠŸå¯©æ ¸äº†%{username} 的新帳戶申請 are_you_sure: 您確定嗎? avatar: é åƒ by_domain: 站點 @@ -97,8 +109,10 @@ zh-TW: confirm: 確定 confirmed: 已確定 confirming: 確定 + delete: 刪除資料 deleted: 已刪除 demote: é™ç´š + destroyed_msg: å³å°‡åˆªé™¤ %{username} 的數據 disable: åœç”¨ disable_two_factor_authentication: åœç”¨å…©éšŽæ®µèªè‰ disabled: å·²åœç”¨ @@ -109,10 +123,12 @@ zh-TW: email_status: é›»å信箱狀態 enable: 啟用 enabled: 已啟用 + enabled_msg: æˆåŠŸè§£é™¤ %{username} 帳戶的å‡çµ followers: 關注者 follows: æ£åœ¨é—œæ³¨ header: é–‹é inbox_url: æ”¶ä»¶ç®± (Inbox) URL + invite_request_text: åŠ å…¥åŽŸå› invited_by: 邀請者 ip: IP ä½å€ joined: å·²åŠ å…¥ @@ -124,6 +140,8 @@ zh-TW: login_status: 登入狀態 media_attachments: 多媒體附件 memorialize: è¨å®šç‚ºè¿½æ‚¼å¸³æˆ¶ + memorialized: 被悼念的 + memorialized_msg: æˆåŠŸå°‡%{username} 的帳號變為紀念帳號 moderation: active: æ´»èº all: 全部 @@ -144,10 +162,14 @@ zh-TW: public: 公開 push_subscription_expires: PuSH è¨‚é–±éŽæœŸ redownload: 釿–°æ•´ç†å€‹äººè³‡æ–™ + redownloaded_msg: æˆåŠŸé‡æ–°è¼‰å…¥%{username} 的個人資料é é¢ reject: 拒絕 reject_all: 全部拒絕 + rejected_msg: æˆåŠŸæ‹’çµ•äº†%{username} 的新帳號申請 remove_avatar: å–æ¶ˆé åƒ remove_header: 移除開é + removed_avatar_msg: æˆåŠŸåˆªé™¤äº† %{username} çš„é åƒ + removed_header_msg: æˆåŠŸåˆªé™¤äº† %{username} çš„é é¢é ‚端 resend_confirmation: already_confirmed: æ¤ä½¿ç”¨è€…å·²è¢«ç¢ºèª send: 釿–°ç™¼é€é©—è‰ä¿¡ @@ -164,6 +186,8 @@ zh-TW: search: æœå°‹ search_same_email_domain: 其他有åŒå€‹é›»å郵件網域的使用者 search_same_ip: 其他有åŒå€‹ IP 的使用者 + sensitive: æ•æ„Ÿå†…容 + sensitized: å·²æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹ shared_inbox_url: å…±äº«æ”¶ä»¶ç®±ç¶²å€ show: created_reports: 建立檢舉 @@ -173,13 +197,19 @@ zh-TW: statuses: 嘟文 subscribe: 訂閱 suspended: å·²åœæ¬Š + suspension_irreversible: 已永久刪除這個帳戶的數據。雖然這個帳戶的數據已被永久刪除,但是您ä»ç„¶å¯ä»¥å–消暫åœé€™å€‹å¸³æˆ¶ã€‚ + suspension_reversible_hint_html: 這個帳戶已被暫åœï¼Œæ‰€æœ‰æ•¸æ“šå°‡æœƒåœ¨ %{date} 被刪除。在æ¤ä¹‹å‰ï¼Œæ‚¨å¯ä»¥å®Œå…¨å›žå¾©æ‚¨çš„å¸³æˆ¶ã€‚å¦‚æžœæ‚¨æƒ³å³æ™‚刪除這個帳戶的數據,您å¯ä»¥åœ¨ä¸‹é¢é€²è¡Œæ“作。 time_in_queue: æ£åœ¨ä½‡åˆ—ç‰å¾… %{time} title: 帳戶 unconfirmed_email: 未確èªçš„é›»åä¿¡ç®±ä½å€ + undo_sensitized: å–æ¶ˆæ•感狀態 undo_silenced: å–æ¶ˆéœéŸ³ undo_suspension: å–æ¶ˆåœæ¬Š + unsilenced_msg: æˆåŠŸè§£é™¤ %{username} 的帳戶é™åˆ¶ unsubscribe: å–æ¶ˆè¨‚é–± + unsuspended_msg: æˆåŠŸå–æ¶ˆæš«åœ %{username} 的帳戶 username: 使用者å稱 + view_domain: æŸ¥çœ‹ç«™å°æ¦‚è¦ warn: è¦å‘Š web: é é¢ whitelisted: å·²åŠ å…¥ç™½åå–® @@ -193,6 +223,38 @@ zh-TW: create_custom_emoji: å»ºç«‹è‡ªè¨‚é¡æ–‡å— create_domain_allow: 建立å…許網域 create_domain_block: 建立阻擋網域 + create_email_domain_block: å°éŽ–é›»åéƒµä»¶ç«™å° + create_ip_block: 新增IPè¦å‰‡ + demote_user: 把用戶é™ç´š + destroy_announcement: 刪除公告 + destroy_custom_emoji: åˆªé™¤è‡ªè¨‚é¡æ–‡å— + destroy_domain_allow: 刪除å…許網域 + destroy_domain_block: 刪除阻擋網域 + destroy_email_domain_block: 刪除阻擋電郵網域 + destroy_ip_block: 刪除 IP è¦å‰‡ + destroy_status: 刪除狀態 + disable_2fa_user: åœç”¨å…©éšŽæ®µèªè‰ + disable_custom_emoji: åœç”¨è‡ªè¨‚顿–‡å— + disable_user: åœç”¨å¸³æˆ¶ + enable_custom_emoji: å•“ç”¨è‡ªè¨‚é¡æ–‡å— + enable_user: 啓用帳戶 + memorialize_account: è¨å®šæˆç´€å¿µå¸³è™Ÿ + promote_user: 把用戶å‡ç´š + remove_avatar_user: 刪除大é è²¼ + reopen_report: é‡é–‹èˆ‰å ± + reset_password_user: é‡è¨å¯†ç¢¼ + resolve_report: æ¶ˆé™¤èˆ‰å ± + sensitive_account: æŠŠæ‚¨çš„å¸³è™Ÿçš„åª’é«”æ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹ + silence_account: éœéŸ³ç”¨æˆ¶ + suspend_account: æš«åœç”¨æˆ¶ + unassigned_report: å–æ¶ˆæŒ‡æ´¾èˆ‰å ± + unsensitive_account: å–æ¶ˆæŠŠæ‚¨çš„帳號的媒體è¨å®šç‚ºæ•感內容 + unsilence_account: å–æ¶ˆç”¨æˆ¶çš„éœéŸ³ç‹€æ…‹ + unsuspend_account: å–æ¶ˆç”¨æˆ¶çš„æš«åœç‹€æ…‹ + update_announcement: 更新公告 + update_custom_emoji: æ›´æ–°è‡ªè¨‚é¡æ–‡å— + update_domain_block: æ›´æ–°å°éŽ–ç¶²åŸŸ + update_status: 更新狀態 actions: assigned_to_self_report: "%{name} 接å—了檢舉 %{target}" change_email_user: "%{name} 變更了使用者 %{target} 的電åä¿¡ç®±ä½å€" @@ -203,12 +265,14 @@ zh-TW: create_domain_allow: "%{name} å°‡ %{target} ç¶²åŸŸåŠ å…¥é»‘å單了" create_domain_block: "%{name} å°éŽ–äº†ç«™é»ž %{target}" create_email_domain_block: "%{name} å°éŽ–äº†é›»å信箱網域 %{target}" + create_ip_block: "%{name} 已經è¨å®šäº†IP %{target} çš„è¦å‰‡" demote_user: "%{name} 把使用者 %{target} é™ç´š" destroy_announcement: "%{name} 刪除了公告 %{target}" destroy_custom_emoji: "%{name} ç ´å£žäº† %{target} 表情符號" destroy_domain_allow: "%{name} 從白åå–®ä¸ç§»é™¤äº† %{target} 網域" destroy_domain_block: "%{name} å–æ¶ˆäº†å°ç«™é»ž %{target} çš„å°éŽ–" destroy_email_domain_block: "%{name} å–æ¶ˆäº†å°é›»å信箱網域 %{target} çš„å°éŽ–" + destroy_ip_block: "%{name} 已經刪除了 IP %{target} çš„è¦å‰‡" destroy_status: "%{name} 刪除了 %{target} 的嘟文" disable_2fa_user: "%{name} åœç”¨äº†ä½¿ç”¨è€… %{target} 的兩階段èªè‰" disable_custom_emoji: "%{name} åœç”¨äº†è‡ªè¨‚表情符號 %{target}" @@ -221,15 +285,21 @@ zh-TW: reopen_report: "%{name} 釿–°é–‹å•Ÿ %{target} 的檢舉" reset_password_user: "%{name} 釿–°è¨å®šäº†ä½¿ç”¨è€… %{target} 的密碼" resolve_report: "%{name} 處ç†äº† %{target} 的檢舉" + sensitive_account: "%{name} å°‡ %{target} çš„åª’é«”æª”æ¡ˆæ¨™è¨˜ç‚ºæ•æ„Ÿå…§å®¹" silence_account: "%{name} éœéŸ³äº†ä½¿ç”¨è€… %{target}" suspend_account: "%{name} åœæ¬Šäº†ä½¿ç”¨è€… %{target}" unassigned_report: "%{name} å–æ¶ˆæŒ‡æ´¾ %{target} 的檢舉" + unsensitive_account: "%{name} å°‡ %{target} çš„åª’é«”æª”æ¡ˆçš„æ•æ„Ÿç‹€æ…‹å–消" unsilence_account: "%{name} å–æ¶ˆäº†ä½¿ç”¨è€… %{target} çš„éœéŸ³ç‹€æ…‹" unsuspend_account: "%{name} å–æ¶ˆäº†ä½¿ç”¨è€… %{target} çš„åœæ¬Šç‹€æ…‹" update_announcement: "%{name} 更新了公告 %{target}" update_custom_emoji: "%{name} 更新了自訂表情符號 %{target}" + update_domain_block: "%{name} æ›´æ–°å°éŽ–ç¶²åŸŸ %{target}" update_status: "%{name} 釿•´äº† %{target} 的嘟文" deleted_status: "(已刪除嘟文)" + empty: 找ä¸åˆ° log + filter_by_action: æŒ‰å‹•ä½œç¯©é¸ + filter_by_user: æŒ‰ä½¿ç”¨è€…ç¯©é¸ title: ç‡Ÿé‹æ—¥èªŒ announcements: destroyed_msg: æˆåŠŸåˆªé™¤å…¬å‘Šï¼ @@ -268,11 +338,13 @@ zh-TW: listed: 已顯示 new: title: åŠ å…¥æ–°çš„è‡ªè¨‚è¡¨æƒ…ç¬¦è™Ÿ + not_permitted: æ‚¨ç„¡æ¬ŠåŸ·è¡Œæ¤æ“作 overwrite: 覆蓋 shortcode: çŸä»£ç¢¼ shortcode_hint: 至少 2 個å—元,åªèƒ½ä½¿ç”¨å—æ¯ã€æ•¸å—和下劃線 title: 自訂表情符號 uncategorized: 未分類 + unlist: ä¸å…¬é–‹ unlisted: å·²éš±è— update_failed_msg: 無法更新表情符號 updated_msg: 已更新表情符號! @@ -315,6 +387,8 @@ zh-TW: created_msg: æ£åœ¨é€²è¡Œç«™é»žå°éŽ– destroyed_msg: 已撤銷站點å°éŽ– domain: 站點 + edit: 更改å°éŽ–çš„ç«™å° + existing_domain_block_html: æ‚¨å·²ç¶“å° %{name} æ–½åŠ äº†æ›´åš´æ ¼çš„é™åˆ¶ï¼Œæ‚¨éœ€è¦å…ˆæŠŠä»–<a href="%{unblock_url}">å–æ¶ˆå°éŽ–</a>。 new: create: 新增å°éŽ– hint: 站點å°éŽ–å‹•ä½œä¸¦ä¸æœƒé˜»æ¢å¸³æˆ¶ç´€éŒ„被新增至資料庫,但會自動回溯性地å°é‚£äº›å¸³æˆ¶å¥—用特定管ç†è¨å®šã€‚ @@ -324,6 +398,12 @@ zh-TW: silence: éœéŸ³ suspend: åœæ¬Š title: 新增å°éŽ–ç«™é»ž + obfuscate: 混淆網域å稱 + obfuscate_hint: 若啟用網域廣告列表é™åˆ¶ï¼Œæ–¼åˆ—表部份混淆網域å稱 + private_comment: ç§äººç•™è¨€ + private_comment_hint: è«‹æä¾›æ›´å¤šæœ‰é—œæ¤ç«™å°é™åˆ¶çš„資訊以供版主作內部åƒè€ƒã€‚ + public_comment: 公開留言 + public_comment_hint: å¦‚æžœä½ å·²ç¶“å•Ÿç”¨ç«™å°é™åˆ¶åˆ—表的公告,請為一般大眾æä¾›æ›´å¤šæœ‰é—œæ¤ç«™å°é™åˆ¶çš„資訊。 reject_media: 拒絕媒體檔案 reject_media_hint: 刪除本地快å–的媒體檔案,並且ä¸å†æŽ¥æ”¶ä¾†è‡ªè©²ç«™é»žçš„ä»»ä½•åª’é«”æª”æ¡ˆã€‚èˆ‡åœæ¬Šç„¡é—œ reject_reports: 拒絕檢舉 @@ -342,44 +422,99 @@ zh-TW: title: 撤銷 %{domain} 的站點å°éŽ– undo: 撤銷 undo: 復原欲å°éŽ–åŸŸå + view: 顯示阻擋的網域 email_domain_blocks: add_new: åŠ å…¥æ–°é …ç›® created_msg: å·²æˆåŠŸå°‡é›»åä¿¡ç®±ç¶²åŸŸåŠ å…¥é»‘åå–® delete: 刪除 destroyed_msg: å·²æˆåŠŸå¾žé»‘å單刪除電å信箱網域 domain: 站點 + empty: ç¾åœ¨æ²’有阻擋任何 e-mail 網域。 + from_html: ç”± %{domain} new: create: 新增站點 title: 新增電å信箱黑åå–®é …ç›® title: é›»å信箱黑åå–® instances: + by_domain: ç«™å° + delivery_available: å¯å‚³é€ + empty: 找ä¸åˆ°ç¶²åŸŸ + known_accounts: + other: "%{count} 已知的帳戶" moderation: all: 全部 limited: é™åˆ¶ title: 版主 + private_comment: ç§äººç•™è¨€ + public_comment: 公開留言 title: è¯é‚¦ + total_blocked_by_us: 被我們å°éŽ– + total_followed_by_them: 被他們關注 + total_followed_by_us: 被我們關注 + total_reported: é—œæ–¼ä»–å€‘çš„èˆ‰å ± + total_storage: 多媒體附檔 invites: + deactivate_all: 全部åœç”¨ filter: all: 全部 available: å¯ç”¨ expired: 已失效 title: ç¯©é¸ title: 邀請使用者 + ip_blocks: + add_new: 建立è¦å‰‡ + created_msg: æ›´æ–° IP è¦å‰‡æˆåŠŸ + delete: 刪除 + expires_in: + '1209600': 2 個星期 + '15778476': 6 個月 + '2629746': 1 個月 + '31556952': 1 å¹´ + '86400': 1 天 + '94670856': 3 å¹´ + new: + title: 建立新的 IP è¦å‰‡ + no_ip_block_selected: å› ç‚ºæ²’æœ‰é¸æ“‡ä»»ä½• IP è¦å‰‡ï¼Œæ‰€ä»¥ä»€éº¼äº‹éƒ½æ²’發生 + title: IP è¦å‰‡ + pending_accounts: + title: 待處ç†å¸³æˆ¶(%{count}) + relationships: + title: "%{acct} 的關係" relays: + add_new: 新增ä¸ç¹¼ç«™ + delete: 刪除 description_html: "<strong>è¯é‚¦ä¸ç¹¼ç«™</strong> 是種ä¸ç¹¼ä¼ºæœå™¨ï¼Œæœƒåœ¨è¨‚閱並推é€è‡³æ¤ä¸ç¹¼ç«™çš„伺æœå™¨ä¹‹é–“交æ›å¤§é‡çš„公開嘟文。<strong>ä¸ç¹¼ç«™ä¹Ÿèƒ½å”助å°åž‹æˆ–ä¸åž‹ä¼ºæœå™¨å¾žè¯é‚¦ä¸æŽ¢ç´¢å…§å®¹</strong>ï¼Œè€Œç„¡é ˆæœ¬åœ°ä½¿ç”¨è€…æ‰‹å‹•é—œæ³¨é 端伺æœå™¨çš„其他使用者。" + disable: åœç”¨ disabled: åœç”¨ enable: 啟用 + enable_hint: å•Ÿç”¨å¾Œï¼Œä½ çš„ä¼ºæœå™¨å°‡è¨‚閱該ä¸ç¹¼çš„æ‰€æœ‰å…¬é–‹æ–‡ç« ,並將會æ¤ä¼ºæœå™¨çš„å…¬é–‹æ–‡ç« ç™¼é€çµ¦å®ƒã€‚ + enabled: 已啟用 + inbox_url: ä¸ç¹¼URL + pending: ç‰å¾…ä¸ç¹¼ç«™å¯©æ ¸ + save_and_enable: 儲å˜ä¸¦å•Ÿç”¨ + setup: è¨å®šä¸ç¹¼é€£çµ + signatures_not_enabled: è‹¥å•Ÿç”¨å®‰å…¨æ¨¡å¼æˆ–å—é™çš„站點è¯ç›Ÿæ¨¡å¼ï¼Œä¸ç¹¼å°‡ä¸æœƒæ£å¸¸é‹ä½œ + status: 狀態 + title: ä¸ç¹¼ report_notes: created_msg: 檢舉記錄建立æˆåŠŸ! destroyed_msg: 檢舉記錄刪除æˆåŠŸ! reports: + account: + notes: + other: "%{count} 則備註" + reports: + other: "%{count} 則檢舉" action_taken_by: æ“作執行者 are_you_sure: ä½ ç¢ºå®šå—Ž? assign_to_self: 指派給自己 assigned: æŒ‡æ´¾è² è²¬äºº + by_target_domain: 檢舉帳號之網域 comment: none: ç„¡ created_at: 日期 + forwarded: 已轉寄 + forwarded_to: 轉寄到 %{domain} mark_as_resolved: 標記為「已解決〠mark_as_unresolved: 標記為「未解決〠notes: @@ -409,19 +544,33 @@ zh-TW: contact_information: email: 用於è¯çµ¡çš„公開電åä¿¡ç®±ä½å€ username: 請輸入使用者å稱 + custom_css: + desc_html: é€éŽæ–¼æ¯å€‹é é¢éƒ½è¼‰å…¥çš„ CSS 調整外觀 + title: 自訂 CSS + default_noindex: + desc_html: 影響所有沒有變更æ¤è¨å®šçš„使用者 + title: é è¨å°‡ä½¿ç”¨è€…退出æœå°‹å¼•擎索引 domain_blocks: all: 給任何人 disabled: 給沒有人 title: 顯示å°éŽ–çš„ç¶²åŸŸ + users: 套用至所有登入的本機使用者 + domain_blocks_rationale: + title: é¡¯ç¤ºè§£é‡‹åŽŸå› enable_bootstrap_timeline_accounts: + desc_html: 使新使用者自動跟隨è¨å®šä¹‹å¸³è™Ÿï¼Œæ‰€ä»¥ä»–們的首é å‹•æ…‹ä¸€é–‹å§‹ä¸æœƒç©ºç™½ title: 啟用新使用者的é è¨è¿½è¹¤ hero: desc_html: 在首é é¡¯ç¤ºã€‚æŽ¨è–¦æœ€å° 600x100px。如果留空,就會é‡è¨å›žä¼ºæœå™¨é 覽圖 title: 主題圖片 + mascot: + desc_html: 在許多é é¢éƒ½æœƒé¡¯ç¤ºã€‚æŽ¨è–¦æœ€å° 293x205px。如果留空,將採用é è¨çš„å‰ç¥¥ç‰© + title: å‰ç¥¥ç‰©åœ–片 peers_api_enabled: desc_html: 本伺æœå™¨åœ¨è¯é‚¦ä¸ç™¼ç¾çš„站點 title: 發布已知伺æœå™¨çš„列表 preview_sensitive_media: + desc_html: 連çµä¾†è‡ªå…¶ä»–網站的é 覽將顯示於縮圖,å³ä½¿é€™äº›åª’é«”è¢«æ¨™è¨˜ç‚ºæ•æ„Ÿ title: 在 OpenGraph é 覽ä¸é¡¯ç¤ºæ•感媒體 profile_directory: desc_html: å…許能探索使用者 @@ -436,6 +585,8 @@ zh-TW: min_invite_role: disabled: 沒有人 title: å…許發é€é‚€è«‹çš„身份 + require_invite_text: + title: è¦æ±‚新使用者填申請書以索å–邀請 registrations_mode: modes: approved: è¨»å†Šéœ€è¦æ ¸å‡† @@ -469,6 +620,8 @@ zh-TW: desc_html: 在主é 顯示本站時間軸 title: 時間軸é 覽 title: 網站è¨å®š + trendable_by_default: + title: å…許熱門的主題標籤直接顯示於趨勢å€ï¼Œä¸éœ€ç¶“éŽå¯©æ ¸ trends: title: 趨勢主題標籤 site_uploads: @@ -489,6 +642,8 @@ zh-TW: title: 帳戶嘟文 with_media: 嫿œ‰åª’體檔案 tags: + accounts_today: 本日ä¸é‡è¤‡ä½¿ç”¨è€…數 + accounts_week: 本週ä¸é‡è¤‡ä½¿ç”¨è€…數 context: 上下文 directory: åœ¨ç›®éŒ„ä¸ in_directory: ç›®éŒ„ä¸æœ‰ %{count} 個 @@ -513,10 +668,16 @@ zh-TW: body_remote: 來自 %{domain} 的使用者檢舉了使用者 %{target} subject: 來自 %{instance} 的使用者檢舉(#%{id}) appearance: + advanced_web_interface: 進階網é ä»‹é¢ + advanced_web_interface_hint: 進階網é 界é¢å¯è®“您é…置許多ä¸åŒçš„æ¬„ä½ä¾†å–„用多餘的螢幕空間,ä¾éœ€è¦åŒæ™‚查看盡å¯èƒ½å¤šçš„資訊如:首é ã€é€šçŸ¥ã€ç«™é»žè¯é‚¦æ™‚間軸ã€ä»»æ„數é‡çš„列表和主題標籤。 + animations_and_accessibility: 動畫與å¯ç”¨æ€§ + discovery: 探索 localization: body: Mastodon 是由志願者翻è¯çš„。 guide_link: https://crowdin.com/project/mastodon guide_link_text: æ¯å€‹äººéƒ½èƒ½è²¢ç»ã€‚ + sensitive_content: æ•æ„Ÿå…§å®¹ + toot_layout: 嘟文佈局 application_mailer: notification_preferences: 變更電åä¿¡ä»¶è¨å®š salutation: "%{name}ã€" @@ -533,12 +694,16 @@ zh-TW: warning: è¦å‘Šï¼Œä¸è¦æŠŠå®ƒåˆ†äº«çµ¦ä»»ä½•人! your_token: ä½ çš„ token auth: + apply_for_account: ç´¢å–註冊邀請 change_password: 密碼 delete_account: 刪除帳戶 delete_account_html: å¦‚æžœä½ æƒ³åˆªé™¤ä½ çš„å¸³æˆ¶ï¼Œè«‹<a href="%{path}">點擊這裡繼續</a>ã€‚ä½ éœ€è¦ç¢ºèªä½ çš„æ“作。 + description: + prefix_sign_up: ç¾åœ¨å°±è¨»å†Š Mastodon 帳號å§ï¼ didnt_get_confirmation: 沒有收到驗è‰ä¿¡? forgot_password: 忘記密碼? invalid_reset_password_token: 密碼é‡è¨ token ç„¡æ•ˆæˆ–å·²éŽæœŸã€‚è«‹é‡æ–°è¨å®šå¯†ç¢¼ã€‚ + link_to_webauth: 使用您的安全金鑰 login: 登入 logout: 登出 migrate_account: 轉移到å¦ä¸€å€‹å¸³æˆ¶ @@ -547,10 +712,14 @@ zh-TW: providers: saml: SAML register: 註冊 + registration_closed: "%{instance} ç¾åœ¨ä¸é–‹æ”¾æ–°æˆå“¡" resend_confirmation: 釿–°å¯„é€ç¢ºèªæŒ‡å¼• reset_password: é‡è¨å¯†ç¢¼ security: 登入資訊 set_new_password: è¨å®šæ–°å¯†ç¢¼ + setup: + email_settings_hint_html: è«‹ç¢ºèª e-mail 是å¦å‚³é€åˆ° %{email} 。如果ä¸å°çš„話,å¯ä»¥å¾žå¸³è™Ÿè¨å®šä¿®æ”¹ã€‚ + title: è¨å®š authorize_follow: already_following: ä½ å·²ç¶“é—œæ³¨äº†é€™å€‹ä½¿ç”¨è€… already_requested: 您早已å‘該帳戶寄é€è¿½è¹¤è«‹æ±‚ @@ -609,15 +778,20 @@ zh-TW: lists: 列表 mutes: 您éœéŸ³çš„使用者 storage: 儲å˜ç©ºé–“å¤§å° + featured_tags: + hint_html: "<strong>推薦標籤是什麼?</strong> 這些標籤將顯示於您的公開個人檔案é ,訪客å¯ä»¥è—‰æ¤é–±è¦½æ‚¨æ¨™ç¤ºäº†é€™äº›æ¨™ç±¤çš„嘟文,拿來展示創æ„ä½œå“æˆ–者長期更新的專案很好用唷ï¼" filters: index: empty: æ‚¨æ²’æœ‰éŽæ¿¾å™¨ã€‚ + title: éŽæ¿¾å™¨ footer: more: 更多...... + trending_now: ç¾æ£ç†±é–€ generic: all: 全部 changes_saved_msg: å·²æˆåŠŸå„²å˜ä¿®æ”¹! copy: 複製 + delete: 刪除 save_changes: 儲å˜ä¿®æ”¹ imports: preface: 您å¯ä»¥åœ¨æ¤åŒ¯å…¥æ‚¨åœ¨å…¶ä»–伺æœå™¨æ‰€åŒ¯å‡ºçš„資料檔,包括關注的使用者ã€å°éŽ–çš„ä½¿ç”¨è€…å單。 @@ -656,6 +830,8 @@ zh-TW: too_many: ç„¡æ³•åŠ å…¥è¶…éŽ 4 個檔案 migrations: acct: 新帳戶的 使用者å稱@站點網域 + proceed_with_move: 移動關注者 + redirected_msg: 您的帳號ç¾åœ¨æŒ‡å‘ %{acct} moderation: title: ç‡Ÿé‹ notification_mailer: @@ -686,6 +862,10 @@ zh-TW: body: 'ä½ çš„å˜Ÿæ–‡è¢« %{name} 轉嘟:' subject: "%{name} è½‰å˜Ÿäº†ä½ çš„å˜Ÿæ–‡" title: 新的轉嘟 + notifications: + email_events: é›»å郵件通知è¨å®š + email_events_hint: é¸å–ä½ æƒ³æŽ¥æ”¶é€šçŸ¥çš„äº‹ä»¶ï¼š + other_settings: 其他通知è¨å®š number: human: decimal_units: @@ -701,6 +881,8 @@ zh-TW: next: 下一é older: 較舊 prev: 上一é + preferences: + other: å…¶ä»–è¨å®š remote_follow: acct: 請輸入您的使用者å稱@站點網域 missing_resource: ç„¡æ³•æ‰¾åˆ°è³‡æº @@ -738,16 +920,19 @@ zh-TW: revoke_success: Session å–æ¶ˆæˆåŠŸ title: 作æ¥éšŽæ®µ settings: + appearance: 外觀è¨å®š authorized_apps: å·²æŽˆæ¬Šæ‡‰ç”¨ç¨‹å¼ back: 回到 Mastodon delete: 刪除帳戶 development: 開發 edit_profile: 編輯使用者資訊 export: 匯出 + featured_tags: 推薦標籤 import: 匯入 migrate: 帳戶æ¬é· notifications: 通知 preferences: å好è¨å®š + profile: 使用者資訊 two_factor_authentication: 兩階段èªè‰ statuses: attached: @@ -787,21 +972,14 @@ zh-TW: formats: default: "%Yå¹´%-m月%dæ—¥ %H:%M" two_factor_authentication: - code_hint: 請輸入您èªè‰å™¨ç”¢ç”Ÿçš„代碼,以進行èªè‰ - description_html: 啟用<strong>兩階段èªè‰</strong>後,登入時將需è¦ä½¿æ‰‹æ©Ÿã€æˆ–其他種類èªè‰å™¨ç”¢ç”Ÿçš„代碼。 disable: åœç”¨ - enable: 啟用 enabled: 兩階段èªè‰å·²å•Ÿç”¨ enabled_success: å·²æˆåŠŸå•Ÿç”¨å…©éšŽæ®µèªè‰ generate_recovery_codes: 產生備用驗è‰ç¢¼ - instructions_html: "<strong>請用您手機的èªè‰å™¨æ‡‰ç”¨ç¨‹å¼ï¼ˆå¦‚ Google Authenticatorã€Authy),掃æé€™è£¡çš„ QR 圖形碼</strong>。在兩階段èªè‰å•Ÿç”¨å¾Œï¼Œæ‚¨ç™»å…¥æ™‚å°‡é ˆè¦ä½¿ç”¨æ¤æ‡‰ç”¨ç¨‹å¼ç”¢ç”Ÿçš„èªè‰ç¢¼ã€‚" lost_recovery_codes: è®“ä½ å¯ä»¥åœ¨éºå¤±æ‰‹æ©Ÿæ™‚,使用備用驗è‰ç¢¼ç™»å…¥ã€‚å¦‚æžœä½ éºå¤±äº†å‚™ç”¨é©—è‰ç¢¼ï¼Œå¯ä»¥åœ¨é€™è£ç”¢ç”Ÿä¸€æ‰¹æ–°çš„,舊有的備用驗è‰ç¢¼å°‡æœƒå¤±æ•ˆã€‚ - manual_instructions: '如果您無法掃æ QR 圖形碼,請手動輸入:' recovery_codes: 備份備用驗è‰ç¢¼ recovery_codes_regenerated: æˆåŠŸç”¢ç”Ÿæ–°çš„å‚™ç”¨é©—è‰ç¢¼ recovery_instructions_html: å¦‚æžœä½ çš„æ‰‹æ©Ÿç„¡æ³•ä½¿ç”¨ï¼Œä½ å¯ä»¥ä½¿ç”¨ä¸‹åˆ—ä»»æ„一個備用驗è‰ç¢¼ä¾†é‡æ–°ç²å¾—å¸³æˆ¶çš„è¨ªå•æ¬Šã€‚<strong>請妥善ä¿ç®¡å¥½ä½ 的備用驗è‰ç¢¼</strong>ï¼ˆä¾‹å¦‚ï¼Œä½ å¯ä»¥å°‡å®ƒå€‘列å°å‡ºä¾†ï¼Œèˆ‡ä½ 的其他é‡è¦æ–‡ä»¶æ”¾åœ¨ä¸€èµ·ï¼‰ã€‚ - setup: è¨å®š - wrong_code: 您輸入的èªè‰ç¢¼ç„¡æ•ˆ! 請確èªä¼ºæœå™¨æ™‚間與è¨å‚™æ™‚é–“æ˜¯å¦æ£ç¢º? user_mailer: backup_ready: explanation: ä½ è¦æ±‚çš„ Mastodon 帳戶完整備份檔案ç¾å·²å°±ç·’,å¯ä¾›ä¸‹è¼‰! @@ -825,8 +1003,15 @@ zh-TW: tips: å°å¹«æ‰‹ title: "%{name} æ¡è¿Žä½ çš„åŠ å…¥ï¼" users: + blocked_email_provider: ä¸å…許使用這個電åä¿¡ç®±æä¾›è€… invalid_email: é›»åä¿¡ç®±ä½å€ä¸æ£ç¢º + invalid_email_mx: 似乎沒有這個電åä¿¡ç®±åœ°å€ invalid_otp_token: 兩階段èªè‰ç¢¼ä¸æ£ç¢º otp_lost_help_html: å¦‚æžœä½ ç„¡æ³•è¨ªå•這兩者,å¯ä»¥é€šéŽ %{email} 與我們è¯ç¹« seamless_external_login: ç”±æ–¼ä½ æ˜¯å¾žå¤–éƒ¨ç³»çµ±ç™»å…¥ï¼Œæ‰€ä»¥ä¸èƒ½è¨å®šå¯†ç¢¼èˆ‡é›»å郵件。 signed_in_as: ç›®å‰ç™»å…¥çš„帳戶: + verification: + explanation_html: 您在 Mastodon 個人資料é 上所列出的連çµï¼Œå¯ä»¥ç”¨æ¤æ–¹å¼<strong>é©—è‰æ‚¨ç¢ºå¯¦æŽŒæŽ§è©²é€£çµç¶²é 的內容</strong>。您å¯ä»¥åœ¨é€£çµçš„ç¶²é ä¸ŠåŠ ä¸Šä¸€å€‹é€£å›ž Mastodon 個人資料é 的連çµï¼Œè©²é€£çµçš„原始碼 <strong>å¿…é ˆ</strong>包å«<code>rel="me"</code>屬性。連çµçš„顯示文å—å¯è‡ªç”±ç™¼æ®ï¼Œä»¥ä¸‹ç‚ºç¯„例: + verification: é©—è‰é€£çµ + webauthn_credentials: + registered_on: 註冊於 %{date} diff --git a/config/navigation.rb b/config/navigation.rb index 8fd296d5a1194106395bf442c79e2268e1a03c34..4a56abe18cb639ad1c0e938bd15422bfa11b3031 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -21,7 +21,7 @@ SimpleNavigation::Configuration.run do |navigation| n.item :security, safe_join([fa_icon('lock fw'), t('settings.account')]), edit_user_registration_url do |s| s.item :password, safe_join([fa_icon('lock fw'), t('settings.account_settings')]), edit_user_registration_url, highlights_on: %r{/auth/edit|/settings/delete|/settings/migration|/settings/aliases} - s.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_url, highlights_on: %r{/settings/two_factor_authentication} + s.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_methods_url, highlights_on: %r{/settings/two_factor_authentication|/settings/otp_authentication|/settings/security_keys} s.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url end @@ -41,6 +41,7 @@ SimpleNavigation::Configuration.run do |navigation| s.item :tags, safe_join([fa_icon('hashtag fw'), t('admin.tags.title')]), admin_tags_path, highlights_on: %r{/admin/tags} s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.admin? } s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? } + s.item :ip_blocks, safe_join([fa_icon('ban fw'), t('admin.ip_blocks.title')]), admin_ip_blocks_url, highlights_on: %r{/admin/ip_blocks}, if: -> { current_user.admin? } end n.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_dashboard_url, if: proc { current_user.staff? } do |s| diff --git a/config/routes.rb b/config/routes.rb index 5b768807b45fcdc18e09fa79f56882fd5941dad0..c8a542be77d4d9742b85c0c49cefec8904fcb2df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,6 +37,7 @@ Rails.application.routes.draw do resource :instance_actor, path: 'actor', only: [:show] do resource :inbox, only: [:create], module: :activitypub + resource :outbox, only: [:show], module: :activitypub end devise_scope :user do @@ -45,6 +46,7 @@ Rails.application.routes.draw do namespace :auth do resource :setup, only: [:show, :update], controller: :setup resource :challenge, only: [:create], controller: :challenges + get 'sessions/security_key_options', to: 'sessions#webauthn_options' end end @@ -81,6 +83,7 @@ Rails.application.routes.draw do resource :inbox, only: [:create], module: :activitypub resource :claim, only: [:create], module: :activitypub resources :collections, only: [:show], module: :activitypub + resource :followers_synchronization, only: [:show], module: :activitypub end resource :inbox, only: [:create], module: :activitypub @@ -122,9 +125,25 @@ Rails.application.routes.draw do resources :mutes, only: :index, controller: :muted_accounts resources :lists, only: :index, controller: :lists resources :domain_blocks, only: :index, controller: :blocked_domains + resources :bookmarks, only: :index, controller: :bookmarks + end + + resources :two_factor_authentication_methods, only: [:index] do + collection do + post :disable + end end - resource :two_factor_authentication, only: [:show, :create, :destroy] + resource :otp_authentication, only: [:show, :create], controller: 'two_factor_authentication/otp_authentication' + + resources :webauthn_credentials, only: [:index, :new, :create, :destroy], + path: 'security_keys', + controller: 'two_factor_authentication/webauthn_credentials' do + + collection do + get :options + end + end namespace :two_factor_authentication do resources :recovery_codes, only: [:create] @@ -171,11 +190,7 @@ Rails.application.routes.draw do get '/dashboard', to: 'dashboard#index' resources :domain_allows, only: [:new, :create, :show, :destroy] - resources :domain_blocks, only: [:new, :create, :show, :destroy, :update] do - member do - get :edit - end - end + resources :domain_blocks, only: [:new, :create, :show, :destroy, :update, :edit] resources :email_domain_blocks, only: [:index, :new, :create, :destroy] resources :action_logs, only: [:index] @@ -219,9 +234,10 @@ Rails.application.routes.draw do resources :report_notes, only: [:create, :destroy] - resources :accounts, only: [:index, :show] do + resources :accounts, only: [:index, :show, :destroy] do member do post :enable + post :unsensitive post :unsilence post :unsuspend post :redownload @@ -270,6 +286,12 @@ Rails.application.routes.draw do end end + resources :ip_blocks, only: [:index, :new, :create] do + collection do + post :batch + end + end + resources :account_moderation_notes, only: [:create, :destroy] resources :tags, only: [:index, :show, :update] do @@ -419,6 +441,7 @@ Rails.application.routes.draw do resources :lists, only: :index, controller: 'accounts/lists' resources :circles, only: :index, controller: 'accounts/circles' resources :identity_proofs, only: :index, controller: 'accounts/identity_proofs' + resources :featured_tags, only: :index, controller: 'accounts/featured_tags' member do post :follow @@ -457,9 +480,10 @@ Rails.application.routes.draw do end namespace :admin do - resources :accounts, only: [:index, :show] do + resources :accounts, only: [:index, :show, :destroy] do member do post :enable + post :unsensitive post :unsilence post :unsuspend post :approve diff --git a/config/settings.yml b/config/settings.yml index 002473643513b7d598746c70cd7d5dfaea817125..9cf68a096632d500c4ac1909c1544054555de6d7 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -26,6 +26,7 @@ defaults: &defaults expand_spoilers: false preview_sensitive_media: false reduce_motion: false + disable_swiping: false show_application: true system_font_ui: false noindex: false @@ -69,6 +70,7 @@ defaults: &defaults spam_check_enabled: true show_domain_blocks: 'disabled' show_domain_blocks_rationale: 'disabled' + require_invite_text: false development: <<: *defaults diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 5de25de234be1f5ebcf246090c4a91cb9bce14cf..010923717eb922849631e59954bedd596724b63c 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -5,34 +5,51 @@ - [push, 4] - [mailers, 2] - [pull] + - [scheduler] +:scheduler: + :listened_queues_only: true :schedule: scheduled_statuses_scheduler: every: '5m' class: Scheduler::ScheduledStatusesScheduler + queue: scheduler trending_tags_scheduler: every: '5m' class: Scheduler::TrendingTagsScheduler + queue: scheduler media_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *' class: Scheduler::MediaCleanupScheduler + queue: scheduler feed_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(0..2) %> * * *' class: Scheduler::FeedCleanupScheduler + queue: scheduler doorkeeper_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(0..2) %> * * 0' class: Scheduler::DoorkeeperCleanupScheduler + queue: scheduler user_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(4..6) %> * * *' class: Scheduler::UserCleanupScheduler + queue: scheduler ip_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *' class: Scheduler::IpCleanupScheduler + queue: scheduler email_scheduler: cron: '0 10 * * 2' class: Scheduler::EmailScheduler + queue: scheduler backup_cleanup_scheduler: cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *' class: Scheduler::BackupCleanupScheduler + queue: scheduler pghero_scheduler: cron: '0 0 * * *' class: Scheduler::PgheroScheduler + queue: scheduler + instance_refresh_scheduler: + cron: '0 * * * *' + class: Scheduler::InstanceRefreshScheduler + queue: scheduler diff --git a/config/webpack/configuration.js b/config/webpack/configuration.js index 80a094c724e6a1986f23bc874150e2a697651685..25b6b7abd618b3ffa85ed90d624d5c0314e96712 100644 --- a/config/webpack/configuration.js +++ b/config/webpack/configuration.js @@ -2,39 +2,26 @@ const { resolve } = require('path'); const { env } = require('process'); -const { safeLoad } = require('js-yaml'); +const { load } = require('js-yaml'); const { readFileSync } = require('fs'); const configPath = resolve('config', 'webpacker.yml'); -const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV]; +const settings = load(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV]; const themePath = resolve('config', 'themes.yml'); -const themes = safeLoad(readFileSync(themePath), 'utf8'); - -function removeOuterSlashes(string) { - return string.replace(/^\/*/, '').replace(/\/*$/, ''); -} - -function formatPublicPath(host = '', path = '') { - let formattedHost = removeOuterSlashes(host); - if (formattedHost && !/^http/i.test(formattedHost)) { - formattedHost = `//${formattedHost}`; - } - const formattedPath = removeOuterSlashes(path); - return `${formattedHost}/${formattedPath}/`; -} +const themes = load(readFileSync(themePath), 'utf8'); const output = { path: resolve('public', settings.public_output_path), - publicPath: formatPublicPath(env.CDN_HOST, settings.public_output_path), + publicPath: `/${settings.public_output_path}/`, }; module.exports = { settings, themes, env: { - CDN_HOST: env.CDN_HOST, NODE_ENV: env.NODE_ENV, + PUBLIC_OUTPUT_PATH: settings.public_output_path, }, output, }; diff --git a/config/webpack/development.js b/config/webpack/development.js index 774ecbc0764437301306f5db296308d2c34f38e0..c3cf1b655c0b5b650cbff0548bbdf9930f83828e 100644 --- a/config/webpack/development.js +++ b/config/webpack/development.js @@ -1,6 +1,6 @@ // Note: You must restart bin/webpack-dev-server for changes to take effect -const merge = require('webpack-merge'); +const { merge } = require('webpack-merge'); const sharedConfig = require('./shared'); const { settings, output } = require('./configuration'); diff --git a/config/webpack/production.js b/config/webpack/production.js index bceffaf5c18e17c2d5b83f004c10bbedd5d8f452..f1d0dabae73837e12a0d37b088dec0d7ceb1c2e0 100644 --- a/config/webpack/production.js +++ b/config/webpack/production.js @@ -2,7 +2,7 @@ const path = require('path'); const { URL } = require('url'); -const merge = require('webpack-merge'); +const { merge } = require('webpack-merge'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const OfflinePlugin = require('offline-plugin'); const TerserPlugin = require('terser-webpack-plugin'); @@ -87,7 +87,7 @@ module.exports = merge(sharedConfig, { '**/*.woff', ], ServiceWorker: { - entry: `imports-loader?ATTACHMENT_HOST=>${encodeURIComponent(JSON.stringify(attachmentHost))}!${encodeURI(path.join(__dirname, '../../app/javascript/mastodon/service_worker/entry.js'))}`, + entry: `imports-loader?additionalCode=${encodeURIComponent(`var ATTACHMENT_HOST=${JSON.stringify(attachmentHost)};`)}!${encodeURI(path.join(__dirname, '../../app/javascript/mastodon/service_worker/entry.js'))}`, cacheName: 'mastodon', output: '../assets/sw.js', publicPath: '/sw.js', diff --git a/config/webpack/rules/index.js b/config/webpack/rules/index.js index bbf6b0187b173ff92f326a99ccfe412973dddadc..92a384e6d8f5971b9a3c405a1ad054b895d24b1c 100644 --- a/config/webpack/rules/index.js +++ b/config/webpack/rules/index.js @@ -1,6 +1,7 @@ const babel = require('./babel'); const css = require('./css'); const file = require('./file'); +const tesseract = require('./tesseract'); const nodeModules = require('./node_modules'); // Webpack loaders are processed in reverse order @@ -8,6 +9,7 @@ const nodeModules = require('./node_modules'); // Lastly, process static files using file loader module.exports = { file, + tesseract, css, nodeModules, babel, diff --git a/config/webpack/rules/node_modules.js b/config/webpack/rules/node_modules.js index 7ed05504bf3d29fcdfccaab9171031b61da2d111..c084d3a57eb0f4ae311ce3d702c47558a1e81021 100644 --- a/config/webpack/rules/node_modules.js +++ b/config/webpack/rules/node_modules.js @@ -4,7 +4,10 @@ const { settings, env } = require('../configuration'); module.exports = { test: /\.(js|mjs)$/, include: /node_modules/, - exclude: /@babel(?:\/|\\{1,2})runtime/, + exclude: [ + /@babel(?:\/|\\{1,2})runtime/, + /tesseract.js/, + ], use: [ { loader: 'babel-loader', diff --git a/config/webpack/rules/tesseract.js b/config/webpack/rules/tesseract.js new file mode 100644 index 0000000000000000000000000000000000000000..de647c8d1041b4254f9268d0d4c5b8f89662402e --- /dev/null +++ b/config/webpack/rules/tesseract.js @@ -0,0 +1,14 @@ +module.exports = { + test: [ + /tesseract\.js\/dist\/worker\.min\.js$/, + /tesseract\.js\/dist\/worker\.min\.js.map$/, + /tesseract\.js-core\/tesseract-core\.wasm$/, + /tesseract\.js-core\/tesseract-core\.wasm.js$/, + ], + use: { + loader: 'file-loader', + options: { + name: 'ocr/[name]-[hash].[ext]', + }, + }, +}; diff --git a/config/webpack/shared.js b/config/webpack/shared.js index 15a209253991f3fbe21d3678f474a64c2542df21..05828aebe076ef30e68e256fe32d12e2d837c5ac 100644 --- a/config/webpack/shared.js +++ b/config/webpack/shared.js @@ -5,7 +5,6 @@ const { basename, dirname, join, relative, resolve } = require('path'); const { sync } = require('glob'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const AssetsManifestPlugin = require('webpack-assets-manifest'); -const CopyPlugin = require('copy-webpack-plugin'); const extname = require('path-complete-extname'); const { env, settings, themes, output } = require('./configuration'); const rules = require('./rules'); @@ -80,17 +79,12 @@ module.exports = { chunkFilename: 'css/[name]-[contenthash:8].chunk.css', }), new AssetsManifestPlugin({ - integrity: false, + integrity: true, + integrityHashes: ['sha256'], entrypoints: true, writeToDisk: true, publicPath: true, }), - new CopyPlugin({ - patterns: [ - { from: 'node_modules/tesseract.js/dist/worker.min.js', to: 'ocr' }, - { from: 'node_modules/tesseract.js-core/tesseract-core.wasm.js', to: 'ocr' }, - ], - }), ], resolve: { diff --git a/config/webpack/tests.js b/config/webpack/tests.js index 8b56eb92f29f37294e26df6f5ab1fda96d21d39f..f9d39f1b800fa30b28e344358ba2d5ee527983dd 100644 --- a/config/webpack/tests.js +++ b/config/webpack/tests.js @@ -1,6 +1,6 @@ // Note: You must restart bin/webpack-dev-server for changes to take effect -const merge = require('webpack-merge'); +const { merge } = require('webpack-merge'); const sharedConfig = require('./shared.js'); module.exports = merge(sharedConfig, { diff --git a/db/migrate/20181127165847_add_show_replies_to_lists.rb b/db/migrate/20181127165847_add_show_replies_to_lists.rb new file mode 100644 index 0000000000000000000000000000000000000000..f68c98dafc27890a95e8b7d104f715bb2bb2b1d6 --- /dev/null +++ b/db/migrate/20181127165847_add_show_replies_to_lists.rb @@ -0,0 +1,23 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddShowRepliesToLists < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default( + :lists, + :replies_policy, + :integer, + allow_null: false, + default: 0 + ) + end + end + + def down + remove_column :lists, :replies_policy + end +end diff --git a/db/migrate/20200309150742_add_forwarded_to_reports.rb b/db/migrate/20200309150742_add_forwarded_to_reports.rb new file mode 100644 index 0000000000000000000000000000000000000000..df278240ba2bd760ba26f965798953ac8b3db686 --- /dev/null +++ b/db/migrate/20200309150742_add_forwarded_to_reports.rb @@ -0,0 +1,5 @@ +class AddForwardedToReports < ActiveRecord::Migration[5.2] + def change + add_column :reports, :forwarded, :boolean + end +end diff --git a/db/migrate/20200317021758_add_expires_at_to_mutes.rb b/db/migrate/20200317021758_add_expires_at_to_mutes.rb new file mode 100644 index 0000000000000000000000000000000000000000..eaae8319d7c11080081c20c5bc5bdd399186b6b0 --- /dev/null +++ b/db/migrate/20200317021758_add_expires_at_to_mutes.rb @@ -0,0 +1,5 @@ +class AddExpiresAtToMutes < ActiveRecord::Migration[5.2] + def change + add_column :mutes, :expires_at, :datetime + end +end diff --git a/db/migrate/20200614002136_add_sensitized_to_accounts.rb b/db/migrate/20200614002136_add_sensitized_to_accounts.rb new file mode 100644 index 0000000000000000000000000000000000000000..bc2dfcb6363bad70f14d57d2b3ad5517cab85477 --- /dev/null +++ b/db/migrate/20200614002136_add_sensitized_to_accounts.rb @@ -0,0 +1,5 @@ +class AddSensitizedToAccounts < ActiveRecord::Migration[5.2] + def change + add_column :accounts, :sensitized_at, :datetime + end +end diff --git a/db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb b/db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb index c5688681fc0c8f6dd1895bdca5d8f34c6c5d1679..c3aa8e33c26931b437b3a41a604f1f0f705a5e24 100644 --- a/db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb +++ b/db/migrate/20200620164023_add_fixed_lowercase_index_to_accounts.rb @@ -1,10 +1,30 @@ class AddFixedLowercaseIndexToAccounts < ActiveRecord::Migration[5.2] disable_ddl_transaction! + class CorruptionError < StandardError + def cause + nil + end + + def backtrace + [] + end + end + def up - rename_index :accounts, 'index_accounts_on_username_and_domain_lower', 'old_index_accounts_on_username_and_domain_lower' unless index_name_exists?(:accounts, 'old_index_accounts_on_username_and_domain_lower') - add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true, algorithm: :concurrently - remove_index :accounts, name: 'old_index_accounts_on_username_and_domain_lower' + if index_name_exists?(:accounts, 'old_index_accounts_on_username_and_domain_lower') && index_name_exists?(:accounts, 'index_accounts_on_username_and_domain_lower') + remove_index :accounts, name: 'index_accounts_on_username_and_domain_lower' + elsif index_name_exists?(:accounts, 'index_accounts_on_username_and_domain_lower') + rename_index :accounts, 'index_accounts_on_username_and_domain_lower', 'old_index_accounts_on_username_and_domain_lower' + end + + begin + add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true, algorithm: :concurrently + rescue ActiveRecord::RecordNotUnique + raise CorruptionError, 'Migration failed because of index corruption, see https://docs.joinmastodon.org/admin/troubleshooting/index-corruption/#fixing' + end + + remove_index :accounts, name: 'old_index_accounts_on_username_and_domain_lower' if index_name_exists?(:accounts, 'old_index_accounts_on_username_and_domain_lower') end def down diff --git a/db/migrate/20200630190240_create_webauthn_credentials.rb b/db/migrate/20200630190240_create_webauthn_credentials.rb new file mode 100644 index 0000000000000000000000000000000000000000..ea924238d4a3a96a7a3590a972a044f5fd76fff9 --- /dev/null +++ b/db/migrate/20200630190240_create_webauthn_credentials.rb @@ -0,0 +1,16 @@ +class CreateWebauthnCredentials < ActiveRecord::Migration[5.2] + def change + create_table :webauthn_credentials do |t| + t.string :external_id, null: false + t.string :public_key, null: false + t.string :nickname, null: false + t.bigint :sign_count, null: false, default: 0 + + t.index :external_id, unique: true + + t.references :user, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/migrate/20200630190544_add_webauthn_id_to_users.rb b/db/migrate/20200630190544_add_webauthn_id_to_users.rb new file mode 100644 index 0000000000000000000000000000000000000000..95d3c92a867a00aea6b76fa02bb3da10fa74fbf9 --- /dev/null +++ b/db/migrate/20200630190544_add_webauthn_id_to_users.rb @@ -0,0 +1,5 @@ +class AddWebauthnIdToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :webauthn_id, :string + end +end diff --git a/db/migrate/20200908193330_create_account_deletion_requests.rb b/db/migrate/20200908193330_create_account_deletion_requests.rb new file mode 100644 index 0000000000000000000000000000000000000000..e03183ae457876610afe44abbbcbce7900097e64 --- /dev/null +++ b/db/migrate/20200908193330_create_account_deletion_requests.rb @@ -0,0 +1,8 @@ +class CreateAccountDeletionRequests < ActiveRecord::Migration[5.2] + def change + create_table :account_deletion_requests do |t| + t.references :account, foreign_key: { on_delete: :cascade } + t.timestamps + end + end +end diff --git a/db/migrate/20200917192924_add_notify_to_follows.rb b/db/migrate/20200917192924_add_notify_to_follows.rb new file mode 100644 index 0000000000000000000000000000000000000000..d27471c447f0af57b4ff3281cae74b164fa20c91 --- /dev/null +++ b/db/migrate/20200917192924_add_notify_to_follows.rb @@ -0,0 +1,19 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddNotifyToFollows < ActiveRecord::Migration[5.1] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured do + add_column_with_default :follows, :notify, :boolean, default: false, allow_null: false + add_column_with_default :follow_requests, :notify, :boolean, default: false, allow_null: false + end + end + + def down + remove_column :follows, :notify + remove_column :follow_requests, :notify + end +end diff --git a/db/migrate/20200917193034_add_type_to_notifications.rb b/db/migrate/20200917193034_add_type_to_notifications.rb new file mode 100644 index 0000000000000000000000000000000000000000..002be3aa00b0dc99827dab1ee0de68130e211a4e --- /dev/null +++ b/db/migrate/20200917193034_add_type_to_notifications.rb @@ -0,0 +1,5 @@ +class AddTypeToNotifications < ActiveRecord::Migration[5.2] + def change + add_column :notifications, :type, :string + end +end diff --git a/db/migrate/20200917222316_add_index_notifications_on_type.rb b/db/migrate/20200917222316_add_index_notifications_on_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..9bd23c1d3d97a589c8477ca1a13cec5b5fb78e64 --- /dev/null +++ b/db/migrate/20200917222316_add_index_notifications_on_type.rb @@ -0,0 +1,7 @@ +class AddIndexNotificationsOnType < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + def change + add_index :notifications, [:account_id, :id, :type], order: { id: :desc }, algorithm: :concurrently + end +end diff --git a/db/migrate/20201008202037_create_ip_blocks.rb b/db/migrate/20201008202037_create_ip_blocks.rb new file mode 100644 index 0000000000000000000000000000000000000000..32acd6ede1759c0d172b9c46ac1c6a3a4fabdd30 --- /dev/null +++ b/db/migrate/20201008202037_create_ip_blocks.rb @@ -0,0 +1,12 @@ +class CreateIpBlocks < ActiveRecord::Migration[5.2] + def change + create_table :ip_blocks do |t| + t.inet :ip, null: false, default: '0.0.0.0' + t.integer :severity, null: false, default: 0 + t.datetime :expires_at + t.text :comment, null: false, default: '' + + t.timestamps + end + end +end diff --git a/db/migrate/20201008220312_add_sign_up_ip_to_users.rb b/db/migrate/20201008220312_add_sign_up_ip_to_users.rb new file mode 100644 index 0000000000000000000000000000000000000000..66cd624bbb8e1f96aa15eb515d2274311cf5bf80 --- /dev/null +++ b/db/migrate/20201008220312_add_sign_up_ip_to_users.rb @@ -0,0 +1,5 @@ +class AddSignUpIpToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :sign_up_ip, :inet + end +end diff --git a/db/migrate/20201017233919_add_suspension_origin_to_accounts.rb b/db/migrate/20201017233919_add_suspension_origin_to_accounts.rb new file mode 100644 index 0000000000000000000000000000000000000000..f0db02143aed1df82fbf95347235aba7a1e59eda --- /dev/null +++ b/db/migrate/20201017233919_add_suspension_origin_to_accounts.rb @@ -0,0 +1,5 @@ +class AddSuspensionOriginToAccounts < ActiveRecord::Migration[5.2] + def change + add_column :accounts, :suspension_origin, :integer + end +end diff --git a/db/migrate/20201206004238_create_instances.rb b/db/migrate/20201206004238_create_instances.rb new file mode 100644 index 0000000000000000000000000000000000000000..a4b866894ad8bf830b002f1e7ff339b7330a34ad --- /dev/null +++ b/db/migrate/20201206004238_create_instances.rb @@ -0,0 +1,9 @@ +class CreateInstances < ActiveRecord::Migration[5.2] + def change + create_view :instances, materialized: true + + # To be able to refresh the view concurrently, + # at least one unique index is required + safety_assured { add_index :instances, :domain, unique: true } + end +end diff --git a/db/migrate/20201218054746_add_obfuscate_to_domain_blocks.rb b/db/migrate/20201218054746_add_obfuscate_to_domain_blocks.rb new file mode 100644 index 0000000000000000000000000000000000000000..26f4ddb851dbb96441b8120de3f303dd01d487c2 --- /dev/null +++ b/db/migrate/20201218054746_add_obfuscate_to_domain_blocks.rb @@ -0,0 +1,15 @@ +require Rails.root.join('lib', 'mastodon', 'migration_helpers') + +class AddObfuscateToDomainBlocks < ActiveRecord::Migration[5.2] + include Mastodon::MigrationHelpers + + disable_ddl_transaction! + + def up + safety_assured { add_column_with_default :domain_blocks, :obfuscate, :boolean, default: false, allow_null: false } + end + + def down + remove_column :domain_blocks, :obfuscate + end +end diff --git a/db/post_migrate/20200917193528_migrate_notifications_type.rb b/db/post_migrate/20200917193528_migrate_notifications_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..88e4230842b4e175c7b2fb9b86efdaa6a0d85d4c --- /dev/null +++ b/db/post_migrate/20200917193528_migrate_notifications_type.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class MigrateNotificationsType < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + TYPES_TO_MIGRATE = { + 'Mention' => :mention, + 'Status' => :reblog, + 'Follow' => :follow, + 'FollowRequest' => :follow_request, + 'Favourite' => :favourite, + 'Poll' => :poll, + }.freeze + + def up + TYPES_TO_MIGRATE.each_pair do |activity_type, type| + Notification.where(activity_type: activity_type, type: nil).in_batches.update_all(type: type) + end + end + + def down; end +end diff --git a/db/post_migrate/20200917222734_remove_index_notifications_on_account_activity.rb b/db/post_migrate/20200917222734_remove_index_notifications_on_account_activity.rb new file mode 100644 index 0000000000000000000000000000000000000000..cb7f78e53bffddf230bc765b32b5cb15549b0cbc --- /dev/null +++ b/db/post_migrate/20200917222734_remove_index_notifications_on_account_activity.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class RemoveIndexNotificationsOnAccountActivity < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + def up + remove_index :notifications, name: :account_activity + remove_index :notifications, name: :index_notifications_on_account_id_and_id + end + + def down + add_index :notifications, [:account_id, :activity_id, :activity_type], unique: true, name: 'account_activity', algorithm: :concurrently + add_index :notifications, [:account_id, :id], order: { id: :desc }, algorithm: :concurrently + end +end diff --git a/db/post_migrate/20201017234926_fill_account_suspension_origin.rb b/db/post_migrate/20201017234926_fill_account_suspension_origin.rb new file mode 100644 index 0000000000000000000000000000000000000000..ab7407d79e01d3aee17cf15ddbc1ee5836390bd4 --- /dev/null +++ b/db/post_migrate/20201017234926_fill_account_suspension_origin.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class FillAccountSuspensionOrigin < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + def up + Account.suspended.where(suspension_origin: nil).in_batches.update_all(suspension_origin: :local) + end + + def down; end +end diff --git a/db/schema.rb b/db/schema.rb index 91869ce1aa732327b31ab310aac43ebb48d6e656..389b33b6142c08d0881dff644f0fcba73dbfc359 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_07_18_225817) do +ActiveRecord::Schema.define(version: 2020_12_18_054746) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -36,6 +36,13 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.index ["conversation_id"], name: "index_account_conversations_on_conversation_id" end + create_table "account_deletion_requests", force: :cascade do |t| + t.bigint "account_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id"], name: "index_account_deletion_requests_on_account_id" + end + create_table "account_domain_blocks", force: :cascade do |t| t.string "domain" t.datetime "created_at", null: false @@ -182,6 +189,8 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.integer "avatar_storage_schema_version" t.integer "header_storage_schema_version" t.string "devices_url" + t.integer "suspension_origin" + t.datetime "sensitized_at" t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id" @@ -372,6 +381,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.boolean "reject_reports", default: false, null: false t.text "private_comment" t.text "public_comment" + t.boolean "obfuscate", default: false, null: false t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true end @@ -425,6 +435,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.bigint "target_account_id", null: false t.boolean "show_reblogs", default: true, null: false t.string "uri" + t.boolean "notify", default: false, null: false t.index ["account_id", "target_account_id"], name: "index_follow_requests_on_account_id_and_target_account_id", unique: true end @@ -435,6 +446,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.bigint "target_account_id", null: false t.boolean "show_reblogs", default: true, null: false t.string "uri" + t.boolean "notify", default: false, null: false t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true t.index ["target_account_id"], name: "index_follows_on_target_account_id" end @@ -475,6 +487,15 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.index ["user_id"], name: "index_invites_on_user_id" end + create_table "ip_blocks", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.datetime "expires_at" + t.inet "ip", default: "0.0.0.0", null: false + t.integer "severity", default: 0, null: false + t.text "comment", default: "", null: false + end + create_table "list_accounts", force: :cascade do |t| t.bigint "list_id", null: false t.bigint "account_id", null: false @@ -489,6 +510,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.string "title", default: "", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "replies_policy", default: 0, null: false t.index ["account_id"], name: "index_lists_on_account_id" end @@ -547,6 +569,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.boolean "hide_notifications", default: true, null: false t.bigint "account_id", null: false t.bigint "target_account_id", null: false + t.datetime "expires_at" t.index ["account_id", "target_account_id"], name: "index_mutes_on_account_id_and_target_account_id", unique: true t.index ["target_account_id"], name: "index_mutes_on_target_account_id" end @@ -558,8 +581,8 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.datetime "updated_at", null: false t.bigint "account_id", null: false t.bigint "from_account_id", null: false - t.index ["account_id", "activity_id", "activity_type"], name: "account_activity", unique: true - t.index ["account_id", "id"], name: "index_notifications_on_account_id_and_id", order: { id: :desc } + t.string "type" + t.index ["account_id", "id", "type"], name: "index_notifications_on_account_id_and_id_and_type", order: { id: :desc } t.index ["activity_id", "activity_type"], name: "index_notifications_on_activity_id_and_activity_type" t.index ["from_account_id"], name: "index_notifications_on_from_account_id" end @@ -716,6 +739,7 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.bigint "target_account_id", null: false t.bigint "assigned_account_id" t.string "uri" + t.boolean "forwarded" t.index ["account_id"], name: "index_reports_on_account_id" t.index ["target_account_id"], name: "index_reports_on_target_account_id" end @@ -901,6 +925,8 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.boolean "approved", default: true, null: false t.string "sign_in_token" t.datetime "sign_in_token_sent_at" + t.string "webauthn_id" + t.inet "sign_up_ip" t.index ["account_id"], name: "index_users_on_account_id" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["created_by_application_id"], name: "index_users_on_created_by_application_id" @@ -930,9 +956,22 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do t.index ["user_id"], name: "index_web_settings_on_user_id", unique: true end + create_table "webauthn_credentials", force: :cascade do |t| + t.string "external_id", null: false + t.string "public_key", null: false + t.string "nickname", null: false + t.bigint "sign_count", default: 0, null: false + t.bigint "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["external_id"], name: "index_webauthn_credentials_on_external_id", unique: true + t.index ["user_id"], name: "index_webauthn_credentials_on_user_id" + end + add_foreign_key "account_aliases", "accounts", on_delete: :cascade add_foreign_key "account_conversations", "accounts", on_delete: :cascade add_foreign_key "account_conversations", "conversations", on_delete: :cascade + add_foreign_key "account_deletion_requests", "accounts", on_delete: :cascade add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade add_foreign_key "account_identity_proofs", "accounts", on_delete: :cascade add_foreign_key "account_migrations", "accounts", column: "target_account_id", on_delete: :nullify @@ -1032,4 +1071,30 @@ ActiveRecord::Schema.define(version: 2020_07_18_225817) do add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade add_foreign_key "web_settings", "users", name: "fk_11910667b2", on_delete: :cascade + add_foreign_key "webauthn_credentials", "users" + + create_view "instances", materialized: true, sql_definition: <<-SQL + WITH domain_counts(domain, accounts_count) AS ( + SELECT accounts.domain, + count(*) AS accounts_count + FROM accounts + WHERE (accounts.domain IS NOT NULL) + GROUP BY accounts.domain + ) + SELECT domain_counts.domain, + domain_counts.accounts_count + FROM domain_counts + UNION + SELECT domain_blocks.domain, + COALESCE(domain_counts.accounts_count, (0)::bigint) AS accounts_count + FROM (domain_blocks + LEFT JOIN domain_counts ON (((domain_counts.domain)::text = (domain_blocks.domain)::text))) + UNION + SELECT domain_allows.domain, + COALESCE(domain_counts.accounts_count, (0)::bigint) AS accounts_count + FROM (domain_allows + LEFT JOIN domain_counts ON (((domain_counts.domain)::text = (domain_allows.domain)::text))); + SQL + add_index "instances", ["domain"], name: "index_instances_on_domain", unique: true + end diff --git a/db/views/instances_v01.sql b/db/views/instances_v01.sql new file mode 100644 index 0000000000000000000000000000000000000000..94acd61a133266aaa70e4020e594872c5bb73960 --- /dev/null +++ b/db/views/instances_v01.sql @@ -0,0 +1,17 @@ +WITH domain_counts(domain, accounts_count) +AS ( + SELECT domain, COUNT(*) as accounts_count + FROM accounts + WHERE domain IS NOT NULL + GROUP BY domain +) +SELECT domain, accounts_count +FROM domain_counts +UNION +SELECT domain_blocks.domain, COALESCE(domain_counts.accounts_count, 0) +FROM domain_blocks +LEFT OUTER JOIN domain_counts ON domain_counts.domain = domain_blocks.domain +UNION +SELECT domain_allows.domain, COALESCE(domain_counts.accounts_count, 0) +FROM domain_allows +LEFT OUTER JOIN domain_counts ON domain_counts.domain = domain_allows.domain diff --git a/lib/chewy/strategy/custom_sidekiq.rb b/lib/chewy/strategy/custom_sidekiq.rb index 3e54326ba8b31b01c76059f7495f0aa54f0b33db..794ae4ed44dc82aa54287f3490ce4743656f6dbb 100644 --- a/lib/chewy/strategy/custom_sidekiq.rb +++ b/lib/chewy/strategy/custom_sidekiq.rb @@ -2,29 +2,10 @@ module Chewy class Strategy - class CustomSidekiq < Base - class Worker - include ::Sidekiq::Worker - - sidekiq_options queue: 'pull' - - def perform(type, ids, options = {}) - options[:refresh] = !Chewy.disable_refresh_async if Chewy.disable_refresh_async - type.constantize.import!(ids, options) - end - end - - def update(type, objects, _options = {}) - return unless Chewy.enabled? - - ids = type.root.id ? Array.wrap(objects) : type.adapter.identify(objects) - - return if ids.empty? - - Worker.perform_async(type.name, ids) + class CustomSidekiq < Sidekiq + def update(_type, _objects, _options = {}) + super if Chewy.enabled? end - - def leave; end end end end diff --git a/lib/cli.rb b/lib/cli.rb index 9162144cc48c5923df5800c07ae0c0594213ca1b..3f1658566b3acced06afcacfbc8a74f94b44b569 100644 --- a/lib/cli.rb +++ b/lib/cli.rb @@ -13,6 +13,8 @@ require_relative 'mastodon/preview_cards_cli' require_relative 'mastodon/cache_cli' require_relative 'mastodon/upgrade_cli' require_relative 'mastodon/email_domain_blocks_cli' +require_relative 'mastodon/ip_blocks_cli' +require_relative 'mastodon/maintenance_cli' require_relative 'mastodon/version' module Mastodon @@ -57,6 +59,12 @@ module Mastodon desc 'email_domain_blocks SUBCOMMAND ...ARGS', 'Manage e-mail domain blocks' subcommand 'email_domain_blocks', Mastodon::EmailDomainBlocksCLI + desc 'ip_blocks SUBCOMMAND ...ARGS', 'Manage IP blocks' + subcommand 'ip_blocks', Mastodon::IpBlocksCLI + + desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities' + subcommand 'maintenance', Mastodon::MaintenanceCLI + option :dry_run, type: :boolean desc 'self-destruct', 'Erase the server from the federation' long_desc <<~LONG_DESC diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 8c91c301358ada62e96f45b7ee2ac1fdfddc9dd8..653bfca3010a07710d2cd59a68e3c17c9aab55fd 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -77,7 +77,7 @@ module Mastodon def create(username) account = Account.new(username: username) password = SecureRandom.hex - user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil) + user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil, bypass_invite_request_check: true) if options[:reattach] account = Account.find_local(username) || Account.new(username: username) @@ -87,7 +87,7 @@ module Mastodon say('Use --force to reattach it anyway and delete the other user') return elsif account.user.present? - account.user.destroy! + DeleteAccountService.new.call(account, reserve_email: false) end end @@ -192,10 +192,69 @@ module Mastodon end say("Deleting user with #{account.statuses_count} statuses, this might take a while...") - SuspendAccountService.new.call(account, reserve_email: false) + DeleteAccountService.new.call(account, reserve_email: false) say('OK', :green) end + option :force, type: :boolean, aliases: [:f], description: 'Override public key check' + desc 'merge FROM TO', 'Merge two remote accounts into one' + long_desc <<-LONG_DESC + Merge two remote accounts specified by their username@domain + into one, whereby the TO account is the one being merged into + and kept, while the FROM one is removed. It is primarily meant + to fix duplicates caused by other servers changing their domain. + + The command by default only works if both accounts have the same + public key to prevent mistakes. To override this, use the --force. + LONG_DESC + def merge(from_acct, to_acct) + username, domain = from_acct.split('@') + from_account = Account.find_remote(username, domain) + + if from_account.nil? || from_account.local? + say("No such account (#{from_acct})", :red) + exit(1) + end + + username, domain = to_acct.split('@') + to_account = Account.find_remote(username, domain) + + if to_account.nil? || to_account.local? + say("No such account (#{to_acct})", :red) + exit(1) + end + + if from_account.public_key != to_account.public_key && !options[:force] + say("Accounts don't have the same public key, might not be duplicates!", :red) + say('Override with --force', :red) + exit(1) + end + + to_account.merge_with!(from_account) + from_account.destroy + + say('OK', :green) + end + + desc 'fix-duplicates', 'Find duplicate remote accounts and merge them' + option :dry_run, type: :boolean + long_desc <<-LONG_DESC + Merge known remote accounts sharing an ActivityPub actor identifier. + + Such duplicates can occur when a remote server admin misconfigures their + domain configuration. + LONG_DESC + def fix_duplicates + Account.remote.select(:uri, 'count(*)').group(:uri).having('count(*) > 1').pluck(:uri).each do |uri| + say("Duplicates found for #{uri}") + begin + ActivityPub::FetchRemoteAccountService.new.call(uri) unless options[:dry_run] + rescue => e + say("Error processing #{uri}: #{e}", :red) + end + end + end + desc 'backup USERNAME', 'Request a backup for a user' long_desc <<-LONG_DESC Request a new backup for an account with a given USERNAME. @@ -245,7 +304,7 @@ module Mastodon end if [404, 410].include?(code) - SuspendAccountService.new.call(account, reserve_username: false) unless options[:dry_run] + DeleteAccountService.new.call(account, reserve_username: false) unless options[:dry_run] 1 else # Touch account even during dry run to avoid getting the account into the window again @@ -325,7 +384,7 @@ module Mastodon end processed, = parallelize_with_progress(Account.local.without_suspended) do |account| - FollowService.new.call(account, target_account) + FollowService.new.call(account, target_account, bypass_limit: true) end say("OK, followed target from #{processed} accounts", :green) @@ -335,7 +394,8 @@ module Mastodon option :verbose, type: :boolean, aliases: [:v] desc 'unfollow ACCT', 'Make all local accounts unfollow account specified by ACCT' def unfollow(acct) - target_account = Account.find_remote(*acct.split('@')) + username, domain = acct.split('@') + target_account = Account.find_remote(username, domain) if target_account.nil? say('No such account', :red) diff --git a/lib/mastodon/domains_cli.rb b/lib/mastodon/domains_cli.rb index 558737c273e818f44020dd9e5591b4b65bed883d..3c2dfd4ec27b7857ae29cb38ab6f7616c01bf676 100644 --- a/lib/mastodon/domains_cli.rb +++ b/lib/mastodon/domains_cli.rb @@ -42,7 +42,7 @@ module Mastodon end processed, = parallelize_with_progress(scope) do |account| - SuspendAccountService.new.call(account, reserve_username: false, skip_side_effects: true) unless options[:dry_run] + DeleteAccountService.new.call(account, reserve_username: false, skip_side_effects: true) unless options[:dry_run] end DomainBlock.where(domain: domains).destroy_all unless options[:dry_run] @@ -53,6 +53,8 @@ module Mastodon custom_emojis_count = custom_emojis.count custom_emojis.destroy_all unless options[:dry_run] + Instance.refresh unless options[:dry_run] + say("Removed #{custom_emojis_count} custom emojis", :green) end @@ -83,7 +85,7 @@ module Mastodon processed = Concurrent::AtomicFixnum.new(0) failed = Concurrent::AtomicFixnum.new(0) start_at = Time.now.to_f - seed = start ? [start] : Account.remote.domains + seed = start ? [start] : Instance.pluck(:domain) blocked_domains = Regexp.new('\\.?' + DomainBlock.where(severity: 1).pluck(:domain).join('|') + '$') progress = create_progress_bar diff --git a/lib/mastodon/email_domain_blocks_cli.rb b/lib/mastodon/email_domain_blocks_cli.rb index 7fe1efaaa5c13043f8f2f8ccb413e1b822fdb20f..55a637d68281c230f1b391dfd18126fb95ad9b33 100644 --- a/lib/mastodon/email_domain_blocks_cli.rb +++ b/lib/mastodon/email_domain_blocks_cli.rb @@ -63,7 +63,7 @@ module Mastodon ips = [] Resolv::DNS.open do |dns| - dns.timeouts = 1 + dns.timeouts = 5 hostnames = dns.getresources(email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s } ([email_domain_block.domain] + hostnames).uniq.each do |hostname| diff --git a/lib/mastodon/emoji_cli.rb b/lib/mastodon/emoji_cli.rb index da8fd6a0dc2b2322e9dbdc1aa8ae0b08b7691a61..0a1f538e6fc27a920712f02bb4cb5671fc87512b 100644 --- a/lib/mastodon/emoji_cli.rb +++ b/lib/mastodon/emoji_cli.rb @@ -43,7 +43,12 @@ module Mastodon tar.each do |entry| next unless entry.file? && entry.full_name.end_with?('.png') - shortcode = [options[:prefix], File.basename(entry.full_name, '.*'), options[:suffix]].compact.join + filename = File.basename(entry.full_name, '.*') + + # Skip macOS shadow files + next if filename.start_with?('._') + + shortcode = [options[:prefix], filename, options[:suffix]].compact.join custom_emoji = CustomEmoji.local.find_by(shortcode: shortcode) if custom_emoji && !options[:overwrite] diff --git a/lib/mastodon/ip_blocks_cli.rb b/lib/mastodon/ip_blocks_cli.rb new file mode 100644 index 0000000000000000000000000000000000000000..5c38c1aca07c91331874d19f9be7dcc934d7029a --- /dev/null +++ b/lib/mastodon/ip_blocks_cli.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +require 'rubygems/package' +require_relative '../../config/boot' +require_relative '../../config/environment' +require_relative 'cli_helper' + +module Mastodon + class IpBlocksCLI < Thor + def self.exit_on_failure? + true + end + + option :severity, required: true, enum: %w(no_access sign_up_requires_approval), desc: 'Severity of the block' + option :comment, aliases: [:c], desc: 'Optional comment' + option :duration, aliases: [:d], type: :numeric, desc: 'Duration of the block in seconds' + option :force, type: :boolean, aliases: [:f], desc: 'Overwrite existing blocks' + desc 'add IP...', 'Add one or more IP blocks' + long_desc <<-LONG_DESC + Add one or more IP blocks. You can use CIDR syntax to + block IP ranges. You must specify --severity of the block. All + options will be copied for each IP block you create in one command. + + You can add a --comment. If an IP block already exists for one of + the provided IPs, it will be skipped unless you use the --force + option to overwrite it. + LONG_DESC + def add(*addresses) + if addresses.empty? + say('No IP(s) given', :red) + exit(1) + end + + skipped = 0 + processed = 0 + failed = 0 + + addresses.each do |address| + ip_block = IpBlock.find_by(ip: address) + + if ip_block.present? && !options[:force] + say("#{address} is already blocked", :yellow) + skipped += 1 + next + end + + ip_block ||= IpBlock.new(ip: address) + + ip_block.severity = options[:severity] + ip_block.comment = options[:comment] if options[:comment].present? + ip_block.expires_in = options[:duration] + + if ip_block.save + processed += 1 + else + say("#{address} could not be saved", :red) + failed += 1 + end + end + + say("Added #{processed}, skipped #{skipped}, failed #{failed}", color(processed, failed)) + end + + option :force, type: :boolean, aliases: [:f], desc: 'Remove blocks for ranges that cover given IP(s)' + desc 'remove IP...', 'Remove one or more IP blocks' + long_desc <<-LONG_DESC + Remove one or more IP blocks. Normally, only exact matches are removed. If + you want to ensure that all of the given IP addresses are unblocked, you + can use --force which will also remove any blocks for IP ranges that would + cover the given IP(s). + LONG_DESC + def remove(*addresses) + if addresses.empty? + say('No IP(s) given', :red) + exit(1) + end + + processed = 0 + skipped = 0 + + addresses.each do |address| + ip_blocks = begin + if options[:force] + IpBlock.where('ip >>= ?', address) + else + IpBlock.where('ip <<= ?', address) + end + end + + if ip_blocks.empty? + say("#{address} is not yet blocked", :yellow) + skipped += 1 + next + end + + ip_blocks.in_batches.destroy_all + processed += 1 + end + + say("Removed #{processed}, skipped #{skipped}", color(processed, 0)) + end + + option :format, aliases: [:f], enum: %w(plain nginx), desc: 'Format of the output' + desc 'export', 'Export blocked IPs' + long_desc <<-LONG_DESC + Export blocked IPs. Different formats are supported for usage with other + tools. Only blocks with no_access severity are returned. + LONG_DESC + def export + IpBlock.where(severity: :no_access).find_each do |ip_block| + case options[:format] + when 'nginx' + puts "deny #{ip_block.ip}/#{ip_block.ip.prefix};" + else + puts "#{ip_block.ip}/#{ip_block.ip.prefix}" + end + end + end + + private + + def color(processed, failed) + if !processed.zero? && failed.zero? + :green + elsif failed.zero? + :yellow + else + :red + end + end + end +end diff --git a/lib/mastodon/maintenance_cli.rb b/lib/mastodon/maintenance_cli.rb new file mode 100644 index 0000000000000000000000000000000000000000..822051ceb879883984a270701c18d9130945bf54 --- /dev/null +++ b/lib/mastodon/maintenance_cli.rb @@ -0,0 +1,618 @@ +# frozen_string_literal: true + +require 'tty-prompt' +require_relative '../../config/boot' +require_relative '../../config/environment' +require_relative 'cli_helper' + +module Mastodon + class MaintenanceCLI < Thor + include CLIHelper + + def self.exit_on_failure? + true + end + + MIN_SUPPORTED_VERSION = 2019_10_01_213028 + MAX_SUPPORTED_VERSION = 2020_12_18_054746 + + # Stubs to enjoy ActiveRecord queries while not depending on a particular + # version of the code/database + + class Status < ApplicationRecord; end + class StatusPin < ApplicationRecord; end + class Poll < ApplicationRecord; end + class Report < ApplicationRecord; end + class Tombstone < ApplicationRecord; end + class Favourite < ApplicationRecord; end + class Follow < ApplicationRecord; end + class FollowRequest < ApplicationRecord; end + class Block < ApplicationRecord; end + class Mute < ApplicationRecord; end + class AccountIdentityProof < ApplicationRecord; end + class AccountModerationNote < ApplicationRecord; end + class AccountPin < ApplicationRecord; end + class ListAccount < ApplicationRecord; end + class PollVote < ApplicationRecord; end + class Mention < ApplicationRecord; end + class AccountDomainBlock < ApplicationRecord; end + class AnnouncementReaction < ApplicationRecord; end + class FeaturedTag < ApplicationRecord; end + class CustomEmoji < ApplicationRecord; end + class CustomEmojiCategory < ApplicationRecord; end + class Bookmark < ApplicationRecord; end + class WebauthnCredential < ApplicationRecord; end + + class PreviewCard < ApplicationRecord + self.inheritance_column = false + end + + class MediaAttachment < ApplicationRecord + self.inheritance_column = nil + end + + class AccountStat < ApplicationRecord + belongs_to :account, inverse_of: :account_stat + end + + # Dummy class, to make migration possible across version changes + class Account < ApplicationRecord + has_one :user, inverse_of: :account + has_one :account_stat, inverse_of: :account + + scope :local, -> { where(domain: nil) } + + def local? + domain.nil? + end + + def acct + local? ? username : "#{username}@#{domain}" + end + + # This is a duplicate of the AccountMerging concern because we need it to + # be independent from code version. + def merge_with!(other_account) + # Since it's the same remote resource, the remote resource likely + # already believes we are following/blocking, so it's safe to + # re-attribute the relationships too. However, during the presence + # of the index bug users could have *also* followed the reference + # account already, therefore mass update will not work and we need + # to check for (and skip past) uniqueness errors + + owned_classes = [ + Status, StatusPin, MediaAttachment, Poll, Report, Tombstone, Favourite, + Follow, FollowRequest, Block, Mute, AccountIdentityProof, + AccountModerationNote, AccountPin, AccountStat, ListAccount, + PollVote, Mention + ] + owned_classes << AccountDeletionRequest if ActiveRecord::Base.connection.table_exists?(:account_deletion_requests) + owned_classes << AccountNote if ActiveRecord::Base.connection.table_exists?(:account_notes) + + owned_classes.each do |klass| + klass.where(account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + target_classes = [Follow, FollowRequest, Block, Mute, AccountModerationNote, AccountPin] + target_classes << AccountNote if ActiveRecord::Base.connection.table_exists?(:account_notes) + + target_classes.each do |klass| + klass.where(target_account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:target_account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + end + end + + class User < ApplicationRecord + belongs_to :account, inverse_of: :user + end + + desc 'fix-duplicates', 'Fix duplicates in database and rebuild indexes' + long_desc <<~LONG_DESC + Delete or merge duplicate accounts, statuses, emojis, etc. and rebuild indexes. + + This is useful if your database indexes are corrupted because of issues such as https://wiki.postgresql.org/wiki/Locale_data_changes + + Mastodon has to be stopped to run this task, which will take a long time and may be destructive. + LONG_DESC + def fix_duplicates + @prompt = TTY::Prompt.new + + if ActiveRecord::Migrator.current_version < MIN_SUPPORTED_VERSION + @prompt.warn 'Your version of the database schema is too old and is not supported by this script.' + @prompt.warn 'Please update to at least Mastodon 3.0.0 before running this script.' + exit(1) + elsif ActiveRecord::Migrator.current_version > MAX_SUPPORTED_VERSION + @prompt.warn 'Your version of the database schema is more recent than this script, this may cause unexpected errors.' + exit(1) unless @prompt.yes?('Continue anyway?') + end + + @prompt.warn 'This task will take a long time to run and is potentially destructive.' + @prompt.warn 'Please make sure to stop Mastodon and have a backup.' + exit(1) unless @prompt.yes?('Continue?') + + deduplicate_accounts! + deduplicate_users! + deduplicate_account_domain_blocks! + deduplicate_account_identity_proofs! + deduplicate_announcement_reactions! + deduplicate_conversations! + deduplicate_custom_emojis! + deduplicate_custom_emoji_categories! + deduplicate_domain_allows! + deduplicate_domain_blocks! + deduplicate_unavailable_domains! + deduplicate_email_domain_blocks! + deduplicate_media_attachments! + deduplicate_preview_cards! + deduplicate_statuses! + deduplicate_tags! + deduplicate_webauthn_credentials! + + Rails.cache.clear + + @prompt.say 'Finished!' + end + + private + + def deduplicate_accounts! + remove_index_if_exists!(:accounts, 'index_accounts_on_username_and_domain_lower') + + @prompt.say 'Deduplicating accounts… for local accounts, you will be asked to chose which account to keep unchanged.' + + find_duplicate_accounts.each do |row| + accounts = Account.where(id: row['ids'].split(',')).to_a + + if accounts.first.local? + deduplicate_local_accounts!(accounts) + else + deduplicate_remote_accounts!(accounts) + end + end + + @prompt.say 'Restoring index_accounts_on_username_and_domain_lower…' + if ActiveRecord::Migrator.current_version < 20200620164023 + ActiveRecord::Base.connection.add_index :accounts, 'lower (username), lower(domain)', name: 'index_accounts_on_username_and_domain_lower', unique: true + else + ActiveRecord::Base.connection.add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true + end + end + + def deduplicate_users! + remove_index_if_exists!(:users, 'index_users_on_confirmation_token') + remove_index_if_exists!(:users, 'index_users_on_email') + remove_index_if_exists!(:users, 'index_users_on_remember_token') + remove_index_if_exists!(:users, 'index_users_on_reset_password_token') + + @prompt.say 'Deduplicating user records…' + + # Deduplicating email + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM users GROUP BY email HAVING count(*) > 1").each do |row| + users = User.where(id: row['ids'].split(',')).sort_by(&:updated_at).reverse + ref_user = users.shift + @prompt.warn "Multiple users registered with e-mail address #{ref_user.email}." + @prompt.warn "e-mail will be disabled for the following accounts: #{user.map(&:account).map(&:acct).join(', ')}" + @prompt.warn 'Please reach out to them and set another address with `tootctl account modify` or delete them.' + + i = 0 + users.each do |user| + user.update!(email: "#{i} " + user.email) + end + end + + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM users WHERE confirmation_token IS NOT NULL GROUP BY confirmation_token HAVING count(*) > 1").each do |row| + users = User.where(id: row['ids'].split(',')).sort_by(&:created_at).reverse.drop(1) + @prompt.warn "Unsetting confirmation token for those accounts: #{users.map(&:account).map(&:acct).join(', ')}" + + users.each do |user| + user.update!(confirmation_token: nil) + end + end + + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM users WHERE remember_token IS NOT NULL GROUP BY remember_token HAVING count(*) > 1").each do |row| + users = User.where(id: row['ids'].split(',')).sort_by(&:updated_at).reverse.drop(1) + @prompt.warn "Unsetting remember token for those accounts: #{users.map(&:account).map(&:acct).join(', ')}" + + users.each do |user| + user.update!(remember_token: nil) + end + end + + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM users WHERE reset_password_token IS NOT NULL GROUP BY reset_password_token HAVING count(*) > 1").each do |row| + users = User.where(id: row['ids'].split(',')).sort_by(&:updated_at).reverse.drop(1) + @prompt.warn "Unsetting password reset token for those accounts: #{users.map(&:account).map(&:acct).join(', ')}" + + users.each do |user| + user.update!(reset_password_token: nil) + end + end + + @prompt.say 'Restoring users indexes…' + ActiveRecord::Base.connection.add_index :users, ['confirmation_token'], name: 'index_users_on_confirmation_token', unique: true + ActiveRecord::Base.connection.add_index :users, ['email'], name: 'index_users_on_email', unique: true + ActiveRecord::Base.connection.add_index :users, ['remember_token'], name: 'index_users_on_remember_token', unique: true + ActiveRecord::Base.connection.add_index :users, ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true + end + + def deduplicate_account_domain_blocks! + remove_index_if_exists!(:account_domain_blocks, 'index_account_domain_blocks_on_account_id_and_domain') + + @prompt.say 'Removing duplicate account domain blocks…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM account_domain_blocks GROUP BY account_id, domain HAVING count(*) > 1").each do |row| + AccountDomainBlock.where(id: row['ids'].split(',').drop(1)).delete_all + end + + @prompt.say 'Restoring account domain blocks indexes…' + ActiveRecord::Base.connection.add_index :account_domain_blocks, ['account_id', 'domain'], name: 'index_account_domain_blocks_on_account_id_and_domain', unique: true + end + + def deduplicate_account_identity_proofs! + remove_index_if_exists!(:account_identity_proofs, 'index_account_proofs_on_account_and_provider_and_username') + + @prompt.say 'Removing duplicate account identity proofs…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM account_identity_proofs GROUP BY account_id, provider, provider_username HAVING count(*) > 1").each do |row| + AccountIdentityProof.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring account identity proofs indexes…' + ActiveRecord::Base.connection.add_index :account_identity_proofs, ['account_id', 'provider', 'provider_username'], name: 'index_account_proofs_on_account_and_provider_and_username', unique: true + end + + def deduplicate_announcement_reactions! + return unless ActiveRecord::Base.connection.table_exists?(:announcement_reactions) + + remove_index_if_exists!(:announcement_reactions, 'index_announcement_reactions_on_account_id_and_announcement_id') + + @prompt.say 'Removing duplicate account identity proofs…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM announcement_reactions GROUP BY account_id, announcement_id, name HAVING count(*) > 1").each do |row| + AnnouncementReaction.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring announcement_reactions indexes…' + ActiveRecord::Base.connection.add_index :announcement_reactions, ['account_id', 'announcement_id', 'name'], name: 'index_announcement_reactions_on_account_id_and_announcement_id', unique: true + end + + def deduplicate_conversations! + remove_index_if_exists!(:conversations, 'index_conversations_on_uri') + + @prompt.say 'Deduplicating conversations…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM conversations WHERE uri IS NOT NULL GROUP BY uri HAVING count(*) > 1").each do |row| + conversations = Conversation.where(id: row['ids'].split(',')).sort_by(&:id).reverse + + ref_conversation = conversations.shift + + conversations.each do |other| + merge_conversations!(ref_conversation, other) + other.destroy + end + end + + @prompt.say 'Restoring conversations indexes…' + ActiveRecord::Base.connection.add_index :conversations, ['uri'], name: 'index_conversations_on_uri', unique: true + end + + def deduplicate_custom_emojis! + remove_index_if_exists!(:custom_emojis, 'index_custom_emojis_on_shortcode_and_domain') + + @prompt.say 'Deduplicating custom_emojis…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM custom_emojis GROUP BY shortcode, domain HAVING count(*) > 1").each do |row| + emojis = CustomEmoji.where(id: row['ids'].split(',')).sort_by(&:id).reverse + + ref_emoji = emojis.shift + + emojis.each do |other| + merge_custom_emojis!(ref_emoji, other) + other.destroy + end + end + + @prompt.say 'Restoring custom_emojis indexes…' + ActiveRecord::Base.connection.add_index :custom_emojis, ['shortcode', 'domain'], name: 'index_custom_emojis_on_shortcode_and_domain', unique: true + end + + def deduplicate_custom_emoji_categories! + remove_index_if_exists!(:custom_emoji_categories, 'index_custom_emoji_categories_on_name') + + @prompt.say 'Deduplicating custom_emoji_categories…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM custom_emoji_categories GROUP BY name HAVING count(*) > 1").each do |row| + categories = CustomEmojiCategory.where(id: row['ids'].split(',')).sort_by(&:id).reverse + + ref_category = categories.shift + + categories.each do |other| + merge_custom_emoji_categories!(ref_category, other) + other.destroy + end + end + + @prompt.say 'Restoring custom_emoji_categories indexes…' + ActiveRecord::Base.connection.add_index :custom_emoji_categories, ['name'], name: 'index_custom_emoji_categories_on_name', unique: true + end + + def deduplicate_domain_allows! + remove_index_if_exists!(:domain_allows, 'index_domain_allows_on_domain') + + @prompt.say 'Deduplicating domain_allows…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM domain_allows GROUP BY domain HAVING count(*) > 1").each do |row| + DomainAllow.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring domain_allows indexes…' + ActiveRecord::Base.connection.add_index :domain_allows, ['domain'], name: 'index_domain_allows_on_domain', unique: true + end + + def deduplicate_domain_blocks! + remove_index_if_exists!(:domain_blocks, 'index_domain_blocks_on_domain') + + @prompt.say 'Deduplicating domain_allows…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM domain_blocks GROUP BY domain HAVING count(*) > 1").each do |row| + domain_blocks = DomainBlock.where(id: row['ids'].split(',')).by_severity.reverse.to_a + + reject_media = domain_blocks.any?(&:reject_media?) + reject_reports = domain_blocks.any?(&:reject_reports?) + + reference_block = domain_blocks.shift + + private_comment = domain_blocks.reduce(reference_block.private_comment.presence) { |a, b| a || b.private_comment.presence } + public_comment = domain_blocks.reduce(reference_block.public_comment.presence) { |a, b| a || b.public_comment.presence } + + reference_block.update!(reject_media: reject_media, reject_reports: reject_reports, private_comment: private_comment, public_comment: public_comment) + + domain_blocks.each(&:destroy) + end + + @prompt.say 'Restoring domain_blocks indexes…' + ActiveRecord::Base.connection.add_index :domain_blocks, ['domain'], name: 'index_domain_blocks_on_domain', unique: true + end + + def deduplicate_unavailable_domains! + return unless ActiveRecord::Base.connection.table_exists?(:unavailable_domains) + + remove_index_if_exists!(:unavailable_domains, 'index_unavailable_domains_on_domain') + + @prompt.say 'Deduplicating unavailable_domains…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM unavailable_domains GROUP BY domain HAVING count(*) > 1").each do |row| + UnavailableDomain.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring domain_allows indexes…' + ActiveRecord::Base.connection.add_index :unavailable_domains, ['domain'], name: 'index_unavailable_domains_on_domain', unique: true + end + + def deduplicate_email_domain_blocks! + remove_index_if_exists!(:email_domain_blocks, 'index_email_domain_blocks_on_domain') + + @prompt.say 'Deduplicating email_domain_blocks…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM email_domain_blocks GROUP BY domain HAVING count(*) > 1").each do |row| + domain_blocks = EmailDomainBlock.where(id: row['ids'].split(',')).sort_by { |b| b.parent.nil? ? 1 : 0 }.to_a + domain_blocks.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring email_domain_blocks indexes…' + ActiveRecord::Base.connection.add_index :email_domain_blocks, ['domain'], name: 'index_email_domain_blocks_on_domain', unique: true + end + + def deduplicate_media_attachments! + remove_index_if_exists!(:media_attachments, 'index_media_attachments_on_shortcode') + + @prompt.say 'Deduplicating media_attachments…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM media_attachments WHERE shortcode IS NOT NULL GROUP BY shortcode HAVING count(*) > 1").each do |row| + MediaAttachment.where(id: row['ids'].split(',').drop(1)).update_all(shortcode: nil) + end + + @prompt.say 'Restoring media_attachments indexes…' + ActiveRecord::Base.connection.add_index :media_attachments, ['shortcode'], name: 'index_media_attachments_on_shortcode', unique: true + end + + def deduplicate_preview_cards! + remove_index_if_exists!(:preview_cards, 'index_preview_cards_on_url') + + @prompt.say 'Deduplicating preview_cards…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM preview_cards GROUP BY url HAVING count(*) > 1").each do |row| + PreviewCard.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring preview_cards indexes…' + ActiveRecord::Base.connection.add_index :preview_cards, ['url'], name: 'index_preview_cards_on_url', unique: true + end + + def deduplicate_statuses! + remove_index_if_exists!(:statuses, 'index_statuses_on_uri') + + @prompt.say 'Deduplicating statuses…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM statuses WHERE uri IS NOT NULL GROUP BY uri HAVING count(*) > 1").each do |row| + statuses = Status.where(id: row['ids'].split(',')).sort_by(&:id) + ref_status = statuses.shift + statuses.each do |status| + merge_statuses!(ref_status, status) if status.account_id == ref_status.account_id + status.destroy + end + end + + @prompt.say 'Restoring statuses indexes…' + ActiveRecord::Base.connection.add_index :statuses, ['uri'], name: 'index_statuses_on_uri', unique: true + end + + def deduplicate_tags! + remove_index_if_exists!(:tags, 'index_tags_on_name_lower') + + @prompt.say 'Deduplicating tags…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM tags GROUP BY lower((name)::text) HAVING count(*) > 1").each do |row| + tags = Tag.where(id: row['ids'].split(',')).sort_by { |t| [t.usable?, t.trendable?, t.listable?].count(false) } + ref_tag = tags.shift + tags.each do |tag| + merge_tags!(ref_tag, tag) + tag.destroy + end + end + + @prompt.say 'Restoring tags indexes…' + ActiveRecord::Base.connection.add_index :tags, 'lower((name)::text)', name: 'index_tags_on_name_lower', unique: true + end + + def deduplicate_webauthn_credentials! + return unless ActiveRecord::Base.connection.table_exists?(:webauthn_credentials) + + remove_index_if_exists!(:webauthn_credentials, 'index_webauthn_credentials_on_external_id') + + @prompt.say 'Deduplicating webauthn_credentials…' + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM webauthn_credentials GROUP BY external_id HAVING count(*) > 1").each do |row| + WebauthnCredential.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy) + end + + @prompt.say 'Restoring webauthn_credentials indexes…' + ActiveRecord::Base.connection.add_index :webauthn_credentials, ['external_id'], name: 'index_webauthn_credentials_on_external_id', unique: true + end + + def deduplicate_local_accounts!(accounts) + accounts = accounts.sort_by(&:id).reverse + + @prompt.warn "Multiple local accounts were found for username '#{accounts.first.username}'." + @prompt.warn 'All those accounts are distinct accounts but only the most recently-created one is fully-functionnal.' + + accounts.each_with_index do |account, idx| + @prompt.say '%2d. %s: created at: %s; updated at: %s; last logged in at: %s; statuses: %5d; last status at: %s' % [idx, account.username, account.created_at, account.updated_at, account.user&.last_sign_in_at&.to_s || 'N/A', account.account_stat&.statuses_count || 0, account.account_stat&.last_status_at || 'N/A'] + end + + @prompt.say 'Please chose the one to keep unchanged, other ones will be automatically renamed.' + + ref_id = @prompt.ask('Account to keep unchanged:') do |q| + q.required true + q.default 0 + q.convert :int + end + + accounts.delete_at(ref_id) + + i = 0 + accounts.each do |account| + i += 1 + username = account.username + "_#{i}" + + while Account.local.exists?(username: username) + i += 1 + username = account.username + "_#{i}" + end + + account.update!(username: username) + end + end + + def deduplicate_remote_accounts!(accounts) + accounts = accounts.sort_by(&:updated_at).reverse + + reference_account = accounts.shift + + accounts.each do |other_account| + if other_account.public_key == reference_account.public_key + # The accounts definitely point to the same resource, so + # it's safe to re-attribute content and relationships + reference_account.merge_with!(other_account) + end + + other_account.destroy + end + end + + def merge_conversations!(main_conv, duplicate_conv) + owned_classes = [ConversationMute, AccountConversation] + owned_classes.each do |klass| + klass.where(conversation_id: duplicate_conv.id).find_each do |record| + begin + record.update_attribute(:account_id, main_conv.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + end + + def merge_custom_emojis!(main_emoji, duplicate_emoji) + owned_classes = [AnnouncementReaction] + owned_classes.each do |klass| + klass.where(custom_emoji_id: duplicate_emoji.id).update_all(custom_emoji_id: main_emoji.id) + end + end + + def merge_custom_emoji_categories!(main_category, duplicate_category) + owned_classes = [CustomEmoji] + owned_classes.each do |klass| + klass.where(category_id: duplicate_category.id).update_all(category_id: main_category.id) + end + end + + def merge_statuses!(main_status, duplicate_status) + owned_classes = [Favourite, Mention, Poll] + owned_classes << Bookmark if ActiveRecord::Base.connection.table_exists?(:bookmarks) + owned_classes.each do |klass| + klass.where(status_id: duplicate_status.id).find_each do |record| + begin + record.update_attribute(:status_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + StatusPin.where(account_id: main_status.account_id, status_id: duplicate_status.id).find_each do |record| + begin + record.update_attribute(:status_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + + Status.where(in_reply_to_id: duplicate_status.id).find_each do |record| + begin + record.update_attribute(:in_reply_to_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + + Status.where(reblog_of_id: duplicate_status.id).find_each do |record| + begin + record.update_attribute(:reblog_of_id, main_status.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + def merge_tags!(main_tag, duplicate_tag) + [FeaturedTag].each do |klass| + klass.where(tag_id: duplicate_tag.id).find_each do |record| + begin + record.update_attribute(:tag_id, main_tag.id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + end + + def find_duplicate_accounts + ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM accounts GROUP BY lower(username), COALESCE(lower(domain), '') HAVING count(*) > 1") + end + + def remove_index_if_exists!(table, name) + ActiveRecord::Base.connection.remove_index(table, name: name) + rescue ArgumentError + nil + rescue ActiveRecord::StatementInvalid + nil + end + end +end diff --git a/lib/mastodon/media_cli.rb b/lib/mastodon/media_cli.rb index 2a4e3e379f3dfa751aa2588a96381ed59995ace4..5f4a414b1a59cee2f0e298c7d7ce0663f7541270 100644 --- a/lib/mastodon/media_cli.rb +++ b/lib/mastodon/media_cli.rb @@ -31,7 +31,7 @@ module Mastodon processed, aggregate = parallelize_with_progress(MediaAttachment.cached.where.not(remote_url: '').where('created_at < ?', time_ago)) do |media_attachment| next if media_attachment.file.blank? - size = media_attachment.file_file_size + (media_attachment.thumbnail_file_size || 0) + size = (media_attachment.file_file_size || 0) + (media_attachment.thumbnail_file_size || 0) unless options[:dry_run] media_attachment.file.destroy @@ -47,6 +47,7 @@ module Mastodon option :start_after option :prefix + option :fix_permissions, type: :boolean, default: false option :dry_run, type: :boolean, default: false desc 'remove-orphans', 'Scan storage and check for files that do not belong to existing media attachments' long_desc <<~LONG_DESC @@ -66,6 +67,7 @@ module Mastodon when :s3 paperclip_instance = MediaAttachment.new.file s3_interface = paperclip_instance.s3_interface + s3_permissions = Paperclip::Attachment.default_options[:s3_permissions] bucket = s3_interface.bucket(Paperclip::Attachment.default_options[:s3_credentials][:bucket]) last_key = options[:start_after] @@ -86,10 +88,12 @@ module Mastodon record_map = preload_records_from_mixed_objects(objects) objects.each do |object| + object.acl.put(acl: s3_permissions) if options[:fix_permissions] && !options[:dry_run] + path_segments = object.key.split('/') path_segments.delete('cache') - if path_segments.size != 7 + unless [7, 10].include?(path_segments.size) progress.log(pastel.yellow("Unrecognized file found: #{object.key}")) next end @@ -133,7 +137,7 @@ module Mastodon path_segments = key.split(File::SEPARATOR) path_segments.delete('cache') - if path_segments.size != 7 + unless [7, 10].include?(path_segments.size) progress.log(pastel.yellow("Unrecognized file found: #{key}")) next end @@ -258,7 +262,7 @@ module Mastodon path_segments = path.split('/')[2..-1] path_segments.delete('cache') - if path_segments.size != 7 + unless [7, 10].include?(path_segments.size) say('Not a media URL', :red) exit(1) end @@ -311,7 +315,7 @@ module Mastodon segments = object.key.split('/') segments.delete('cache') - next if segments.size != 7 + next unless [7, 10].include?(segments.size) model_name = segments.first.classify record_id = segments[2..-2].join.to_i diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb index e9db9122fabaad4a979559b1b620bdbc45dbcf7f..c3c8ff8005d3262244328560c8689ba295bc52b1 100644 --- a/lib/mastodon/redis_config.rb +++ b/lib/mastodon/redis_config.rb @@ -23,7 +23,7 @@ end setup_redis_env_url setup_redis_env_url(:cache, false) -namespace = ENV.fetch('REDIS_NAMESPACE') { nil } +namespace = ENV.fetch('REDIS_NAMESPACE', nil) cache_namespace = namespace ? namespace + '_cache' : 'cache' REDIS_CACHE_PARAMS = { diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 104cb1807a4fd4c65036521499dcc0087cbb32f4..bd0915775411a873732c1957fdf81b9467a59ba8 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def minor - 2 + 3 end def patch @@ -17,7 +17,7 @@ module Mastodon end def flags - 'rc1' + '' end def suffix @@ -33,16 +33,16 @@ module Mastodon end def repository - ENV.fetch('GITHUB_REPOSITORY') { 'tootsuite/mastodon' } + ENV.fetch('GITHUB_REPOSITORY', 'tootsuite/mastodon') end def source_base_url - ENV.fetch('SOURCE_BASE_URL') { "https://github.com/#{repository}" } + ENV.fetch('SOURCE_BASE_URL', "https://github.com/#{repository}") end # specify git tag or commit hash here def source_tag - ENV.fetch('SOURCE_TAG') { nil } + ENV.fetch('SOURCE_TAG', nil) end def source_url diff --git a/lib/paperclip/attachment_extensions.rb b/lib/paperclip/attachment_extensions.rb index 93df0a326f07c57dc5774c14bcd480e47a76e49e..94f7769b65b57c2ecfeb2ca7d72738ab6dc03892 100644 --- a/lib/paperclip/attachment_extensions.rb +++ b/lib/paperclip/attachment_extensions.rb @@ -35,6 +35,27 @@ module Paperclip formats.include?(other_extension.delete('.')) && File.basename(other_filename, other_extension) == File.basename(original_filename, File.extname(original_filename)) end + + def default_url(style_name = default_style) + @url_generator.for_as_default(style_name) + end + + STOPLIGHT_THRESHOLD = 10 + STOPLIGHT_COOLDOWN = 30 + + # We overwrite this method to put a circuit breaker around + # calls to object storage, to stop hitting APIs that are slow + # to respond or don't respond at all and as such minimize the + # impact of object storage outages on application throughput + def save + Stoplight('object-storage') { super }.with_threshold(STOPLIGHT_THRESHOLD).with_cool_off_time(STOPLIGHT_COOLDOWN).with_error_handler do |error, handle| + if error.is_a?(Seahorse::Client::NetworkingError) + handle.call(error) + else + raise error + end + end.run + end end end diff --git a/lib/paperclip/color_extractor.rb b/lib/paperclip/color_extractor.rb index 44fe5ff1dafedb3558a14fb2ed96d426aa5abf20..f850dc067c68c16c1a35e91d952ad89e60d51c4e 100644 --- a/lib/paperclip/color_extractor.rb +++ b/lib/paperclip/color_extractor.rb @@ -5,6 +5,7 @@ require 'mime/types/columnar' module Paperclip class ColorExtractor < Paperclip::Processor MIN_CONTRAST = 3.0 + ACCENT_MIN_CONTRAST = 2.0 FREQUENCY_THRESHOLD = 0.01 def make @@ -26,8 +27,9 @@ module Paperclip foreground_palette.each do |color| distance = ColorDiff.between(background_color, color) + contrast = w3c_contrast(background_color, color) - if distance > max_distance + if distance > max_distance && contrast >= ACCENT_MIN_CONTRAST max_distance = distance max_distance_color = color end @@ -77,8 +79,8 @@ module Paperclip private def w3c_contrast(color1, color2) - luminance1 = (0.2126 * color1.r + 0.7152 * color1.g + 0.0722 * color1.b) + 0.05 - luminance2 = (0.2126 * color2.r + 0.7152 * color2.g + 0.0722 * color2.b) + 0.05 + luminance1 = color1.to_xyz.y * 0.01 + 0.05 + luminance2 = color2.to_xyz.y * 0.01 + 0.05 if luminance1 > luminance2 luminance1 / luminance2 @@ -87,7 +89,7 @@ module Paperclip end end - # rubocop:disable Style/MethodParameterName + # rubocop:disable Naming/MethodParameterName def rgb_to_hsl(r, g, b) r /= 255.0 g /= 255.0 @@ -154,7 +156,7 @@ module Paperclip [(r * 255).round, (g * 255).round, (b * 255).round] end - # rubocop:enable Style/MethodParameterName + # rubocop:enable Naming/MethodParameterName def lighten_or_darken(color, by) hue, saturation, light = rgb_to_hsl(color.r, color.g, color.b) diff --git a/lib/paperclip/media_type_spoof_detector_extensions.rb b/lib/paperclip/media_type_spoof_detector_extensions.rb index 363934d8d1395df9902f2779e6dcf4438315d869..43337cc6884222af8e5b61f4be9a65f71d3aa26b 100644 --- a/lib/paperclip/media_type_spoof_detector_extensions.rb +++ b/lib/paperclip/media_type_spoof_detector_extensions.rb @@ -18,7 +18,7 @@ module Paperclip @type_from_mime_magic ||= begin begin File.open(@file.path) do |file| - MimeMagic.by_magic(file)&.type + MimeMagic.by_magic(file)&.type || '' end rescue Errno::ENOENT '' diff --git a/lib/paperclip/response_with_limit_adapter.rb b/lib/paperclip/response_with_limit_adapter.rb index 7d897b8d672c8825c2e676a721c021f1f65043ba..17a2abd25f2c79af2a80473bdb8a6f5a3760b61b 100644 --- a/lib/paperclip/response_with_limit_adapter.rb +++ b/lib/paperclip/response_with_limit_adapter.rb @@ -16,10 +16,10 @@ module Paperclip private def cache_current_values - @original_filename = filename_from_content_disposition || filename_from_path || 'data' + @original_filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data' @size = @target.response.content_length @tempfile = copy_to_tempfile(@target) - @content_type = @target.response.mime_type || ContentTypeDetector.new(@tempfile.path).detect + @content_type = ContentTypeDetector.new(@tempfile.path).detect end def copy_to_tempfile(source) diff --git a/lib/paperclip/url_generator_extensions.rb b/lib/paperclip/url_generator_extensions.rb index 1079efdbc4f231b7a3f4b07faf56be8c6037d4bb..e1d6df2c299cdeaf5abb332f741d1dc67db4038b 100644 --- a/lib/paperclip/url_generator_extensions.rb +++ b/lib/paperclip/url_generator_extensions.rb @@ -11,6 +11,10 @@ module Paperclip Addressable::URI.parse(url).normalize.to_str.gsub(escape_regex) { |m| "%#{m.ord.to_s(16).upcase}" } end end + + def for_as_default(style_name) + attachment_options[:interpolator].interpolate(default_url, @attachment, style_name) + end end end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index b76e90131f210ff4227ffca696902b25df012c60..f6c9c7eecfc21f5415447e1edf390674b2ed64bc 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -48,6 +48,20 @@ namespace :db do end end + task :post_migration_hook do + at_exit do + unless %w(C POSIX).include?(ActiveRecord::Base.connection.execute('SELECT datcollate FROM pg_database WHERE datname = current_database();').first['datcollate']) + warn <<~WARNING + Your database collation is susceptible to index corruption. + (This warning does not indicate that index corruption has occured and can be ignored) + (To learn more, visit: https://docs.joinmastodon.org/admin/troubleshooting/index-corruption/) + WARNING + end + end + end + + Rake::Task['db:migrate'].enhance(['db:post_migration_hook']) + # Before we load the schema, define the timestamp_id function. # Idiomatically, we might do this in a migration, but then it # wouldn't end up in schema.rb, so we'd need to figure out a way to diff --git a/lib/tasks/emojis.rake b/lib/tasks/emojis.rake index 0e7921ffc994b641242f015dc658a2c03cc6b2ac..d0b8fa890b3e0eda09a7ec26e6182d04701947c0 100644 --- a/lib/tasks/emojis.rake +++ b/lib/tasks/emojis.rake @@ -91,7 +91,7 @@ namespace :emojis do desc 'Generate emoji variants with white borders' task :generate_borders do src = Rails.root.join('app', 'javascript', 'mastodon', 'features', 'emoji', 'emoji_map.json') - emojis = '🎱ðŸœâš«ðŸ–¤â¬›â—¼ï¸â—¾â—¼ï¸âœ’ï¸â–ªï¸ðŸ’£ðŸŽ³ðŸ“·ðŸ“¸â™£ï¸ðŸ•¶ï¸âœ´ï¸ðŸ”ŒðŸ’‚â€â™€ï¸ðŸ“½ï¸ðŸ³ðŸ¦ðŸ’‚🔪🕳ï¸ðŸ•¹ï¸ðŸ•‹ðŸ–Šï¸ðŸ–‹ï¸ðŸ’‚â€â™‚ï¸ðŸŽ¤ðŸŽ“🎥🎼♠ï¸ðŸŽ©ðŸ¦ƒðŸ“¼ðŸ“¹ðŸŽ®ðŸƒðŸ´ðŸ‘½âš¾ðŸ”â˜ï¸ðŸ’¨ðŸ•Šï¸ðŸ‘€ðŸ¥ðŸ‘»ðŸâ•â”⛸ï¸ðŸŒ©ï¸ðŸ”ŠðŸ”‡ðŸ“ƒðŸŒ§ï¸ðŸðŸšðŸ™ðŸ“ðŸ‘💀☠ï¸ðŸŒ¨ï¸ðŸ”‰ðŸ”ˆðŸ’¬ðŸ’ðŸðŸ³ï¸âšªâ¬œâ—½â—»ï¸â–«ï¸' + emojis = '🎱ðŸœâš«ðŸ–¤â¬›â—¼ï¸â—¾â—¼ï¸âœ’ï¸â–ªï¸ðŸ’£ðŸŽ³ðŸ“·ðŸ“¸â™£ï¸ðŸ•¶ï¸âœ´ï¸ðŸ”ŒðŸ’‚â€â™€ï¸ðŸ“½ï¸ðŸ³ðŸ¦ðŸ’‚🔪🕳ï¸ðŸ•¹ï¸ðŸ•‹ðŸ–Šï¸ðŸ–‹ï¸ðŸ’‚â€â™‚ï¸ðŸŽ¤ðŸŽ“🎥🎼♠ï¸ðŸŽ©ðŸ¦ƒðŸ“¼ðŸ“¹ðŸŽ®ðŸƒðŸ´ðŸžðŸ•ºðŸ‘½âš¾ðŸ”â˜ï¸ðŸ’¨ðŸ•Šï¸ðŸ‘€ðŸ¥ðŸ‘»ðŸâ•â”⛸ï¸ðŸŒ©ï¸ðŸ”ŠðŸ”‡ðŸ“ƒðŸŒ§ï¸ðŸðŸšðŸ™ðŸ“ðŸ‘💀☠ï¸ðŸŒ¨ï¸ðŸ”‰ðŸ”ˆðŸ’¬ðŸ’ðŸðŸ³ï¸âšªâ¬œâ—½â—»ï¸â–«ï¸' map = Oj.load(File.read(src)) diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 9e80989ef0114194dd10386175844434c648f990..2ad1e778ba34cf0de2bf254eb74b6007b90e8ff1 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -412,7 +412,7 @@ namespace :mastodon do password = SecureRandom.hex(16) - user = User.new(admin: true, email: email, password: password, confirmed_at: Time.now.utc, account_attributes: { username: username }) + user = User.new(admin: true, email: email, password: password, confirmed_at: Time.now.utc, account_attributes: { username: username }, bypass_invite_request_check: true) user.save(validate: false) prompt.ok "You can login with the password: #{password}" diff --git a/lib/webpacker/helper_extensions.rb b/lib/webpacker/helper_extensions.rb new file mode 100644 index 0000000000000000000000000000000000000000..8f46d763132b5d78aee93da580b884641283f4c2 --- /dev/null +++ b/lib/webpacker/helper_extensions.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Webpacker::HelperExtensions + def javascript_pack_tag(name, **options) + src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :javascript, with_integrity: true) + javascript_include_tag(src, options.merge(integrity: integrity)) + end + + def stylesheet_pack_tag(name, **options) + src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :stylesheet, with_integrity: true) + stylesheet_link_tag(src, options.merge(integrity: integrity)) + end + + def preload_pack_asset(name, **options) + src, integrity = current_webpacker_instance.manifest.lookup!(name, with_integrity: true) + preload_link_tag(src, options.merge(integrity: integrity)) + end +end + +Webpacker::Helper.prepend(Webpacker::HelperExtensions) diff --git a/lib/webpacker/manifest_extensions.rb b/lib/webpacker/manifest_extensions.rb new file mode 100644 index 0000000000000000000000000000000000000000..789eb81ccf31735cd59ec03ba64592f2661293b0 --- /dev/null +++ b/lib/webpacker/manifest_extensions.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Webpacker::ManifestExtensions + def lookup(name, pack_type = {}) + asset = super + + if pack_type[:with_integrity] && asset.respond_to?(:dig) + [asset.dig('src'), asset.dig('integrity')] + elsif asset.respond_to?(:dig) + asset.dig('src') + else + asset + end + end +end + +Webpacker::Manifest.prepend(Webpacker::ManifestExtensions) diff --git a/package.json b/package.json index 37c6d97d3c753b8e8e585eb7b866ce8936fc8183..30926b651dbec4ea5f6bca6f1487b7af66953932 100644 --- a/package.json +++ b/package.json @@ -59,22 +59,23 @@ }, "private": true, "dependencies": { - "@babel/core": "^7.10.3", + "@babel/core": "^7.12.10", "@babel/plugin-proposal-class-properties": "^7.8.3", - "@babel/plugin-proposal-decorators": "^7.10.3", - "@babel/plugin-transform-react-inline-elements": "^7.10.4", - "@babel/plugin-transform-runtime": "^7.10.4", - "@babel/preset-env": "^7.10.4", - "@babel/preset-react": "^7.10.4", - "@babel/runtime": "^7.8.4", - "@clusterws/cws": "^2.0.0", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-transform-react-inline-elements": "^7.12.1", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/runtime": "^7.12.5", + "@clusterws/cws": "^3.0.0", "@gamestdio/websocket": "^0.3.2", - "@rails/ujs": "^6.0.3", - "array-includes": "^3.1.1", + "@github/webauthn-json": "^0.5.7", + "@rails/ujs": "^6.1.0", + "array-includes": "^3.1.2", "arrow-key-navigation": "^1.2.0", - "autoprefixer": "^9.8.0", - "axios": "^0.19.2", - "babel-loader": "^8.1.0", + "autoprefixer": "^9.8.6", + "axios": "^0.21.1", + "babel-loader": "^8.2.2", "babel-plugin-lodash": "^3.3.4", "babel-plugin-preval": "^5.0.0", "babel-plugin-react-intl": "^6.2.0", @@ -82,40 +83,40 @@ "babel-runtime": "^6.26.0", "blurhash": "^1.1.3", "classnames": "^2.2.5", - "compression-webpack-plugin": "^4.0.0", - "copy-webpack-plugin": "^6.0.2", - "cross-env": "^7.0.2", - "css-loader": "^3.6.0", + "color-blend": "^3.0.1", + "compression-webpack-plugin": "^6.1.1", + "cross-env": "^7.0.3", + "css-loader": "^5.0.1", "cssnano": "^4.1.10", - "detect-passive-events": "^1.0.2", + "detect-passive-events": "^2.0.2", "dotenv": "^8.2.0", "emoji-mart": "Gargron/emoji-mart#build", "es6-symbol": "^3.1.3", "escape-html": "^1.0.3", "exif-js": "^2.3.0", "express": "^4.17.1", - "file-loader": "^6.0.0", + "file-loader": "^6.2.0", "font-awesome": "^4.7.0", "glob": "^7.1.6", "history": "^4.10.1", - "http-link-header": "^1.0.2", + "http-link-header": "^1.0.3", "immutable": "^3.8.2", - "imports-loader": "^0.8.0", - "intersection-observer": "^0.10.0", + "imports-loader": "^1.2.0", + "intersection-observer": "^0.12.0", "intl": "^1.2.5", "intl-messageformat": "^2.2.0", "intl-relativeformat": "^6.4.3", - "is-nan": "^1.3.0", - "js-yaml": "^3.13.1", + "is-nan": "^1.3.2", + "js-yaml": "^4.0.0", "lodash": "^4.17.19", "mark-loader": "^0.1.6", "marky": "^1.2.1", - "mini-css-extract-plugin": "^0.9.0", + "mini-css-extract-plugin": "^1.3.3", "mkdirp": "^1.0.4", "npmlog": "^4.1.2", "object-assign": "^4.1.1", "object-fit-images": "^3.2.3", - "object.values": "^1.1.1", + "object.values": "^1.1.2", "offline-plugin": "^5.0.7", "path-complete-extname": "^1.0.0", "pg": "^6.4.0", @@ -124,8 +125,8 @@ "promise.prototype.finally": "^3.1.2", "prop-types": "^15.5.10", "punycode": "^2.1.0", - "react": "^16.13.1", - "react-dom": "^16.13.1", + "react": "^16.14.0", + "react-dom": "^16.14.0", "react-hotkeys": "^1.1.4", "react-immutable-proptypes": "^2.2.0", "react-immutable-pure-component": "^2.2.2", @@ -133,58 +134,59 @@ "react-masonry-infinite": "^1.2.2", "react-motion": "^0.5.2", "react-notification": "^6.8.5", - "react-overlays": "^0.9.1", - "react-redux": "^7.2.0", + "react-overlays": "^0.9.3", + "react-redux": "^7.2.2", "react-redux-loading-bar": "^4.0.8", "react-router-dom": "^4.1.1", "react-router-scroll-4": "^1.0.0-beta.1", - "react-select": "^3.1.0", + "react-select": "^3.1.1", "react-sparklines": "^1.7.0", "react-swipeable-views": "^0.13.9", - "react-textarea-autosize": "^8.1.1", + "react-textarea-autosize": "^8.3.0", "react-toggle": "^4.1.1", "redis": "^3.0.2", "redux": "^4.0.5", "redux-immutable": "^4.0.0", "redux-thunk": "^2.2.0", + "regenerator-runtime": "^0.13.7", "rellax": "^1.12.1", "requestidlecallback": "^0.3.0", "reselect": "^4.0.0", "rimraf": "^3.0.2", - "sass": "^1.26.8", - "sass-loader": "^8.0.2", + "sass": "^1.32.0", + "sass-loader": "^10.1.0", "stacktrace-js": "^2.0.2", "stringz": "^2.1.0", "substring-trie": "^1.0.2", - "terser-webpack-plugin": "^3.0.6", - "tesseract.js": "2.0.0-alpha.16", + "terser-webpack-plugin": "^4.2.3", + "tesseract.js": "^2.1.1", "throng": "^4.0.0", "tiny-queue": "^0.2.1", - "uuid": "^8.2.0", - "webpack": "^4.43.0", + "uuid": "^8.3.1", + "webpack": "^4.44.2", "webpack-assets-manifest": "^3.1.1", - "webpack-bundle-analyzer": "^3.8.0", + "webpack-bundle-analyzer": "^4.3.0", "webpack-cli": "^3.3.12", - "webpack-merge": "^4.2.1", - "wicg-inert": "^3.0.3" + "webpack-merge": "^5.7.3", + "wicg-inert": "^3.1.0" }, "devDependencies": { - "@testing-library/jest-dom": "^5.11.0", - "@testing-library/react": "^10.4.3", + "@testing-library/jest-dom": "^5.11.8", + "@testing-library/react": "^11.2.2", "babel-eslint": "^10.1.0", - "babel-jest": "^26.1.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "~2.21.2", - "eslint-plugin-jsx-a11y": "~6.3.1", + "babel-jest": "^26.6.3", + "eslint": "^7.17.0", + "eslint-plugin-import": "~2.22.1", + "eslint-plugin-jsx-a11y": "~6.4.1", "eslint-plugin-promise": "~4.2.1", - "eslint-plugin-react": "~7.20.0", - "jest": "^26.0.1", + "eslint-plugin-react": "~7.22.0", + "jest": "^26.6.3", "raf": "^3.4.1", "react-intl-translations-manager": "^5.0.3", - "react-test-renderer": "^16.13.1", + "react-test-renderer": "^16.14.0", "sass-lint": "^1.13.1", - "webpack-dev-server": "^3.11.0", - "yargs": "^15.4.0" + "webpack-dev-server": "^3.11.1", + "yargs": "^16.2.0" }, "resolutions": { "kind-of": "^6.0.3" diff --git a/public/emoji/1f41e_border.svg b/public/emoji/1f41e_border.svg new file mode 100644 index 0000000000000000000000000000000000000000..5d4b1e3d7b35c29eeacf0b6e086912d7ed7a3156 --- /dev/null +++ b/public/emoji/1f41e_border.svg @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 40 40"> + <g> + <path d="M35 21H1c-.552 0-1-.447-1-1s.448-1 1-1h34c.553 0 1 .447 1 1s-.447 1-1 1zm-22.177-2l-.069-.002c-.092-.007-9.214-.714-10.734-8.235-.109-.542.241-1.069.782-1.178.543-.113 1.069.241 1.178.782 1.221 6.044 8.833 6.631 8.91 6.636.551.038.967.515.93 1.066-.036.527-.476.931-.997.931zM3 31c-.142 0-.286-.03-.423-.094-.5-.234-.716-.829-.482-1.33 3.166-6.77 11.038-7.721 11.372-7.758.548-.056 1.042.334 1.103.882.062.548-.332 1.043-.88 1.106-.071.008-7.099.876-9.783 6.617-.171.364-.532.577-.907.577zm19.753-12c-.522 0-.961-.405-.996-.934-.036-.551.381-1.027.931-1.064.081-.005 8.116-.617 9.332-6.636.108-.541.633-.895 1.179-.782.541.109.892.637.782 1.178-1.521 7.525-10.769 8.21-11.162 8.235l-.066.003zm10.248 12c-.377 0-.737-.213-.907-.576-2.694-5.763-10.124-6.609-10.198-6.617-.55-.058-.948-.55-.89-1.099.058-.55.555-.952 1.099-.89.352.037 8.634.983 11.802 7.758.233.501.018 1.096-.482 1.33-.139.064-.282.094-.424.094z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M24.989 7.766c-.069-2.626-1.277-4.216-3.095-5.04C21.961 2.5 22 2.257 22 2c0-1.105-.672-2-1.5-2S19 .895 19 2c0 .015.003.028.003.043C18.675 2.017 18.342 2 18 2s-.675.017-1.003.043c0-.015.003-.028.003-.043 0-1.105-.671-2-1.5-2S14 .895 14 2c0 .257.04.5.106.726-1.817.824-3.025 2.414-3.095 5.04C7.98 9.551 6 12.662 6 17c0 7.159 5.373 16.923 12 16.923 6.628 0 12-9.764 12-16.923 0-4.338-1.98-7.45-5.011-9.234z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M16.001 34.959C9.564 34.364 4.5 28.064 4.5 20.378 4.5 12.693 9.564 9.597 16 9c.33-.03 1-.046 1 2.294v22.541c0 1.171-.669 1.156-.999 1.124zm3.998 0c6.436-.595 11.501-6.895 11.501-14.581C31.5 12.693 26.435 9.597 20 9c-.33-.03-1-.046-1 2.294v22.541c0 1.171.67 1.156.999 1.124z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <g stroke="white" stroke-linejoin="round" stroke-width="4px"> + <circle cx="13" cy="15" r="2"/> + <circle cx="10" cy="22" r="3"/> + <circle cx="13" cy="29" r="2"/> + <circle cx="24.5" cy="14.5" r="2.5"/> + <circle cx="22.5" cy="20.5" r="1.5"/> + <circle cx="28" cy="23" r="2"/> + <circle cx="24" cy="29" r="3"/> + </g> + </g> + <path d="M35 21H1c-.552 0-1-.447-1-1s.448-1 1-1h34c.553 0 1 .447 1 1s-.447 1-1 1zm-22.177-2l-.069-.002c-.092-.007-9.214-.714-10.734-8.235-.109-.542.241-1.069.782-1.178.543-.113 1.069.241 1.178.782 1.221 6.044 8.833 6.631 8.91 6.636.551.038.967.515.93 1.066-.036.527-.476.931-.997.931zM3 31c-.142 0-.286-.03-.423-.094-.5-.234-.716-.829-.482-1.33 3.166-6.77 11.038-7.721 11.372-7.758.548-.056 1.042.334 1.103.882.062.548-.332 1.043-.88 1.106-.071.008-7.099.876-9.783 6.617-.171.364-.532.577-.907.577zm19.753-12c-.522 0-.961-.405-.996-.934-.036-.551.381-1.027.931-1.064.081-.005 8.116-.617 9.332-6.636.108-.541.633-.895 1.179-.782.541.109.892.637.782 1.178-1.521 7.525-10.769 8.21-11.162 8.235l-.066.003zm10.248 12c-.377 0-.737-.213-.907-.576-2.694-5.763-10.124-6.609-10.198-6.617-.55-.058-.948-.55-.89-1.099.058-.55.555-.952 1.099-.89.352.037 8.634.983 11.802 7.758.233.501.018 1.096-.482 1.33-.139.064-.282.094-.424.094z" fill="#31373D"/> + <path fill="#31373D" d="M24.989 7.766c-.069-2.626-1.277-4.216-3.095-5.04C21.961 2.5 22 2.257 22 2c0-1.105-.672-2-1.5-2S19 .895 19 2c0 .015.003.028.003.043C18.675 2.017 18.342 2 18 2s-.675.017-1.003.043c0-.015.003-.028.003-.043 0-1.105-.671-2-1.5-2S14 .895 14 2c0 .257.04.5.106.726-1.817.824-3.025 2.414-3.095 5.04C7.98 9.551 6 12.662 6 17c0 7.159 5.373 16.923 12 16.923 6.628 0 12-9.764 12-16.923 0-4.338-1.98-7.45-5.011-9.234z"/> + <path fill="#DD2E44" d="M16.001 34.959C9.564 34.364 4.5 28.064 4.5 20.378 4.5 12.693 9.564 9.597 16 9c.33-.03 1-.046 1 2.294v22.541c0 1.171-.669 1.156-.999 1.124zm3.998 0c6.436-.595 11.501-6.895 11.501-14.581C31.5 12.693 26.435 9.597 20 9c-.33-.03-1-.046-1 2.294v22.541c0 1.171.67 1.156.999 1.124z"/> + <g fill="#31373D"> + <circle cx="13" cy="15" r="2"/> + <circle cx="10" cy="22" r="3"/> + <circle cx="13" cy="29" r="2"/> + <circle cx="24.5" cy="14.5" r="2.5"/> + <circle cx="22.5" cy="20.5" r="1.5"/> + <circle cx="28" cy="23" r="2"/> + <circle cx="24" cy="29" r="3"/> + </g> +</svg> diff --git a/public/emoji/1f57a_border.svg b/public/emoji/1f57a_border.svg new file mode 100644 index 0000000000000000000000000000000000000000..7d3729976cfa0d94ad71edf104e446e1844ed98e --- /dev/null +++ b/public/emoji/1f57a_border.svg @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 40 40"> + <g> + <path d="M26.157 35.26c-.005-.034-.055-.214-.055-.214l-.057.027.004-.134c-.021-.58-.608-.51-.678-.516-.07-.006-.305.006-.596-.031-.29-.037-.57-.108-.816-.257-.287-.174-.678-.467-1.014-.663s-.758-.437-.758-.437-.367.682-1.127.654c-.409-.015-1.05-.337-1.133-.36-.11-.031-.159.031-.205.116-.046.086-.211.684-.211 1.005 0 .204.025.333.044.405l-.055-.017c-.025-.007-.049.012-.049.039v.687c0 .045.037.147.155.171.118.024 1.759.165 1.821.11s.13-.232.183-.257c.053-.024.603.094.859.155s.698.165 1.218.165 1.191-.153 1.607-.257c.415-.104.741-.243.815-.289.074-.046.053-.067.048-.102z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M21.19 35.405l-.41-.287c.008-.013.829-1.147 2.439-.666.092-.126.23-.324.363-.544l.428.26c-.24.396-.491.718-.501.731l-.111.142-.17-.061c-1.379-.491-2.031.415-2.038.425z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M14.268 35.26c-.005-.034-.055-.214-.055-.214l-.057.027.004-.134c-.021-.58-.608-.51-.678-.516-.07-.006-.305.006-.596-.031s-.57-.108-.816-.257c-.287-.174-.678-.467-1.014-.663s-.758-.437-.758-.437-.367.682-1.127.654c-.409-.015-1.05-.337-1.133-.36-.11-.031-.159.031-.205.116-.046.086-.211.684-.211 1.005 0 .204.025.333.044.405l-.055-.017c-.025-.007-.049.012-.049.039v.687c0 .045.037.147.155.171.118.024 1.759.165 1.821.11s.13-.232.183-.257c.053-.024.603.094.859.155s.698.165 1.218.165 1.191-.153 1.607-.257c.415-.104.741-.243.815-.289.073-.046.053-.067.048-.102z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M9.3 35.406l-.409-.288c.008-.012.823-1.149 2.439-.666.091-.126.23-.324.363-.544l.428.26c-.24.396-.491.718-.501.731l-.111.142-.17-.061c-1.366-.488-2.012.388-2.039.426z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M28.658 1.816c-.19-.089-.279.102-.279.102l-.378.812c.007-.014-.083-.071-.077-.082l.56-1.201s.089-.19-.102-.279-.279.102-.279.102l-.054.115-.472 1.013c.001-.003-.093-.049-.092-.051l.622-1.336s.089-.19-.102-.279c-.19-.089-.279.102-.279.102l-.622 1.336c-.001.002-.097-.039-.099-.036l.515-1.106s.089-.19-.102-.279c-.19-.089-.279.102-.279.102l-.702 1.507c-.048.103-.139.105-.179.078-.106-.072-.05-.26-.079-.424-.045-.25-.196-.415-.355-.418-.176-.003-.206.138-.192.187.028.095.073.254.126.506.037.177-.017.324-.017.324-.023.072-.085.318-.038.604.028.169.092.352.205.52l-.332.714 1.507.659.366-.956c.267-.119.5-.319.633-.604l.044-.095.631-1.355c.003-.004.091-.194-.099-.282z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M26.348 2.443c.04-.012.06-.036.075-.058.168.108.389.272.491.543.132.351.054.627-.028.798-.066.138-.172.168-.099-.047.092-.27.143-.866-.455-1.205l-.055-.03c.001 0 .037.009.071-.001z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M11.397 20.373c-.076-.064-.202-.171-.385-.352-.129-.128-.165-.279-.165-.279-.021-.073-.105-.312-.303-.524-.117-.126-.271-.243-.459-.319l-.116-.779-1.62.284.224.999c-.156.247-.24.542-.193.854l.016.104.224 1.478s.031.207.239.176.176-.239.176-.239L8.9 20.89c.002.015.108.013.11.026l.198 1.31s.031.207.239.176c.207-.031.176-.239.176-.239l-.019-.126-.167-1.105c0 .003.104-.01.105-.009l.221 1.457s.031.207.239.176c.207-.031.176-.239.176-.239l-.22-1.457c0-.002.103-.021.102-.024l.182 1.206s.031.207.239.176c.207-.031.176-.239.176-.239l-.249-1.644c-.017-.112.057-.165.106-.164.128.001.185.189.3.309.176.183.393.237.527.152.148-.092.095-.227.056-.259z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M25.814 3.729S23.755 8.05 23.512 8.19c-.219.126-1.719-.042-3.699.354-1.979.396-2.744-.155-4.769-.075-1.176.046-2.413.452-3.227.648-1.237.299-3.276 3.237-3.848 4.26-.443.791-.421 1.68-.327 2.372.078.578.058 1.486.82 3.41l1.719-.281s-.289-3.783-.043-4.192c.102-.169 1.323-2.119 2.303-2.473l8.188-.385s3.375-.485 4.302-1.167c.708-.521 2.497-6.251 2.497-6.251l-1.614-.681z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M15.546 5.857c.175-.172.407-.289.671-.314.613-.064 1.16.383 1.222.997l.319 3.153c.061.611-.384 1.16-.997 1.221-.615.063-1.161-.384-1.222-.997l-.32-3.153c-.035-.35.095-.676.327-.907z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M19.243 4.296c0 1.849-1.309 3.348-2.927 3.348s-2.929-1.499-2.929-3.348c0-1.848 1.311-3.347 2.929-3.347 1.618 0 2.927 1.499 2.927 3.347z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M17.89 2.018s-1.14 1.07-2.349 1.255c0 0-.723 1.171-.768 1.847 0 0-.45-1.081-.81-.9-.36.18-.496.855-.18 1.305.315.451.705 1.226.363 1.003-.689-.45-.79-.768-.976-1.07-.127-.206-.425-.943-.465-2.162-.024-.721.232-2.116 1.707-2.857 1.278-.644 3.287-.315 4.231.359.945.676 1.18 2.38.594 3.056 0 0-.085-.63-.488-1.14-.226-.283-.859-.696-.859-.696z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M12.407 9.474v9.253l7.083-.024s.625-2.703 1.034-4.549c.474-2.135-1.079-5.392-1.079-5.392l-1.082-.108-.212-1.011-1.056.4-.151 1.751-.456-1.666-1.548-.135-.184 1.067-2.349.414z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + <path d="M11.781 9.593s.688 2.443.385 7.5c2.228-.038 3.963-.732 3.963-.732s.146-1.919-.228-3.615c-.546-2.469-1.105-3.921-1.105-3.921l-3.015.768zm6.516-1.246s.623 3.271.484 5.224c-.14 1.953-.235 2.694-.235 2.694s.441.486 1.57.466c.467-1.222.752-3.679.695-5.183-.059-1.585-1.002-3.127-1.002-3.127l-1.512-.074zm-5.89 10.38s-.607 6.995-.982 8.307c-.334 1.168-3.799 6.742-3.799 6.742s1.646.406 3.229.094c0 0 3.163-3.836 3.99-5.688.24-.539 1.835-5.521 1.835-5.521s1.712 1.908 2.863 3.599c.728 2.003.09 7.442.09 7.442s1.483.312 2.899.042c0 0 .859-5.397.651-7.688-.033-.367-.103-1.05-.245-1.309-.619-1.123-1.963-3.231-2.822-4.172-.774-.847-.625-1.873-.625-1.873l-7.084.025z" stroke="white" stroke-linejoin="round" stroke-width="4px"/> + </g> + <path fill="#292F33" d="M26.157 35.26c-.005-.034-.055-.214-.055-.214l-.057.027.004-.134c-.021-.58-.608-.51-.678-.516-.07-.006-.305.006-.596-.031-.29-.037-.57-.108-.816-.257-.287-.174-.678-.467-1.014-.663s-.758-.437-.758-.437-.367.682-1.127.654c-.409-.015-1.05-.337-1.133-.36-.11-.031-.159.031-.205.116-.046.086-.211.684-.211 1.005 0 .204.025.333.044.405l-.055-.017c-.025-.007-.049.012-.049.039v.687c0 .045.037.147.155.171.118.024 1.759.165 1.821.11s.13-.232.183-.257c.053-.024.603.094.859.155s.698.165 1.218.165 1.191-.153 1.607-.257c.415-.104.741-.243.815-.289.074-.046.053-.067.048-.102z"/> + <path fill="#4B545D" d="M21.19 35.405l-.41-.287c.008-.013.829-1.147 2.439-.666.092-.126.23-.324.363-.544l.428.26c-.24.396-.491.718-.501.731l-.111.142-.17-.061c-1.379-.491-2.031.415-2.038.425z"/> + <path fill="#292F33" d="M14.268 35.26c-.005-.034-.055-.214-.055-.214l-.057.027.004-.134c-.021-.58-.608-.51-.678-.516-.07-.006-.305.006-.596-.031s-.57-.108-.816-.257c-.287-.174-.678-.467-1.014-.663s-.758-.437-.758-.437-.367.682-1.127.654c-.409-.015-1.05-.337-1.133-.36-.11-.031-.159.031-.205.116-.046.086-.211.684-.211 1.005 0 .204.025.333.044.405l-.055-.017c-.025-.007-.049.012-.049.039v.687c0 .045.037.147.155.171.118.024 1.759.165 1.821.11s.13-.232.183-.257c.053-.024.603.094.859.155s.698.165 1.218.165 1.191-.153 1.607-.257c.415-.104.741-.243.815-.289.073-.046.053-.067.048-.102z"/> + <path fill="#4B545D" d="M9.3 35.406l-.409-.288c.008-.012.823-1.149 2.439-.666.091-.126.23-.324.363-.544l.428.26c-.24.396-.491.718-.501.731l-.111.142-.17-.061c-1.366-.488-2.012.388-2.039.426z"/> + <path fill="#FFDC5D" d="M28.658 1.816c-.19-.089-.279.102-.279.102l-.378.812c.007-.014-.083-.071-.077-.082l.56-1.201s.089-.19-.102-.279-.279.102-.279.102l-.054.115-.472 1.013c.001-.003-.093-.049-.092-.051l.622-1.336s.089-.19-.102-.279c-.19-.089-.279.102-.279.102l-.622 1.336c-.001.002-.097-.039-.099-.036l.515-1.106s.089-.19-.102-.279c-.19-.089-.279.102-.279.102l-.702 1.507c-.048.103-.139.105-.179.078-.106-.072-.05-.26-.079-.424-.045-.25-.196-.415-.355-.418-.176-.003-.206.138-.192.187.028.095.073.254.126.506.037.177-.017.324-.017.324-.023.072-.085.318-.038.604.028.169.092.352.205.52l-.332.714 1.507.659.366-.956c.267-.119.5-.319.633-.604l.044-.095.631-1.355c.003-.004.091-.194-.099-.282z"/> + <path fill="#EF9645" d="M26.348 2.443c.04-.012.06-.036.075-.058.168.108.389.272.491.543.132.351.054.627-.028.798-.066.138-.172.168-.099-.047.092-.27.143-.866-.455-1.205l-.055-.03c.001 0 .037.009.071-.001z"/> + <path fill="#FFDC5D" d="M11.397 20.373c-.076-.064-.202-.171-.385-.352-.129-.128-.165-.279-.165-.279-.021-.073-.105-.312-.303-.524-.117-.126-.271-.243-.459-.319l-.116-.779-1.62.284.224.999c-.156.247-.24.542-.193.854l.016.104.224 1.478s.031.207.239.176.176-.239.176-.239L8.9 20.89c.002.015.108.013.11.026l.198 1.31s.031.207.239.176c.207-.031.176-.239.176-.239l-.019-.126-.167-1.105c0 .003.104-.01.105-.009l.221 1.457s.031.207.239.176c.207-.031.176-.239.176-.239l-.22-1.457c0-.002.103-.021.102-.024l.182 1.206s.031.207.239.176c.207-.031.176-.239.176-.239l-.249-1.644c-.017-.112.057-.165.106-.164.128.001.185.189.3.309.176.183.393.237.527.152.148-.092.095-.227.056-.259z"/> + <path fill="#292F33" d="M25.814 3.729S23.755 8.05 23.512 8.19c-.219.126-1.719-.042-3.699.354-1.979.396-2.744-.155-4.769-.075-1.176.046-2.413.452-3.227.648-1.237.299-3.276 3.237-3.848 4.26-.443.791-.421 1.68-.327 2.372.078.578.058 1.486.82 3.41l1.719-.281s-.289-3.783-.043-4.192c.102-.169 1.323-2.119 2.303-2.473l8.188-.385s3.375-.485 4.302-1.167c.708-.521 2.497-6.251 2.497-6.251l-1.614-.681z"/> + <path fill="#FFDC5D" d="M15.546 5.857c.175-.172.407-.289.671-.314.613-.064 1.16.383 1.222.997l.319 3.153c.061.611-.384 1.16-.997 1.221-.615.063-1.161-.384-1.222-.997l-.32-3.153c-.035-.35.095-.676.327-.907z"/> + <path fill="#FFDC5D" d="M19.243 4.296c0 1.849-1.309 3.348-2.927 3.348s-2.929-1.499-2.929-3.348c0-1.848 1.311-3.347 2.929-3.347 1.618 0 2.927 1.499 2.927 3.347z"/> + <path fill="#FFAC33" d="M17.89 2.018s-1.14 1.07-2.349 1.255c0 0-.723 1.171-.768 1.847 0 0-.45-1.081-.81-.9-.36.18-.496.855-.18 1.305.315.451.705 1.226.363 1.003-.689-.45-.79-.768-.976-1.07-.127-.206-.425-.943-.465-2.162-.024-.721.232-2.116 1.707-2.857 1.278-.644 3.287-.315 4.231.359.945.676 1.18 2.38.594 3.056 0 0-.085-.63-.488-1.14-.226-.283-.859-.696-.859-.696z"/> + <path fill="#DD2E44" d="M12.407 9.474v9.253l7.083-.024s.625-2.703 1.034-4.549c.474-2.135-1.079-5.392-1.079-5.392l-1.082-.108-.212-1.011-1.056.4-.151 1.751-.456-1.666-1.548-.135-.184 1.067-2.349.414z"/> + <path fill="#292F33" d="M11.781 9.593s.688 2.443.385 7.5c2.228-.038 3.963-.732 3.963-.732s.146-1.919-.228-3.615c-.546-2.469-1.105-3.921-1.105-3.921l-3.015.768zm6.516-1.246s.623 3.271.484 5.224c-.14 1.953-.235 2.694-.235 2.694s.441.486 1.57.466c.467-1.222.752-3.679.695-5.183-.059-1.585-1.002-3.127-1.002-3.127l-1.512-.074zm-5.89 10.38s-.607 6.995-.982 8.307c-.334 1.168-3.799 6.742-3.799 6.742s1.646.406 3.229.094c0 0 3.163-3.836 3.99-5.688.24-.539 1.835-5.521 1.835-5.521s1.712 1.908 2.863 3.599c.728 2.003.09 7.442.09 7.442s1.483.312 2.899.042c0 0 .859-5.397.651-7.688-.033-.367-.103-1.05-.245-1.309-.619-1.123-1.963-3.231-2.822-4.172-.774-.847-.625-1.873-.625-1.873l-7.084.025z"/> +</svg> diff --git a/public/shortcuts/direct.png b/public/shortcuts/direct.png new file mode 100644 index 0000000000000000000000000000000000000000..e8772c00e664042779abc16be73407e3e2cb0e89 Binary files /dev/null and b/public/shortcuts/direct.png differ diff --git a/public/shortcuts/new-status.png b/public/shortcuts/new-status.png new file mode 100644 index 0000000000000000000000000000000000000000..b7095f3c457071547153ab5b99255d37d26b6457 Binary files /dev/null and b/public/shortcuts/new-status.png differ diff --git a/public/shortcuts/notifications.png b/public/shortcuts/notifications.png new file mode 100644 index 0000000000000000000000000000000000000000..6b9d45718c82784e5c3380dcc9e4cd3fadb9e9b2 Binary files /dev/null and b/public/shortcuts/notifications.png differ diff --git a/public/shortcuts/profile.png b/public/shortcuts/profile.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3bf517ddaa5d49281a6f2ad32d3e6f49e8bb6f Binary files /dev/null and b/public/shortcuts/profile.png differ diff --git a/spec/controllers/account_follow_controller_spec.rb b/spec/controllers/account_follow_controller_spec.rb index 9a93e1ebeacb0c306960b69aa8f9934834d70eeb..d33cd0499e5fe0fdee0b4f4c8c98392a2f4c60c2 100644 --- a/spec/controllers/account_follow_controller_spec.rb +++ b/spec/controllers/account_follow_controller_spec.rb @@ -16,17 +16,49 @@ describe AccountFollowController do allow(service).to receive(:call) end - it 'does not create for user who is not signed in' do - subject - expect(FollowService).not_to receive(:new) + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + subject + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + subject + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + + context 'when signed out' do + before do + subject + end + + it 'does not follow' do + expect(FollowService).not_to receive(:new) + end end - it 'redirects to account path' do - sign_in(user) - subject + context 'when signed in' do + before do + sign_in(user) + subject + end - expect(service).to have_received(:call).with(user.account, alice, with_rate_limit: true) - expect(response).to redirect_to(account_path(alice)) + it 'redirects to account path' do + expect(service).to have_received(:call).with(user.account, alice, with_rate_limit: true) + expect(response).to redirect_to(account_path(alice)) + end end end end diff --git a/spec/controllers/account_unfollow_controller_spec.rb b/spec/controllers/account_unfollow_controller_spec.rb index bdebcfa94c85efbe63f34ae8be2a687e36c56941..a11f7aa6846b6cb77904c73b01e59dd97d0a2087 100644 --- a/spec/controllers/account_unfollow_controller_spec.rb +++ b/spec/controllers/account_unfollow_controller_spec.rb @@ -16,17 +16,49 @@ describe AccountUnfollowController do allow(service).to receive(:call) end - it 'does not create for user who is not signed in' do - subject - expect(UnfollowService).not_to receive(:new) + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + subject + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + subject + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + + context 'when signed out' do + before do + subject + end + + it 'does not unfollow' do + expect(UnfollowService).not_to receive(:new) + end end - it 'redirects to account path' do - sign_in(user) - subject + context 'when signed in' do + before do + sign_in(user) + subject + end - expect(service).to have_received(:call).with(user.account, alice) - expect(response).to redirect_to(account_path(alice)) + it 'redirects to account path' do + expect(service).to have_received(:call).with(user.account, alice) + expect(response).to redirect_to(account_path(alice)) + end end end end diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb index bd36f5494074ca727d7bc689449fb8f35125d0d6..f7d0b1af54e7ca88f7d0c992b55536821c58f992 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/controllers/accounts_controller_spec.rb @@ -5,6 +5,21 @@ RSpec.describe AccountsController, type: :controller do let(:account) { Fabricate(:user).account } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:format) { 'html' } @@ -33,10 +48,17 @@ RSpec.describe AccountsController, type: :controller do expect(response).to have_http_status(404) end end + end + + context 'as HTML' do + let(:format) { 'html' } - context 'when account is suspended' do + it_behaves_like 'preliminary checks' + + context 'when account is permanently suspended' do before do account.suspend! + account.deletion_request.destroy end it 'returns http gone' do @@ -44,12 +66,17 @@ RSpec.describe AccountsController, type: :controller do expect(response).to have_http_status(410) end end - end - context 'as HTML' do - let(:format) { 'html' } + context 'when account is temporarily suspended' do + before do + account.suspend! + end - it_behaves_like 'preliminary checks' + it 'returns http forbidden' do + get :show, params: { username: account.username, format: format } + expect(response).to have_http_status(403) + end + end shared_examples 'common response characteristics' do it 'returns http success' do @@ -310,6 +337,29 @@ RSpec.describe AccountsController, type: :controller do it_behaves_like 'preliminary checks' + context 'when account is suspended permanently' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + get :show, params: { username: account.username, format: format } + expect(response).to have_http_status(410) + end + end + + context 'when account is suspended temporarily' do + before do + account.suspend! + end + + it 'returns http success' do + get :show, params: { username: account.username, format: format } + expect(response).to have_http_status(200) + end + end + context do before do get :show, params: { username: account.username, format: format } @@ -323,9 +373,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -335,26 +383,8 @@ RSpec.describe AccountsController, type: :controller do context 'in authorized fetch mode' do let(:authorized_fetch_mode) { true } - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'returns application/activity+json' do - expect(response.content_type).to eq 'application/activity+json' - end - - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end - - it 'returns Vary header with Signature' do - expect(response.headers['Vary']).to include 'Signature' - end - - it 'renders bare minimum account' do - json = body_as_json - expect(json).to include(:id, :type, :preferredUsername, :inbox, :publicKey) - expect(json).to_not include(:name, :summary) + it 'returns http unauthorized' do + expect(response).to have_http_status(401) end end end @@ -401,9 +431,7 @@ RSpec.describe AccountsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'renders account' do json = body_as_json @@ -442,14 +470,35 @@ RSpec.describe AccountsController, type: :controller do it_behaves_like 'preliminary checks' + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + get :show, params: { username: account.username, format: format } + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http forbidden' do + get :show, params: { username: account.username, format: format } + expect(response).to have_http_status(403) + end + end + shared_examples 'common response characteristics' do it 'returns http success' do expect(response).to have_http_status(200) end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' end context do diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb index 56be49be3d7c7dad3a47b3d4c2ce50c4c3574303..ac661e5e1d931a6c212d3def8453d22af56eb5be 100644 --- a/spec/controllers/activitypub/collections_controller_spec.rb +++ b/spec/controllers/activitypub/collections_controller_spec.rb @@ -6,6 +6,22 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do let!(:account) { Fabricate(:account) } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + response + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -19,9 +35,8 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do context 'without signature' do let(:remote_account) { nil } - before do - get :show, params: { id: 'featured', account_username: account.username } - end + subject(:response) { get :show, params: { id: 'featured', account_username: account.username } } + subject(:body) { body_as_json } it 'returns http success' do expect(response).to have_http_status(200) @@ -31,14 +46,32 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 2 + expect(body[:orderedItems]).to be_an Array + expect(body[:orderedItems].size).to eq 2 + end + + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end end end @@ -58,9 +91,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns orderedItems with pinned statuses' do json = body_as_json diff --git a/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..88f4554c2d6cbd70aa50d12ae06d1216d9eb1929 --- /dev/null +++ b/spec/controllers/activitypub/followers_synchronizations_controller_spec.rb @@ -0,0 +1,77 @@ +require 'rails_helper' + +RSpec.describe ActivityPub::FollowersSynchronizationsController, type: :controller do + let!(:account) { Fabricate(:account) } + let!(:follower_1) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/a') } + let!(:follower_2) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/b') } + let!(:follower_3) { Fabricate(:account, domain: 'foo.com', uri: 'https://foo.com/users/a') } + + before do + follower_1.follow!(account) + follower_2.follow!(account) + follower_3.follow!(account) + end + + before do + allow(controller).to receive(:signed_request_account).and_return(remote_account) + end + + describe 'GET #show' do + context 'without signature' do + let(:remote_account) { nil } + + before do + get :show, params: { account_username: account.username } + end + + it 'returns http not authorized' do + expect(response).to have_http_status(401) + end + end + + context 'with signature from example.com' do + let(:remote_account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/instance') } + + subject(:response) { get :show, params: { account_username: account.username } } + subject(:body) { body_as_json } + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'returns application/activity+json' do + expect(response.content_type).to eq 'application/activity+json' + end + + it 'returns orderedItems with followers from example.com' do + expect(body[:orderedItems]).to be_an Array + expect(body[:orderedItems].sort).to eq [follower_1.uri, follower_2.uri] + end + + it 'returns private Cache-Control header' do + expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + end + + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + end + end +end diff --git a/spec/controllers/activitypub/inboxes_controller_spec.rb b/spec/controllers/activitypub/inboxes_controller_spec.rb index f3bc23953a5c7bd834fa985f8689ac3760919099..973ad83bb3e28705450c055d0dba2b09bfe3bdaa 100644 --- a/spec/controllers/activitypub/inboxes_controller_spec.rb +++ b/spec/controllers/activitypub/inboxes_controller_spec.rb @@ -20,6 +20,83 @@ RSpec.describe ActivityPub::InboxesController, type: :controller do it 'returns http accepted' do expect(response).to have_http_status(202) end + + context 'for a specific account' do + let(:account) { Fabricate(:account) } + + subject(:response) { post :create, params: { account_username: account.username }, body: '{}' } + + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http accepted' do + expect(response).to have_http_status(202) + end + end + end + end + + context 'with Collection-Synchronization header' do + let(:remote_account) { Fabricate(:account, followers_url: 'https://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor', protocol: :activitypub) } + let(:synchronization_collection) { remote_account.followers_url } + let(:synchronization_url) { 'https://example.com/followers-for-domain' } + let(:synchronization_hash) { 'somehash' } + let(:synchronization_header) { "collectionId=\"#{synchronization_collection}\", digest=\"#{synchronization_hash}\", url=\"#{synchronization_url}\"" } + + before do + allow(ActivityPub::FollowersSynchronizationWorker).to receive(:perform_async).and_return(nil) + allow_any_instance_of(Account).to receive(:local_followers_hash).and_return('somehash') + + request.headers['Collection-Synchronization'] = synchronization_header + post :create, body: '{}' + end + + context 'with mismatching target collection' do + let(:synchronization_collection) { 'https://example.com/followers2' } + + it 'does not start a synchronization job' do + expect(ActivityPub::FollowersSynchronizationWorker).not_to have_received(:perform_async) + end + end + + context 'with mismatching domain in partial collection attribute' do + let(:synchronization_url) { 'https://example.org/followers' } + + it 'does not start a synchronization job' do + expect(ActivityPub::FollowersSynchronizationWorker).not_to have_received(:perform_async) + end + end + + context 'with matching digest' do + it 'does not start a synchronization job' do + expect(ActivityPub::FollowersSynchronizationWorker).not_to have_received(:perform_async) + end + end + + context 'with mismatching digest' do + let(:synchronization_hash) { 'wronghash' } + + it 'starts a synchronization job' do + expect(ActivityPub::FollowersSynchronizationWorker).to have_received(:perform_async) + end + end + + it 'returns http accepted' do + expect(response).to have_http_status(202) + end end context 'without signature' do diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index 03490533dd5926f343be5a50417eeb0687cce917..84e3a8956027857a2091cb2364fd33cac6e49d31 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -3,6 +3,22 @@ require 'rails_helper' RSpec.describe ActivityPub::OutboxesController, type: :controller do let!(:account) { Fabricate(:account) } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + response + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do Fabricate(:status, account: account, visibility: :public) Fabricate(:status, account: account, visibility: :unlisted) @@ -19,9 +35,8 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do context 'without signature' do let(:remote_account) { nil } - before do - get :show, params: { account_username: account.username, page: page } - end + subject(:response) { get :show, params: { account_username: account.username, page: page } } + subject(:body) { body_as_json } context 'with page not requested' do let(:page) { nil } @@ -35,12 +50,30 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns totalItems' do - json = body_as_json - expect(json[:totalItems]).to eq 4 + expect(body[:totalItems]).to eq 4 end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' + it_behaves_like 'cachable response' + + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end end end @@ -56,14 +89,32 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns orderedItems with public or unlisted statuses' do - json = body_as_json - expect(json[:orderedItems]).to be_an Array - expect(json[:orderedItems].size).to eq 2 - expect(json[:orderedItems].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true + expect(body[:orderedItems]).to be_an Array + expect(body[:orderedItems].size).to eq 2 + expect(body[:orderedItems].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' + it_behaves_like 'cachable response' + + context 'when account is permanently suspended' do + before do + account.suspend! + account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + account.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end end end end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index d956e1b35f0e043998c4188a6c6d64d96d29ceaa..25025975283e041bbddd970ce30ad4ad2732dca3 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -7,6 +7,22 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do let(:remote_reply_id) { nil } let(:remote_account) { nil } + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + response + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + before do allow(controller).to receive(:signed_request_account).and_return(remote_account) @@ -21,8 +37,32 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do describe 'GET #index' do context 'with no signature' do - before do - get :index, params: { account_username: status.account.username, status_id: status.id } + subject(:response) { get :index, params: { account_username: status.account.username, status_id: status.id } } + subject(:body) { body_as_json } + + context 'when account is permanently suspended' do + let(:parent_visibility) { :public } + + before do + status.account.suspend! + status.account.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + let(:parent_visibility) { :public } + + before do + status.account.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end end context 'when status is public' do @@ -36,17 +76,13 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns items with account\'s own replies' do - json = body_as_json - - expect(json[:first]).to be_a Hash - expect(json[:first][:items]).to be_an Array - expect(json[:first][:items].size).to eq 1 - expect(json[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true + expect(body[:first]).to be_a Hash + expect(body[:first][:items]).to be_an Array + expect(body[:first][:items].size).to eq 1 + expect(body[:first][:items].all? { |item| item[:to].include?(ActivityPub::TagManager::COLLECTIONS[:public]) || item[:cc].include?(ActivityPub::TagManager::COLLECTIONS[:public]) }).to be true end end @@ -87,9 +123,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do expect(response.content_type).to eq 'application/activity+json' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' context 'without only_other_accounts' do it 'returns items with account\'s own replies' do diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb index 412b814439bc0f52d49f1b4f767ea3ec64b08af0..8c0b309f2a50db4fe2e43a766d75080622db6ce2 100644 --- a/spec/controllers/admin/instances_controller_spec.rb +++ b/spec/controllers/admin/instances_controller_spec.rb @@ -9,10 +9,10 @@ RSpec.describe Admin::InstancesController, type: :controller do describe 'GET #index' do around do |example| - default_per_page = Account.default_per_page - Account.paginates_per 1 + default_per_page = Instance.default_per_page + Instance.paginates_per 1 example.run - Account.paginates_per default_per_page + Instance.paginates_per default_per_page end it 'renders instances' do diff --git a/spec/controllers/admin/two_factor_authentications_controller_spec.rb b/spec/controllers/admin/two_factor_authentications_controller_spec.rb index 4c1aa88d7547f216353a80f0946400d5e8486a0c..b0e82d3d6637770982d7e8645455a9cbcd51653c 100644 --- a/spec/controllers/admin/two_factor_authentications_controller_spec.rb +++ b/spec/controllers/admin/two_factor_authentications_controller_spec.rb @@ -1,20 +1,51 @@ require 'rails_helper' +require 'webauthn/fake_client' describe Admin::TwoFactorAuthenticationsController do render_views - let(:user) { Fabricate(:user, otp_required_for_login: true) } + let(:user) { Fabricate(:user) } before do sign_in Fabricate(:user, admin: true), scope: :user end describe 'DELETE #destroy' do - it 'redirects to admin accounts page' do - delete :destroy, params: { user_id: user.id } + context 'when user has OTP enabled' do + before do + user.update(otp_required_for_login: true) + end - user.reload - expect(user.otp_required_for_login).to eq false - expect(response).to redirect_to(admin_accounts_path) + it 'redirects to admin accounts page' do + delete :destroy, params: { user_id: user.id } + + user.reload + expect(user.otp_enabled?).to eq false + expect(response).to redirect_to(admin_accounts_path) + end + end + + context 'when user has OTP and WebAuthn enabled' do + let(:fake_client) { WebAuthn::FakeClient.new('http://test.host') } + + before do + user.update(otp_required_for_login: true, webauthn_id: WebAuthn.generate_user_id) + + public_key_credential = WebAuthn::Credential.from_create(fake_client.create) + Fabricate(:webauthn_credential, + user_id: user.id, + external_id: public_key_credential.id, + public_key: public_key_credential.public_key, + nickname: 'Security Key') + end + + it 'redirects to admin accounts page' do + delete :destroy, params: { user_id: user.id } + + user.reload + expect(user.otp_enabled?).to eq false + expect(user.webauthn_enabled?).to eq false + expect(response).to redirect_to(admin_accounts_path) + end end end end diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb index 024409dab85328018d94bf44a3cf74f84c9b17d8..1e656503fbccb4994faf35c3222cd0729a03baa0 100644 --- a/spec/controllers/api/v1/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -71,50 +71,80 @@ RSpec.describe Api::V1::AccountsController, type: :controller do let(:scopes) { 'write:follows' } let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', locked: locked)).account } - before do - post :follow, params: { id: other_account.id } - end + context do + before do + post :follow, params: { id: other_account.id } + end - context 'with unlocked account' do - let(:locked) { false } + context 'with unlocked account' do + let(:locked) { false } - it 'returns http success' do - expect(response).to have_http_status(200) - end + it 'returns http success' do + expect(response).to have_http_status(200) + end - it 'returns JSON with following=true and requested=false' do - json = body_as_json + it 'returns JSON with following=true and requested=false' do + json = body_as_json - expect(json[:following]).to be true - expect(json[:requested]).to be false - end + expect(json[:following]).to be true + expect(json[:requested]).to be false + end + + it 'creates a following relation between user and target user' do + expect(user.account.following?(other_account)).to be true + end - it 'creates a following relation between user and target user' do - expect(user.account.following?(other_account)).to be true + it_behaves_like 'forbidden for wrong scope', 'read:accounts' end - it_behaves_like 'forbidden for wrong scope', 'read:accounts' + context 'with locked account' do + let(:locked) { true } + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'returns JSON with following=false and requested=true' do + json = body_as_json + + expect(json[:following]).to be false + expect(json[:requested]).to be true + end + + it 'creates a follow request relation between user and target user' do + expect(user.account.requested?(other_account)).to be true + end + + it_behaves_like 'forbidden for wrong scope', 'read:accounts' + end end - context 'with locked account' do - let(:locked) { true } + context 'modifying follow options' do + let(:locked) { false } - it 'returns http success' do - expect(response).to have_http_status(200) + before do + user.account.follow!(other_account, reblogs: false, notify: false) end - it 'returns JSON with following=false and requested=true' do + it 'changes reblogs option' do + post :follow, params: { id: other_account.id, reblogs: true } + json = body_as_json - expect(json[:following]).to be false - expect(json[:requested]).to be true + expect(json[:following]).to be true + expect(json[:showing_reblogs]).to be true + expect(json[:notifying]).to be false end - it 'creates a follow request relation between user and target user' do - expect(user.account.requested?(other_account)).to be true - end + it 'changes notify option' do + post :follow, params: { id: other_account.id, notify: true } + + json = body_as_json - it_behaves_like 'forbidden for wrong scope', 'read:accounts' + expect(json[:following]).to be true + expect(json[:showing_reblogs]).to be false + expect(json[:notifying]).to be true + end end end diff --git a/spec/controllers/api/v1/admin/accounts_controller_spec.rb b/spec/controllers/api/v1/admin/accounts_controller_spec.rb index f3f9946baac2dbb197586350c93ccc891d0a7710..f6be35f7f10036b79a7a4c5f73d317a597220a28 100644 --- a/spec/controllers/api/v1/admin/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/admin/accounts_controller_spec.rb @@ -111,7 +111,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do describe 'POST #unsuspend' do before do - account.touch(:suspended_at) + account.suspend! post :unsuspend, params: { id: account.id } end @@ -127,6 +127,24 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do end end + describe 'POST #unsensitive' do + before do + account.touch(:sensitized_at) + post :unsensitive, params: { id: account.id } + end + + it_behaves_like 'forbidden for wrong scope', 'write:statuses' + it_behaves_like 'forbidden for wrong role', 'user' + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'unsensitives account' do + expect(account.reload.sensitized?).to be false + end + end + describe 'POST #unsilence' do before do account.touch(:silenced_at) diff --git a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb index aa5ca433fb794e38c1c80b24cfa7da74429174e3..7c75a4f7383d4bb1833628d0851c348120bf954f 100644 --- a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb @@ -72,6 +72,31 @@ describe Api::V1::Statuses::BookmarksController do end end + context 'with public status when blocked by its author' do + let(:status) { Fabricate(:status) } + + before do + Bookmark.find_or_create_by!(account: user.account, status: status) + status.account.block!(user.account) + post :destroy, params: { status_id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'updates the bookmarked attribute' do + expect(user.account.bookmarked?(status)).to be false + end + + it 'returns json with updated attributes' do + hash_body = body_as_json + + expect(hash_body[:id]).to eq status.id.to_s + expect(hash_body[:bookmarked]).to be false + end + end + context 'with private status that was not bookmarked' do let(:status) { Fabricate(:status, visibility: :private) } diff --git a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb b/spec/controllers/api/v1/statuses/favourites_controller_spec.rb index 6e947f5d2b6f444229fae2aad4295cba8ada952b..4716ecae3c34fe917a3a85d3a0ef147eba9c791b 100644 --- a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/favourites_controller_spec.rb @@ -82,6 +82,31 @@ describe Api::V1::Statuses::FavouritesController do end end + context 'with public status when blocked by its author' do + let(:status) { Fabricate(:status) } + + before do + FavouriteService.new.call(user.account, status) + status.account.block!(user.account) + post :destroy, params: { status_id: status.id } + end + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'updates the favourite attribute' do + expect(user.account.favourited?(status)).to be false + end + + it 'returns json with updated attributes' do + hash_body = body_as_json + + expect(hash_body[:id]).to eq status.id.to_s + expect(hash_body[:favourited]).to be false + end + end + context 'with private status that was not favourited' do let(:status) { Fabricate(:status, visibility: :private) } diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index c2e9f33a82a0bfff62e0257db9913a232a561bb7..ccf304a930ec2993a7b3eac91049583f48eb6aef 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -82,6 +82,10 @@ RSpec.describe Auth::RegistrationsController, type: :controller do describe 'POST #create' do let(:accept_language) { Rails.application.config.i18n.available_locales.sample.to_s } + before do + session[:registration_form_time] = 5.seconds.ago + end + around do |example| current_locale = I18n.locale example.run @@ -191,17 +195,21 @@ RSpec.describe Auth::RegistrationsController, type: :controller do end end - context 'approval-based registrations with valid invite' do + context 'approval-based registrations with valid invite and required invite text' do around do |example| registrations_mode = Setting.registrations_mode + require_invite_text = Setting.require_invite_text example.run + Setting.require_invite_text = require_invite_text Setting.registrations_mode = registrations_mode end subject do + inviter = Fabricate(:user, confirmed_at: 2.days.ago) Setting.registrations_mode = 'approved' + Setting.require_invite_text = true request.headers["Accept-Language"] = accept_language - invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now) + invite = Fabricate(:invite, user: inviter, max_uses: nil, expires_at: 1.hour.from_now) post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code, agreement: 'true' } } end diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index c387842cda909f62b19b011b1741e2b8e37ca411..d3a9a11ebbd71b105361aac465399f2213a6ebec 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'rails_helper' +require 'webauthn/fake_client' RSpec.describe Auth::SessionsController, type: :controller do render_views @@ -183,90 +184,170 @@ RSpec.describe Auth::SessionsController, type: :controller do end context 'using two-factor authentication' do - let!(:user) do - Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) - end - - let!(:recovery_codes) do - codes = user.generate_otp_backup_codes! - user.save - return codes - end - - context 'using email and password' do - before do - post :create, params: { user: { email: user.email, password: user.password } } + context 'with OTP enabled as second factor' do + let!(:user) do + Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) end - it 'renders two factor authentication page' do - expect(controller).to render_template("two_factor") + let!(:recovery_codes) do + codes = user.generate_otp_backup_codes! + user.save + return codes end - end - context 'using upcase email and password' do - before do - post :create, params: { user: { email: user.email.upcase, password: user.password } } - end + context 'using email and password' do + before do + post :create, params: { user: { email: user.email, password: user.password } } + end - it 'renders two factor authentication page' do - expect(controller).to render_template("two_factor") + it 'renders two factor authentication page' do + expect(controller).to render_template("two_factor") + expect(controller).to render_template(partial: "_otp_authentication_form") + end end - end - context 'using a valid OTP' do - before do - post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id } - end + context 'using upcase email and password' do + before do + post :create, params: { user: { email: user.email.upcase, password: user.password } } + end - it 'redirects to home' do - expect(response).to redirect_to(root_path) + it 'renders two factor authentication page' do + expect(controller).to render_template("two_factor") + expect(controller).to render_template(partial: "_otp_authentication_form") + end end - it 'logs the user in' do - expect(controller.current_user).to eq user + context 'using a valid OTP' do + before do + post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + end + + it 'redirects to home' do + expect(response).to redirect_to(root_path) + end + + it 'logs the user in' do + expect(controller.current_user).to eq user + end end - end - context 'when the server has an decryption error' do - before do - allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError) - post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id } + context 'when the server has an decryption error' do + before do + allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError) + post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + end + + it 'shows a login error' do + expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') + end + + it "doesn't log the user in" do + expect(controller.current_user).to be_nil + end end - it 'shows a login error' do - expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') + context 'using a valid recovery code' do + before do + post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + end + + it 'redirects to home' do + expect(response).to redirect_to(root_path) + end + + it 'logs the user in' do + expect(controller.current_user).to eq user + end end - it "doesn't log the user in" do - expect(controller.current_user).to be_nil + context 'using an invalid OTP' do + before do + post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + end + + it 'shows a login error' do + expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') + end + + it "doesn't log the user in" do + expect(controller.current_user).to be_nil + end end end - context 'using a valid recovery code' do - before do - post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { attempt_user_id: user.id } + context 'with WebAuthn and OTP enabled as second factor' do + let!(:user) do + Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) end - it 'redirects to home' do - expect(response).to redirect_to(root_path) + let!(:recovery_codes) do + codes = user.generate_otp_backup_codes! + user.save + return codes end - it 'logs the user in' do - expect(controller.current_user).to eq user + let!(:webauthn_credential) do + user.update(webauthn_id: WebAuthn.generate_user_id) + public_key_credential = WebAuthn::Credential.from_create(fake_client.create) + user.webauthn_credentials.create( + nickname: 'SecurityKeyNickname', + external_id: public_key_credential.id, + public_key: public_key_credential.public_key, + sign_count: '1000' + ) + user.webauthn_credentials.take end - end - context 'using an invalid OTP' do - before do - post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id } + let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" } + + let(:fake_client) { WebAuthn::FakeClient.new(domain) } + + let(:challenge) { WebAuthn::Credential.options_for_get.challenge } + + let(:sign_count) { 1234 } + + let(:fake_credential) { fake_client.get(challenge: challenge, sign_count: sign_count) } + + context 'using email and password' do + before do + post :create, params: { user: { email: user.email, password: user.password } } + end + + it 'renders webauthn authentication page' do + expect(controller).to render_template("two_factor") + expect(controller).to render_template(partial: "_webauthn_form") + end end - it 'shows a login error' do - expect(flash[:alert]).to match I18n.t('users.invalid_otp_token') + context 'using upcase email and password' do + before do + post :create, params: { user: { email: user.email.upcase, password: user.password } } + end + + it 'renders webauthn authentication page' do + expect(controller).to render_template("two_factor") + expect(controller).to render_template(partial: "_webauthn_form") + end end - it "doesn't log the user in" do - expect(controller.current_user).to be_nil + context 'using a valid webauthn credential' do + before do + @controller.session[:webauthn_challenge] = challenge + + post :create, params: { user: { credential: fake_credential } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } + end + + it 'instructs the browser to redirect to home' do + expect(body_as_json[:redirect_path]).to eq(root_path) + end + + it 'logs the user in' do + expect(controller.current_user).to eq user + end + + it 'updates the sign count' do + expect(webauthn_credential.reload.sign_count).to eq(sign_count) + end end end end @@ -302,7 +383,7 @@ RSpec.describe Auth::SessionsController, type: :controller do context 'using a valid sign in token' do before do user.generate_sign_in_token && user.save - post :create, params: { user: { sign_in_token_attempt: user.sign_in_token } }, session: { attempt_user_id: user.id } + post :create, params: { user: { sign_in_token_attempt: user.sign_in_token } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end it 'redirects to home' do @@ -316,7 +397,7 @@ RSpec.describe Auth::SessionsController, type: :controller do context 'using an invalid sign in token' do before do - post :create, params: { user: { sign_in_token_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id } + post :create, params: { user: { sign_in_token_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } end it 'shows a login error' do diff --git a/spec/controllers/concerns/export_controller_concern_spec.rb b/spec/controllers/concerns/export_controller_concern_spec.rb index e5861c801f54448442d09ffeebbec2c72f69de20..fce129bee2223aadd8624690704289a9ff1ee0d8 100644 --- a/spec/controllers/concerns/export_controller_concern_spec.rb +++ b/spec/controllers/concerns/export_controller_concern_spec.rb @@ -5,6 +5,7 @@ require 'rails_helper' describe ApplicationController, type: :controller do controller do include ExportControllerConcern + def index send_export_file end diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb index 34a0cf3f482ec58929e973f9ff27a3cdda07183d..f6d55f69326b611db81b20cce16093a52d8f6135 100644 --- a/spec/controllers/follower_accounts_controller_spec.rb +++ b/spec/controllers/follower_accounts_controller_spec.rb @@ -14,6 +14,27 @@ describe FollowerAccountsController do context 'when format is html' do subject(:response) { get :index, params: { account_username: alice.username, format: :html } } + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + it 'assigns follows' do expect(response).to have_http_status(200) @@ -48,6 +69,27 @@ describe FollowerAccountsController do expect(body['totalItems']).to eq 2 expect(body['partOf']).to be_present end + + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end end context 'without page' do @@ -58,6 +100,27 @@ describe FollowerAccountsController do expect(body['totalItems']).to eq 2 expect(body['partOf']).to be_blank end + + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end end end end diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb index e9a1f597df609af3c9331362e0016c396dd2bc97..0fc0967a632847828d0ce0cb1941feeb779a670d 100644 --- a/spec/controllers/following_accounts_controller_spec.rb +++ b/spec/controllers/following_accounts_controller_spec.rb @@ -14,6 +14,27 @@ describe FollowingAccountsController do context 'when format is html' do subject(:response) { get :index, params: { account_username: alice.username, format: :html } } + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + it 'assigns follows' do expect(response).to have_http_status(200) @@ -48,6 +69,27 @@ describe FollowingAccountsController do expect(body['totalItems']).to eq 2 expect(body['partOf']).to be_present end + + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end end context 'without page' do @@ -58,6 +100,27 @@ describe FollowingAccountsController do expect(body['totalItems']).to eq 2 expect(body['partOf']).to be_blank end + + context 'when account is permanently suspended' do + before do + alice.suspend! + alice.deletion_request.destroy + end + + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when account is temporarily suspended' do + before do + alice.suspend! + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end end end end diff --git a/spec/controllers/remote_follow_controller_spec.rb b/spec/controllers/remote_follow_controller_spec.rb index 3ef8f14d9f68c36386e19627380947d856b04b47..01d43f48c29f04c501b1a8dd1b17594a190a3500 100644 --- a/spec/controllers/remote_follow_controller_spec.rb +++ b/spec/controllers/remote_follow_controller_spec.rb @@ -43,8 +43,7 @@ describe RemoteFollowController do end it 'renders new when template is nil' do - link_with_nil_template = double(template: nil) - resource_with_link = double(link: link_with_nil_template) + resource_with_link = double(link: nil) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link) post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } @@ -55,8 +54,7 @@ describe RemoteFollowController do context 'when webfinger values are good' do before do - link_with_template = double(template: 'http://example.com/follow_me?acct={uri}') - resource_with_link = double(link: link_with_template) + resource_with_link = double(link: 'http://example.com/follow_me?acct={uri}') allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link) post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } end @@ -78,8 +76,8 @@ describe RemoteFollowController do expect(response).to render_template(:new) end - it 'renders new with error when goldfinger fails' do - allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_raise(Goldfinger::Error) + it 'renders new with error when webfinger fails' do + allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_raise(Webfinger::Error) post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } expect(response).to render_template(:new) @@ -96,21 +94,42 @@ describe RemoteFollowController do end end - describe 'with a suspended account' do + context 'with a permanently suspended account' do before do - @account = Fabricate(:account, suspended: true) + @account = Fabricate(:account) + @account.suspend! + @account.deletion_request.destroy end - it 'returns 410 gone on GET to #new' do + it 'returns http gone on GET to #new' do get :new, params: { account_username: @account.to_param } - expect(response).to have_http_status(:gone) + expect(response).to have_http_status(410) end - it 'returns 410 gone on POST to #create' do + it 'returns http gone on POST to #create' do post :create, params: { account_username: @account.to_param } - expect(response).to have_http_status(:gone) + expect(response).to have_http_status(410) + end + end + + context 'with a temporarily suspended account' do + before do + @account = Fabricate(:account) + @account.suspend! + end + + it 'returns http forbidden on GET to #new' do + get :new, params: { account_username: @account.to_param } + + expect(response).to have_http_status(403) + end + + it 'returns http forbidden on POST to #create' do + post :create, params: { account_username: @account.to_param } + + expect(response).to have_http_status(403) end end end diff --git a/spec/controllers/settings/deletes_controller_spec.rb b/spec/controllers/settings/deletes_controller_spec.rb index 996872efd1af639726dc957e2981fd7787559c7d..8d5c4774fd8541ce971eebc15199314f723238cc 100644 --- a/spec/controllers/settings/deletes_controller_spec.rb +++ b/spec/controllers/settings/deletes_controller_spec.rb @@ -77,26 +77,26 @@ describe Settings::DeletesController do expect(response).to redirect_to settings_delete_path end end - end - context 'when not signed in' do - it 'redirects' do - delete :destroy - expect(response).to redirect_to '/auth/sign_in' - end - end + context 'when account deletions are disabled' do + around do |example| + open_deletion = Setting.open_deletion + example.run + Setting.open_deletion = open_deletion + end - context do - around do |example| - open_deletion = Setting.open_deletion - example.run - Setting.open_deletion = open_deletion + it 'redirects' do + Setting.open_deletion = false + delete :destroy + expect(response).to redirect_to root_path + end end + end + context 'when not signed in' do it 'redirects' do - Setting.open_deletion = false delete :destroy - expect(response).to redirect_to root_path + expect(response).to redirect_to '/auth/sign_in' end end end diff --git a/spec/controllers/settings/exports/bookmarks_controller_specs.rb b/spec/controllers/settings/exports/bookmarks_controller_specs.rb new file mode 100644 index 0000000000000000000000000000000000000000..85761577bd9d21bfa119e11c4238e4b78f8a34ae --- /dev/null +++ b/spec/controllers/settings/exports/bookmarks_controller_specs.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +describe Settings::Exports::BookmarksController do + render_views + + describe 'GET #index' do + it 'returns a csv of the bookmarked toots' do + user = Fabricate(:user) + user.account.bookmarks.create!(status: Fabricate(:status, uri: 'https://foo.bar/statuses/1312')) + + sign_in user, scope: :user + get :index, format: :csv + + expect(response.body).to eq "https://foo.bar/statuses/1312\n" + end + end +end diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 336f131279fc11a61269c69cd1463da922b8aa86..cdfeef8d6a7223a7d2a14ac8ee0d20730fb8fd00 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -5,8 +5,6 @@ require 'rails_helper' describe Settings::TwoFactorAuthentication::ConfirmationsController do render_views - let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: 'thisisasecretforthespecofnewview') } - let(:user_without_otp_secret) { Fabricate(:user, email: 'local-part@domain') } shared_examples 'renders :new' do it 'renders the new view' do @@ -20,87 +18,101 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do end end - describe 'GET #new' do - context 'when signed in' do - subject do - sign_in user, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc } - end + [true, false].each do |with_otp_secret| + let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) } - include_examples 'renders :new' - end + describe 'GET #new' do + context 'when signed in and a new otp secret has been setted in the session' do + subject do + sign_in user, scope: :user + get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end - it 'redirects if not signed in' do - get :new - expect(response).to redirect_to('/auth/sign_in') - end + include_examples 'renders :new' + end - it 'redirects if user do not have otp_secret' do - sign_in user_without_otp_secret, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc } - expect(response).to redirect_to('/settings/two_factor_authentication') - end - end + it 'redirects if not signed in' do + get :new + expect(response).to redirect_to('/auth/sign_in') + end - describe 'POST #create' do - context 'when signed in' do - before do + it 'redirects if a new otp_secret has not been setted in the session' do sign_in user, scope: :user + get :new, session: { challenge_passed_at: Time.now.utc } + expect(response).to redirect_to('/settings/otp_authentication') end + end - describe 'when form_two_factor_confirmation parameter is not provided' do - it 'raises ActionController::ParameterMissing' do - post :create, params: {}, session: { challenge_passed_at: Time.now.utc } - expect(response).to have_http_status(400) + describe 'POST #create' do + context 'when signed in' do + before do + sign_in user, scope: :user end - end - describe 'when creation succeeds' do - it 'renders page with success' do - otp_backup_codes = user.generate_otp_backup_codes! - expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value| - expect(value).to eq user - otp_backup_codes - end - expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg| - expect(value).to eq user - expect(arg).to eq '123456' - true + describe 'when form_two_factor_confirmation parameter is not provided' do + it 'raises ActionController::ParameterMissing' do + post :create, params: {}, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + expect(response).to have_http_status(400) end + end - post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, session: { challenge_passed_at: Time.now.utc } - - expect(assigns(:recovery_codes)).to eq otp_backup_codes - expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled' - expect(response).to have_http_status(200) - expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index') + describe 'when creation succeeds' do + it 'renders page with success' do + otp_backup_codes = user.generate_otp_backup_codes! + expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value| + expect(value).to eq user + otp_backup_codes + end + expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, code, options| + expect(value).to eq user + expect(code).to eq '123456' + expect(options).to eq({ otp_secret: 'thisisasecretforthespecofnewview' }) + true + end + + expect do + post :create, + params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, + session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end.to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' + + expect(assigns(:recovery_codes)).to eq otp_backup_codes + expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled' + expect(response).to have_http_status(200) + expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index') + end end - end - describe 'when creation fails' do - subject do - expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg| - expect(value).to eq user - expect(arg).to eq '123456' - false + describe 'when creation fails' do + subject do + expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, code, options| + expect(value).to eq user + expect(code).to eq '123456' + expect(options).to eq({ otp_secret: 'thisisasecretforthespecofnewview' }) + false + end + + expect do + post :create, + params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, + session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end.to not_change { user.reload.otp_secret } end - post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, session: { challenge_passed_at: Time.now.utc } - end + it 'renders the new view' do + subject + expect(response.body).to include 'The entered code was invalid! Are server time and device time correct?' + end - it 'renders the new view' do - subject - expect(response.body).to include 'The entered code was invalid! Are server time and device time correct?' + include_examples 'renders :new' end - - include_examples 'renders :new' end - end - context 'when not signed in' do - it 'redirects if not signed in' do - post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } - expect(response).to redirect_to('/auth/sign_in') + context 'when not signed in' do + it 'redirects if not signed in' do + post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } + expect(response).to redirect_to('/auth/sign_in') + end end end end diff --git a/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..17e8fa9b8212e9b581c0c112a529ca53ab3ccabb --- /dev/null +++ b/spec/controllers/settings/two_factor_authentication/otp_authentication_controller_spec.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Settings::TwoFactorAuthentication::OtpAuthenticationController do + render_views + + let(:user) { Fabricate(:user) } + + describe 'GET #show' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + describe 'when user has OTP enabled' do + before do + user.update(otp_required_for_login: true) + end + + it 'redirects to two factor authentciation methods list page' do + get :show + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + end + end + + describe 'when user does not have OTP enabled' do + before do + user.update(otp_required_for_login: false) + end + + it 'returns http success' do + get :show + + expect(response).to have_http_status(200) + end + end + end + + context 'when not signed in' do + it 'redirects' do + get :show + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe 'POST #create' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + describe 'when user has OTP enabled' do + before do + user.update(otp_required_for_login: true) + end + + describe 'when creation succeeds' do + it 'redirects to code confirmation page without updating user secret and setting otp secret in the session' do + expect do + post :create, session: { challenge_passed_at: Time.now.utc } + end.to not_change { user.reload.otp_secret } + .and change { session[:new_otp_secret] } + + expect(response).to redirect_to(new_settings_two_factor_authentication_confirmation_path) + end + end + end + + describe 'when user does not have OTP enabled' do + before do + user.update(otp_required_for_login: false) + end + + describe 'when creation succeeds' do + it 'redirects to code confirmation page without updating user secret and setting otp secret in the session' do + expect do + post :create, session: { challenge_passed_at: Time.now.utc } + end.to not_change { user.reload.otp_secret } + .and change { session[:new_otp_secret] } + + expect(response).to redirect_to(new_settings_two_factor_authentication_confirmation_path) + end + end + end + end + + context 'when not signed in' do + it 'redirects to login' do + get :show + + expect(response).to redirect_to new_user_session_path + end + end + end +end diff --git a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..fe53b4dfc26c17da196225e20f617bfcd0b22e5c --- /dev/null +++ b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb @@ -0,0 +1,374 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'webauthn/fake_client' + +describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do + render_views + + let(:user) { Fabricate(:user) } + let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" } + let(:fake_client) { WebAuthn::FakeClient.new(domain) } + + def add_webauthn_credential(user) + Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key') + end + + describe 'GET #new' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + context 'when user has otp enabled' do + before do + user.update(otp_required_for_login: true) + end + + it 'returns http success' do + get :new + + expect(response).to have_http_status(200) + end + end + + context 'when user does not have otp enabled' do + before do + user.update(otp_required_for_login: false) + end + + it 'requires otp enabled first' do + get :new + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + end + + describe 'GET #index' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + context 'when user has otp enabled' do + before do + user.update(otp_required_for_login: true) + end + + context 'when user has webauthn enabled' do + before do + user.update(webauthn_id: WebAuthn.generate_user_id) + add_webauthn_credential(user) + end + + it 'returns http success' do + get :index + + expect(response).to have_http_status(200) + end + end + + context 'when user does not has webauthn enabled' do + it 'redirects to 2FA methods list page' do + get :index + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when user does not have otp enabled' do + before do + user.update(otp_required_for_login: false) + end + + it 'requires otp enabled first' do + get :index + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when not signed in' do + it 'redirects to login' do + delete :index + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe 'GET /options #options' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + context 'when user has otp enabled' do + before do + user.update(otp_required_for_login: true) + end + + context 'when user has webauthn enabled' do + before do + user.update(webauthn_id: WebAuthn.generate_user_id) + add_webauthn_credential(user) + end + + it 'returns http success' do + get :options + + expect(response).to have_http_status(200) + end + + it 'stores the challenge on the session' do + get :options + + expect(@controller.session[:webauthn_challenge]).to be_present + end + + it 'does not change webauthn_id' do + expect { get :options }.to_not change { user.webauthn_id } + end + + it "includes existing credentials in list of excluded credentials" do + get :options + + excluded_credentials_ids = JSON.parse(response.body)['excludeCredentials'].map { |credential| credential['id'] } + expect(excluded_credentials_ids).to match_array(user.webauthn_credentials.pluck(:external_id)) + end + end + + context 'when user does not have webauthn enabled' do + it 'returns http success' do + get :options + + expect(response).to have_http_status(200) + end + + it 'stores the challenge on the session' do + get :options + + expect(@controller.session[:webauthn_challenge]).to be_present + end + + it 'sets user webauthn_id' do + get :options + + expect(user.reload.webauthn_id).to be_present + end + end + end + + context 'when user has not enabled otp' do + before do + user.update(otp_required_for_login: false) + end + + it 'requires otp enabled first' do + get :options + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when not signed in' do + it 'redirects to login' do + get :options + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe 'POST #create' do + let(:nickname) { 'SecurityKeyNickname' } + + let(:challenge) do + WebAuthn::Credential.options_for_create( + user: { id: user.id, name: user.account.username, display_name: user.account.display_name } + ).challenge + end + + let(:new_webauthn_credential) { fake_client.create(challenge: challenge) } + + context 'when signed in' do + before do + sign_in user, scope: :user + end + + context 'when user has enabled otp' do + before do + user.update(otp_required_for_login: true) + end + + context 'when user has enabled webauthn' do + before do + user.update(webauthn_id: WebAuthn.generate_user_id) + add_webauthn_credential(user) + end + + context 'when creation succeeds' do + it 'returns http success' do + @controller.session[:webauthn_challenge] = challenge + + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + + expect(response).to have_http_status(200) + end + + it 'adds a new credential to user credentials' do + @controller.session[:webauthn_challenge] = challenge + + expect do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + end.to change { user.webauthn_credentials.count }.by(1) + end + + it 'does not change webauthn_id' do + @controller.session[:webauthn_challenge] = challenge + + expect do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + end.to_not change { user.webauthn_id } + end + end + + context 'when the nickname is already used' do + it 'fails' do + @controller.session[:webauthn_challenge] = challenge + + post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' } + + expect(response).to have_http_status(500) + expect(flash[:error]).to be_present + end + end + + context 'when the credential already exists' do + before do + user2 = Fabricate(:user) + public_key_credential = WebAuthn::Credential.from_create(new_webauthn_credential) + Fabricate(:webauthn_credential, + user_id: user2.id, + external_id: public_key_credential.id, + public_key: public_key_credential.public_key) + end + + it 'fails' do + @controller.session[:webauthn_challenge] = challenge + + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + + expect(response).to have_http_status(500) + expect(flash[:error]).to be_present + end + end + end + + context 'when user have not enabled webauthn' do + context 'creation succeeds' do + it 'creates a webauthn credential' do + @controller.session[:webauthn_challenge] = challenge + + expect do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + end.to change { user.webauthn_credentials.count }.by(1) + end + end + end + end + + context 'when user has not enabled otp' do + before do + user.update(otp_required_for_login: false) + end + + it 'requires otp enabled first' do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when not signed in' do + it 'redirects to login' do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe 'DELETE #destroy' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + context 'when user has otp enabled' do + before do + user.update(otp_required_for_login: true) + end + + context 'when user has webauthn enabled' do + before do + user.update(webauthn_id: WebAuthn.generate_user_id) + add_webauthn_credential(user) + end + + context 'when deletion succeeds' do + it 'redirects to 2FA methods list and shows flash success' do + delete :destroy, params: { id: user.webauthn_credentials.take.id } + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:success]).to be_present + end + + it 'deletes the credential' do + expect do + delete :destroy, params: { id: user.webauthn_credentials.take.id } + end.to change { user.webauthn_credentials.count }.by(-1) + end + end + end + + context 'when user does not have webauthn enabled' do + it 'redirects to 2FA methods list and shows flash error' do + delete :destroy, params: { id: '1' } + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when user does not have otp enabled' do + it 'requires otp enabled first' do + delete :destroy, params: { id: '1' } + + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:error]).to be_present + end + end + end + + context 'when not signed in' do + it 'redirects to login' do + delete :destroy, params: { id: '1' } + + expect(response).to redirect_to new_user_session_path + end + end + end +end diff --git a/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb b/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..66ffe89f3d81e6c3ad1c12da7f8e467c8f139223 --- /dev/null +++ b/spec/controllers/settings/two_factor_authentication_methods_controller_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Settings::TwoFactorAuthenticationMethodsController do + render_views + + let(:user) { Fabricate(:user) } + + describe 'GET #index' do + context 'when signed in' do + before do + sign_in user, scope: :user + end + + describe 'when user has enabled otp' do + before do + user.update(otp_required_for_login: true) + end + + it 'returns http success' do + get :index + + expect(response).to have_http_status(200) + end + end + + describe 'when user has not enabled otp' do + before do + user.update(otp_required_for_login: false) + end + + it 'redirects to enable otp' do + get :index + + expect(response).to redirect_to(settings_otp_authentication_path) + end + end + end + + context 'when not signed in' do + it 'redirects' do + get :index + + expect(response).to redirect_to '/auth/sign_in' + end + end + end +end diff --git a/spec/controllers/settings/two_factor_authentications_controller_spec.rb b/spec/controllers/settings/two_factor_authentications_controller_spec.rb deleted file mode 100644 index 9df9763fd33bd848db890502e20d45da159b848e..0000000000000000000000000000000000000000 --- a/spec/controllers/settings/two_factor_authentications_controller_spec.rb +++ /dev/null @@ -1,125 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Settings::TwoFactorAuthenticationsController do - render_views - - let(:user) { Fabricate(:user) } - - describe 'GET #show' do - context 'when signed in' do - before do - sign_in user, scope: :user - end - - describe 'when user requires otp for login already' do - it 'returns http success' do - user.update(otp_required_for_login: true) - get :show - - expect(response).to have_http_status(200) - end - end - - describe 'when user does not require otp for login' do - it 'returns http success' do - user.update(otp_required_for_login: false) - get :show - - expect(response).to have_http_status(200) - end - end - end - - context 'when not signed in' do - it 'redirects' do - get :show - expect(response).to redirect_to '/auth/sign_in' - end - end - end - - describe 'POST #create' do - context 'when signed in' do - before do - sign_in user, scope: :user - end - - describe 'when user requires otp for login already' do - it 'redirects to show page' do - user.update(otp_required_for_login: true) - post :create - - expect(response).to redirect_to(settings_two_factor_authentication_path) - end - end - - describe 'when creation succeeds' do - it 'updates user secret' do - before = user.otp_secret - post :create, session: { challenge_passed_at: Time.now.utc } - - expect(user.reload.otp_secret).not_to eq(before) - expect(response).to redirect_to(new_settings_two_factor_authentication_confirmation_path) - end - end - end - - context 'when not signed in' do - it 'redirects' do - get :show - expect(response).to redirect_to '/auth/sign_in' - end - end - end - - describe 'POST #destroy' do - before do - user.update(otp_required_for_login: true) - end - - context 'when signed in' do - before do - sign_in user, scope: :user - end - - it 'turns off otp requirement with correct code' do - expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg| - expect(value).to eq user - expect(arg).to eq '123456' - true - end - - post :destroy, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } - - expect(response).to redirect_to(settings_two_factor_authentication_path) - user.reload - expect(user.otp_required_for_login).to eq(false) - end - - it 'does not turn off otp if code is incorrect' do - expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg| - expect(value).to eq user - expect(arg).to eq '057772' - false - end - - post :destroy, params: { form_two_factor_confirmation: { otp_attempt: '057772' } } - - user.reload - expect(user.otp_required_for_login).to eq(true) - end - - it 'raises ActionController::ParameterMissing if code is missing' do - post :destroy - expect(response).to have_http_status(400) - end - end - - it 'redirects if not signed in' do - get :show - expect(response).to redirect_to '/auth/sign_in' - end - end -end diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb index ba1f1370a631e521df5071587cae1fceb47ac565..9986efa51d27d9ca504fb1dc5acaeb919fc26039 100644 --- a/spec/controllers/statuses_controller_spec.rb +++ b/spec/controllers/statuses_controller_spec.rb @@ -5,14 +5,30 @@ require 'rails_helper' describe StatusesController do render_views + shared_examples 'cachable response' do + it 'does not set cookies' do + expect(response.cookies).to be_empty + expect(response.headers['Set-Cookies']).to be nil + end + + it 'does not set sessions' do + expect(session).to be_empty + end + + it 'returns public Cache-Control header' do + expect(response.headers['Cache-Control']).to include 'public' + end + end + describe 'GET #show' do let(:account) { Fabricate(:account) } let(:status) { Fabricate(:status, account: account) } - context 'when account is suspended' do - let(:account) { Fabricate(:account, suspended: true) } - + context 'when account is permanently suspended' do before do + account.suspend! + account.deletion_request.destroy + get :show, params: { account_username: account.username, id: status.id } end @@ -21,6 +37,18 @@ describe StatusesController do end end + context 'when account is temporarily suspended' do + before do + account.suspend! + + get :show, params: { account_username: account.username, id: status.id } + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + context 'when status is a reblog' do let(:original_account) { Fabricate(:account, domain: 'example.com') } let(:original_status) { Fabricate(:status, account: original_account, url: 'https://example.com/123') } @@ -80,9 +108,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' @@ -470,9 +496,7 @@ describe StatusesController do expect(response.headers['Vary']).to eq 'Accept' end - it 'returns public Cache-Control header' do - expect(response.headers['Cache-Control']).to include 'public' - end + it_behaves_like 'cachable response' it 'returns Content-Type header' do expect(response.headers['Content-Type']).to include 'application/activity+json' @@ -665,10 +689,11 @@ describe StatusesController do let(:account) { Fabricate(:account) } let(:status) { Fabricate(:status, account: account) } - context 'when account is suspended' do - let(:account) { Fabricate(:account, suspended: true) } - + context 'when account is permanently suspended' do before do + account.suspend! + account.deletion_request.destroy + get :activity, params: { account_username: account.username, id: status.id } end @@ -677,6 +702,18 @@ describe StatusesController do end end + context 'when account is temporarily suspended' do + before do + account.suspend! + + get :activity, params: { account_username: account.username, id: status.id } + end + + it 'returns http forbidden' do + expect(response).to have_http_status(403) + end + end + context 'when status is public' do pending end diff --git a/spec/controllers/well_known/host_meta_controller_spec.rb b/spec/controllers/well_known/host_meta_controller_spec.rb index b43ae19d87a2922d202cd65357e7496c0bf52c7d..643ba9cd3283aa1b1df379a428364a69395c263e 100644 --- a/spec/controllers/well_known/host_meta_controller_spec.rb +++ b/spec/controllers/well_known/host_meta_controller_spec.rb @@ -12,7 +12,7 @@ describe WellKnown::HostMetaController, type: :controller do expect(response.body).to eq <<XML <?xml version="1.0" encoding="UTF-8"?> <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"> - <Link rel="lrdd" type="application/xrd+xml" template="https://cb6e6126.ngrok.io/.well-known/webfinger?resource={uri}"/> + <Link rel="lrdd" template="https://cb6e6126.ngrok.io/.well-known/webfinger?resource={uri}"/> </XRD> XML end diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb index 46f63185b9ec7c530d55d7bcab9407eba9052f22..cf7005b0e79a315b70557b178602093d7b5d46cc 100644 --- a/spec/controllers/well_known/webfinger_controller_spec.rb +++ b/spec/controllers/well_known/webfinger_controller_spec.rb @@ -4,95 +4,134 @@ describe WellKnown::WebfingerController, type: :controller do render_views describe 'GET #show' do - let(:alice) do - Fabricate(:account, username: 'alice') + let(:alternate_domains) { [] } + let(:alice) { Fabricate(:account, username: 'alice') } + let(:resource) { nil } + + around(:each) do |example| + tmp = Rails.configuration.x.alternate_domains + Rails.configuration.x.alternate_domains = alternate_domains + example.run + Rails.configuration.x.alternate_domains = tmp end - before do - alice.private_key = <<-PEM ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDHgPoPJlrfMZrVcuF39UbVssa8r4ObLP3dYl9Y17Mgp5K4mSYD -R/Y2ag58tSi6ar2zM3Ze3QYsNfTq0NqN1g89eAu0MbSjWqpOsgntRPJiFuj3hai2 -X2Im8TBrkiM/UyfTRgn8q8WvMoKbXk8Lu6nqv420eyqhhLxfUoCpxuem1QIDAQAB -AoGBAIKsOh2eM7spVI8mdgQKheEG/iEsnPkQ2R8ehfE9JzjmSbXbqghQJDaz9NU+ -G3Uu4R31QT0VbCudE9SSA/UPFl82GeQG4QLjrSE+PSjSkuslgSXelJHfAJ+ycGax -ajtPyiQD0e4c2loagHNHPjqK9OhHx9mFnZWmoagjlZ+mQGEpAkEA8GtqfS65IaRQ -uVhMzpp25rF1RWOwaaa+vBPkd7pGdJEQGFWkaR/a9UkU+2C4ZxGBkJDP9FApKVQI -RANEwN3/hwJBANRuw5+es6BgBv4PD387IJvuruW2oUtYP+Lb2Z5k77J13hZTr0db -Oo9j1UbbR0/4g+vAcsDl4JD9c/9LrGYEpcMCQBon9Yvs+2M3lziy7JhFoc3zXIjS -Ea1M4M9hcqe78lJYPeIH3z04o/+vlcLLgQRlmSz7NESmO/QtGkEcAezhuh0CQHji -pzO4LeO/gXslut3eGcpiYuiZquOjToecMBRwv+5AIKd367Che4uJdh6iPcyGURvh -IewfZFFdyZqnx20ui90CQQC1W2rK5Y30wAunOtSLVA30TLK/tKrTppMC3corjKlB -FTX8IvYBNTbpEttc1VCf/0ccnNpfb0CrFNSPWxRj7t7D ------END RSA PRIVATE KEY----- -PEM - - alice.public_key = <<-PEM ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHgPoPJlrfMZrVcuF39UbVssa8 -r4ObLP3dYl9Y17Mgp5K4mSYDR/Y2ag58tSi6ar2zM3Ze3QYsNfTq0NqN1g89eAu0 -MbSjWqpOsgntRPJiFuj3hai2X2Im8TBrkiM/UyfTRgn8q8WvMoKbXk8Lu6nqv420 -eyqhhLxfUoCpxuem1QIDAQAB ------END PUBLIC KEY----- -PEM - - alice.save! + subject do + get :show, params: { resource: resource }, format: :json end - around(:each) do |example| - before = Rails.configuration.x.alternate_domains - example.run - Rails.configuration.x.alternate_domains = before + shared_examples 'a successful response' do + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'returns application/jrd+json' do + expect(response.content_type).to eq 'application/jrd+json' + end + + it 'returns links for the account' do + json = body_as_json + expect(json[:subject]).to eq 'acct:alice@cb6e6126.ngrok.io' + expect(json[:aliases]).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice') + end end - it 'returns JSON when account can be found' do - get :show, params: { resource: alice.to_webfinger_s }, format: :json + context 'when an account exists' do + let(:resource) { alice.to_webfinger_s } - json = body_as_json + before do + subject + end - expect(response).to have_http_status(200) - expect(response.content_type).to eq 'application/jrd+json' - expect(json[:subject]).to eq 'acct:alice@cb6e6126.ngrok.io' - expect(json[:aliases]).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice') + it_behaves_like 'a successful response' end - it 'returns http not found when account cannot be found' do - get :show, params: { resource: 'acct:not@existing.com' }, format: :json + context 'when an account is temporarily suspended' do + let(:resource) { alice.to_webfinger_s } - expect(response).to have_http_status(:not_found) + before do + alice.suspend! + subject + end + + it_behaves_like 'a successful response' end - it 'returns JSON when account can be found with alternate domains' do - Rails.configuration.x.alternate_domains = ['foo.org'] - username, = alice.to_webfinger_s.split('@') + context 'when an account is permanently suspended or deleted' do + let(:resource) { alice.to_webfinger_s } + + before do + alice.suspend! + alice.deletion_request.destroy + subject + end - get :show, params: { resource: "#{username}@foo.org" }, format: :json + it 'returns http gone' do + expect(response).to have_http_status(410) + end + end + + context 'when an account is not found' do + let(:resource) { 'acct:not@existing.com' } - json = body_as_json + before do + subject + end - expect(response).to have_http_status(200) - expect(response.content_type).to eq 'application/jrd+json' - expect(json[:subject]).to eq 'acct:alice@cb6e6126.ngrok.io' - expect(json[:aliases]).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice') + it 'returns http not found' do + expect(response).to have_http_status(404) + end end - it 'returns http not found when account can not be found with alternate domains' do - Rails.configuration.x.alternate_domains = ['foo.org'] - username, = alice.to_webfinger_s.split('@') + context 'with an alternate domain' do + let(:alternate_domains) { ['foo.org'] } + + before do + subject + end + + context 'when an account exists' do + let(:resource) do + username, = alice.to_webfinger_s.split('@') + "#{username}@foo.org" + end + + it_behaves_like 'a successful response' + end - get :show, params: { resource: "#{username}@bar.org" }, format: :json + context 'when the domain is wrong' do + let(:resource) do + username, = alice.to_webfinger_s.split('@') + "#{username}@bar.org" + end - expect(response).to have_http_status(:not_found) + it 'returns http not found' do + expect(response).to have_http_status(404) + end + end end - it 'returns http bad request when not given a resource parameter' do - get :show, params: { }, format: :json - expect(response).to have_http_status(:bad_request) + context 'with no resource parameter' do + let(:resource) { nil } + + before do + subject + end + + it 'returns http bad request' do + expect(response).to have_http_status(400) + end end - it 'returns http bad request when given a nonsense parameter' do - get :show, params: { resource: 'df/:dfkj' } - expect(response).to have_http_status(:bad_request) + context 'with a nonsense parameter' do + let(:resource) { 'df/:dfkj' } + + before do + subject + end + + it 'returns http bad request' do + expect(response).to have_http_status(400) + end end end end diff --git a/spec/fabricators/account_deletion_request_fabricator.rb b/spec/fabricators/account_deletion_request_fabricator.rb new file mode 100644 index 0000000000000000000000000000000000000000..08a82ba3c3363331207214945af35cb5f474eaa5 --- /dev/null +++ b/spec/fabricators/account_deletion_request_fabricator.rb @@ -0,0 +1,3 @@ +Fabricator(:account_deletion_request) do + account +end diff --git a/spec/fabricators/ip_block_fabricator.rb b/spec/fabricators/ip_block_fabricator.rb new file mode 100644 index 0000000000000000000000000000000000000000..31dc336e64be30e20ef7ee69a01479b80eb44f9a --- /dev/null +++ b/spec/fabricators/ip_block_fabricator.rb @@ -0,0 +1,6 @@ +Fabricator(:ip_block) do + ip "" + severity "" + expires_at "2020-10-08 22:20:37" + comment "MyText" +end \ No newline at end of file diff --git a/spec/fabricators/webauthn_credential_fabricator.rb b/spec/fabricators/webauthn_credential_fabricator.rb new file mode 100644 index 0000000000000000000000000000000000000000..496a7a7351bb8108d30f1e43cc6b01b75d98c325 --- /dev/null +++ b/spec/fabricators/webauthn_credential_fabricator.rb @@ -0,0 +1,7 @@ +Fabricator(:webauthn_credential) do + user_id { Fabricate(:user).id } + external_id { Base64.urlsafe_encode64(SecureRandom.random_bytes(16)) } + public_key { OpenSSL::PKey::EC.new("prime256v1").generate_key.public_key } + nickname 'USB key' + sign_count 0 +end diff --git a/spec/fixtures/files/bookmark-imports.txt b/spec/fixtures/files/bookmark-imports.txt new file mode 100644 index 0000000000000000000000000000000000000000..7cc8901a0ac0711981d2cd34ad8575b9f70ab2d1 --- /dev/null +++ b/spec/fixtures/files/bookmark-imports.txt @@ -0,0 +1,4 @@ +https://example.com/statuses/1312 +https://local.com/users/foo/statuses/42 +https://unknown-remote.com/users/bar/statuses/1 +https://example.com/statuses/direct diff --git a/spec/helpers/statuses_helper_spec.rb b/spec/helpers/statuses_helper_spec.rb index 940ff072e602ff1e840a806f31bec1d19b67b3fb..cba659bfb5bc05ad099b20b127e26c8fe999dc1b 100644 --- a/spec/helpers/statuses_helper_spec.rb +++ b/spec/helpers/statuses_helper_spec.rb @@ -149,22 +149,4 @@ RSpec.describe StatusesHelper, type: :helper do expect(css_class).to eq 'h-cite' end end - - describe '#rtl?' do - it 'is false if text is empty' do - expect(helper).not_to be_rtl '' - end - - it 'is false if there are no right to left characters' do - expect(helper).not_to be_rtl 'hello world' - end - - it 'is false if right to left characters are fewer than 1/3 of total text' do - expect(helper).not_to be_rtl 'hello ÝŸ world' - end - - it 'is true if right to left characters are greater than 1/3 of total text' do - expect(helper).to be_rtl 'aaÝŸaaÝŸ' - end - end end diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb index 60fd96a18ac69d2687698bf0ed756d1af5bdd4f3..b93fcbe66563a2f20386b88d0ce8a84e93c21c2f 100644 --- a/spec/lib/activitypub/activity/announce_spec.rb +++ b/spec/lib/activitypub/activity/announce_spec.rb @@ -73,6 +73,26 @@ RSpec.describe ActivityPub::Activity::Announce do expect(sender.reblogged?(sender.statuses.first)).to be true end end + + context 'self-boost of a previously unknown status with correct attributedTo, inlined Collection in audience' do + let(:object_json) do + { + id: 'https://example.com/actor#bar', + type: 'Note', + content: 'Lorem ipsum', + attributedTo: 'https://example.com/actor', + to: { + 'type': 'OrderedCollection', + 'id': 'http://example.com/followers', + 'first': 'http://example.com/followers?page=true', + } + } + end + + it 'creates a reblog by sender of status' do + expect(sender.reblogged?(sender.statuses.first)).to be true + end + end end context 'when the status belongs to a local user' do diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 94d37356dd14c23a98436a65f00161689d8d6554..42bdfdc810ef6ff23b774d246a3eed75122191d3 100644 --- a/spec/lib/activitypub/activity/block_spec.rb +++ b/spec/lib/activitypub/activity/block_spec.rb @@ -28,6 +28,28 @@ RSpec.describe ActivityPub::Activity::Block do end end + context 'when the recipient is already blocked' do + before do + sender.block!(recipient, uri: 'old') + end + + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'creates a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be true + end + + it 'sets the uri to that of last received block activity' do + expect(sender.block_relationships.find_by(target_account: recipient).uri).to eq 'foo' + end + end + end + context 'when the recipient follows the sender' do before do recipient.follow!(sender) diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 2ac4acc12aa7be60e3a7820a64a4c14423c89d46..d2e9fe33ce4cfebb8bcd331d8ee9bb155f609616 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -18,6 +18,7 @@ RSpec.describe ActivityPub::Activity::Create do stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt')) stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png')) + stub_request(:get, 'http://example.com/emojib.png').to_return(body: attachment_fixture('emojo.png'), headers: { 'Content-Type' => 'application/octet-stream' }) end describe '#perform' do @@ -120,6 +121,28 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'private with inlined Collection in audience' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: { + 'type': 'OrderedCollection', + 'id': 'http://example.com/followers', + 'first': 'http://example.com/followers?page=true', + } + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'private' + end + end + context 'limited' do let(:recipient) { Fabricate(:account) } @@ -451,6 +474,32 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'with emojis served with invalid content-type' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum :tinkong:', + tag: [ + { + type: 'Emoji', + icon: { + url: 'http://example.com/emojib.png', + }, + name: 'tinkong', + }, + ], + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.emojis.map(&:shortcode)).to include('tinkong') + end + end + context 'with emojis missing name' do let(:object_json) do { diff --git a/spec/lib/activitypub/activity/reject_spec.rb b/spec/lib/activitypub/activity/reject_spec.rb index e7205df8dd6dcb30bfd18c304ef1fecdc4dd3917..fed4cd8cdc47eb61608748793dd25a0d90e758a8 100644 --- a/spec/lib/activitypub/activity/reject_spec.rb +++ b/spec/lib/activitypub/activity/reject_spec.rb @@ -3,6 +3,14 @@ require 'rails_helper' RSpec.describe ActivityPub::Activity::Reject do let(:sender) { Fabricate(:account) } let(:recipient) { Fabricate(:account) } + let(:object_json) do + { + id: 'bar', + type: 'Follow', + actor: ActivityPub::TagManager.instance.uri_for(recipient), + object: ActivityPub::TagManager.instance.uri_for(sender), + } + end let(:json) do { @@ -10,29 +18,105 @@ RSpec.describe ActivityPub::Activity::Reject do id: 'foo', type: 'Reject', actor: ActivityPub::TagManager.instance.uri_for(sender), - object: { - id: 'bar', - type: 'Follow', - actor: ActivityPub::TagManager.instance.uri_for(recipient), - object: ActivityPub::TagManager.instance.uri_for(sender), - }, + object: object_json, }.with_indifferent_access end describe '#perform' do subject { described_class.new(json, sender) } - before do - Fabricate(:follow_request, account: recipient, target_account: sender) - subject.perform + context 'rejecting a pending follow request by target' do + before do + Fabricate(:follow_request, account: recipient, target_account: sender) + subject.perform + end + + it 'does not create a follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'removes the follow request' do + expect(recipient.requested?(sender)).to be false + end + end + + context 'rejecting a pending follow request by uri' do + before do + Fabricate(:follow_request, account: recipient, target_account: sender, uri: 'bar') + subject.perform + end + + it 'does not create a follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'removes the follow request' do + expect(recipient.requested?(sender)).to be false + end end - it 'does not create a follow relationship' do - expect(recipient.following?(sender)).to be false + context 'rejecting a pending follow request by uri only' do + let(:object_json) { 'bar' } + + before do + Fabricate(:follow_request, account: recipient, target_account: sender, uri: 'bar') + subject.perform + end + + it 'does not create a follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'removes the follow request' do + expect(recipient.requested?(sender)).to be false + end end - it 'removes the follow request' do - expect(recipient.requested?(sender)).to be false + context 'rejecting an existing follow relationship by target' do + before do + Fabricate(:follow, account: recipient, target_account: sender) + subject.perform + end + + it 'removes the follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'does not create a follow request' do + expect(recipient.requested?(sender)).to be false + end + end + + context 'rejecting an existing follow relationship by uri' do + before do + Fabricate(:follow, account: recipient, target_account: sender, uri: 'bar') + subject.perform + end + + it 'removes the follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'does not create a follow request' do + expect(recipient.requested?(sender)).to be false + end + end + + context 'rejecting an existing follow relationship by uri only' do + let(:object_json) { 'bar' } + + before do + Fabricate(:follow, account: recipient, target_account: sender, uri: 'bar') + subject.perform + end + + it 'removes the follow relationship' do + expect(recipient.following?(sender)).to be false + end + + it 'does not create a follow request' do + expect(recipient.requested?(sender)).to be false + end end end diff --git a/spec/lib/activitypub/activity/undo_spec.rb b/spec/lib/activitypub/activity/undo_spec.rb index 9545e1f46af6b98ba924ad53b5e84f2e2cc7ebdb..c0309e49dafcee0f6f523ec14957f4815d7b1f67 100644 --- a/spec/lib/activitypub/activity/undo_spec.rb +++ b/spec/lib/activitypub/activity/undo_spec.rb @@ -50,6 +50,19 @@ RSpec.describe ActivityPub::Activity::Undo do expect(sender.reblogged?(status)).to be false end end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + before do + Fabricate(:status, reblog: status, account: sender, uri: 'bar') + end + + it 'deletes the reblog by uri' do + subject.perform + expect(sender.reblogged?(status)).to be false + end + end end context 'with Accept' do @@ -91,13 +104,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.block!(recipient) + sender.block!(recipient, uri: 'bar') end it 'deletes block from sender to recipient' do subject.perform expect(sender.blocking?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes block from sender to recipient' do + subject.perform + expect(sender.blocking?(recipient)).to be false + end + end end context 'with Follow' do @@ -113,13 +135,22 @@ RSpec.describe ActivityPub::Activity::Undo do end before do - sender.follow!(recipient) + sender.follow!(recipient, uri: 'bar') end it 'deletes follow from sender to recipient' do subject.perform expect(sender.following?(recipient)).to be false end + + context 'with only object uri' do + let(:object_json) { 'bar' } + + it 'deletes follow from sender to recipient' do + subject.perform + expect(sender.following?(recipient)).to be false + end + end end context 'with Like' do diff --git a/spec/lib/activitypub/dereferencer_spec.rb b/spec/lib/activitypub/dereferencer_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ce30513d762219f99aa34351a4207f4c61b11b3f --- /dev/null +++ b/spec/lib/activitypub/dereferencer_spec.rb @@ -0,0 +1,73 @@ +require 'rails_helper' + +RSpec.describe ActivityPub::Dereferencer do + describe '#object' do + let(:object) { { '@context': 'https://www.w3.org/ns/activitystreams', id: 'https://example.com/foo', type: 'Note', content: 'Hoge' } } + let(:permitted_origin) { 'https://example.com' } + let(:signature_account) { nil } + let(:uri) { nil } + + subject { described_class.new(uri, permitted_origin: permitted_origin, signature_account: signature_account).object } + + before do + stub_request(:get, 'https://example.com/foo').to_return(body: Oj.dump(object), headers: { 'Content-Type' => 'application/activity+json' }) + end + + context 'with a URI' do + let(:uri) { 'https://example.com/foo' } + + it 'returns object' do + expect(subject.with_indifferent_access).to eq object.with_indifferent_access + end + + context 'with signature account' do + let(:signature_account) { Fabricate(:account) } + + it 'makes signed request' do + subject + expect(a_request(:get, 'https://example.com/foo').with { |req| req.headers['Signature'].present? }).to have_been_made + end + end + + context 'with different origin' do + let(:uri) { 'https://other-example.com/foo' } + + it 'does not make request' do + subject + expect(a_request(:get, 'https://other-example.com/foo')).to_not have_been_made + end + end + end + + context 'with a bearcap' do + let(:uri) { 'bear:?t=hoge&u=https://example.com/foo' } + + it 'makes request with Authorization header' do + subject + expect(a_request(:get, 'https://example.com/foo').with(headers: { 'Authorization' => 'Bearer hoge' })).to have_been_made + end + + it 'returns object' do + expect(subject.with_indifferent_access).to eq object.with_indifferent_access + end + + context 'with signature account' do + let(:signature_account) { Fabricate(:account) } + + it 'makes signed request' do + subject + expect(a_request(:get, 'https://example.com/foo').with { |req| req.headers['Signature'].present? && req.headers['Authorization'] == 'Bearer hoge' }).to have_been_made + end + end + + context 'with different origin' do + let(:uri) { 'bear:?t=hoge&u=https://other-example.com/foo' } + + it 'does not make request' do + subject + expect(a_request(:get, 'https://other-example.com/foo')).to_not have_been_made + end + end + end + end +end diff --git a/spec/lib/fast_ip_map_spec.rb b/spec/lib/fast_ip_map_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c66f64828ac551b0485e03b540e994b733ba9561 --- /dev/null +++ b/spec/lib/fast_ip_map_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe FastIpMap do + describe '#include?' do + subject { described_class.new([IPAddr.new('20.4.0.0/16'), IPAddr.new('145.22.30.0/24'), IPAddr.new('189.45.86.3')])} + + it 'returns true for an exact match' do + expect(subject.include?(IPAddr.new('189.45.86.3'))).to be true + end + + it 'returns true for a range match' do + expect(subject.include?(IPAddr.new('20.4.45.7'))).to be true + end + + it 'returns false for no match' do + expect(subject.include?(IPAddr.new('145.22.40.64'))).to be false + end + end +end diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 22eddd2ab6e3196771f8e9da9aca2d3b9b987218..0df85e5bcbb64968c81037b97037d4cb95b889c6 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -29,14 +29,14 @@ RSpec.describe FeedManager do it 'returns false for followee\'s status' do status = Fabricate(:status, text: 'Hello world', account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, status, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, status, bob)).to be false end it 'returns false for reblog by followee' do status = Fabricate(:status, text: 'Hello world', account: jeff) reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, reblog, bob)).to be false end it 'returns true for reblog by followee of blocked account' do @@ -44,7 +44,7 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) bob.block!(jeff) - expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog by followee of muted account' do @@ -52,7 +52,7 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) bob.mute!(jeff) - expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog by followee of someone who is blocking recipient' do @@ -60,14 +60,14 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) jeff.block!(bob) - expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog from account with reblogs disabled' do status = Fabricate(:status, text: 'Hello world', account: jeff) reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice, reblogs: false) - expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, reblog, bob)).to be true end it 'returns false for reply by followee to another followee' do @@ -75,48 +75,49 @@ RSpec.describe FeedManager do reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) bob.follow!(jeff) - expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, reply, bob)).to be false end it 'returns false for reply by followee to recipient' do status = Fabricate(:status, text: 'Hello world', account: bob) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, reply, bob)).to be false end it 'returns false for reply by followee to self' do status = Fabricate(:status, text: 'Hello world', account: alice) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, reply, bob)).to be false end it 'returns true for reply by followee to non-followed account' do status = Fabricate(:status, text: 'Hello world', account: jeff) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, reply, bob)).to be true end it 'returns true for the second reply by followee to a non-federated status' do reply = Fabricate(:status, text: 'Reply 1', reply: true, account: alice) second_reply = Fabricate(:status, text: 'Reply 2', thread: reply, account: alice) bob.follow!(alice) - expect(FeedManager.instance.filter?(:home, second_reply, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, second_reply, bob)).to be true end it 'returns false for status by followee mentioning another account' do bob.follow!(alice) + jeff.follow!(alice) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(FeedManager.instance.filter?(:home, status, bob.id)).to be false + expect(FeedManager.instance.filter?(:home, status, bob)).to be false end it 'returns true for status by followee mentioning blocked account' do bob.block!(jeff) bob.follow!(alice) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(FeedManager.instance.filter?(:home, status, bob.id)).to be true + expect(FeedManager.instance.filter?(:home, status, bob)).to be true end it 'returns true for reblog of a personally blocked domain' do @@ -124,7 +125,7 @@ RSpec.describe FeedManager do alice.follow!(jeff) status = Fabricate(:status, text: 'Hello world', account: bob) reblog = Fabricate(:status, reblog: status, account: jeff) - expect(FeedManager.instance.filter?(:home, reblog, alice.id)).to be true + expect(FeedManager.instance.filter?(:home, reblog, alice)).to be true end context 'for irreversibly muted phrases' do @@ -132,7 +133,7 @@ RSpec.describe FeedManager do alice.custom_filters.create!(phrase: 'bob', context: %w(home), irreversible: true) alice.follow!(jeff) status = Fabricate(:status, text: 'bobcats', account: jeff) - expect(FeedManager.instance.filter?(:home, status, alice.id)).to be_falsy + expect(FeedManager.instance.filter?(:home, status, alice)).to be_falsy end it 'returns true if phrase is contained' do @@ -140,14 +141,14 @@ RSpec.describe FeedManager do alice.custom_filters.create!(phrase: 'pop tarts', context: %w(home), irreversible: true) alice.follow!(jeff) status = Fabricate(:status, text: 'i sure like POP TARts', account: jeff) - expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true + expect(FeedManager.instance.filter?(:home, status, alice)).to be true end it 'matches substrings if whole_word is false' do alice.custom_filters.create!(phrase: 'take', context: %w(home), whole_word: false, irreversible: true) alice.follow!(jeff) status = Fabricate(:status, text: 'shiitake', account: jeff) - expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true + expect(FeedManager.instance.filter?(:home, status, alice)).to be true end it 'returns true if phrase is contained in a poll option' do @@ -155,7 +156,7 @@ RSpec.describe FeedManager do alice.custom_filters.create!(phrase: 'pop tarts', context: %w(home), irreversible: true) alice.follow!(jeff) status = Fabricate(:status, text: 'what do you prefer', poll: Fabricate(:poll, options: %w(farts POP TARts)), account: jeff) - expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true + expect(FeedManager.instance.filter?(:home, status, alice)).to be true end end end @@ -164,27 +165,27 @@ RSpec.describe FeedManager do it 'returns true for status that mentions blocked account' do bob.block!(jeff) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be true + expect(FeedManager.instance.filter?(:mentions, status, bob)).to be true end it 'returns true for status that replies to a blocked account' do status = Fabricate(:status, text: 'Hello world', account: jeff) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.block!(jeff) - expect(FeedManager.instance.filter?(:mentions, reply, bob.id)).to be true + expect(FeedManager.instance.filter?(:mentions, reply, bob)).to be true end it 'returns true for status by silenced account who recipient is not following' do status = Fabricate(:status, text: 'Hello world', account: alice) alice.silence! - expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be true + expect(FeedManager.instance.filter?(:mentions, status, bob)).to be true end it 'returns false for status by followed silenced account' do status = Fabricate(:status, text: 'Hello world', account: alice) alice.silence! bob.follow!(alice) - expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be false + expect(FeedManager.instance.filter?(:mentions, status, bob)).to be false end end end @@ -309,62 +310,125 @@ RSpec.describe FeedManager do end describe '#push_to_list' do + let(:owner) { Fabricate(:account, username: 'owner') } + let(:alice) { Fabricate(:account, username: 'alice') } + let(:bob) { Fabricate(:account, username: 'bob') } + let(:eve) { Fabricate(:account, username: 'eve') } + let(:list) { Fabricate(:list, account: owner) } + + before do + owner.follow!(alice) + owner.follow!(bob) + owner.follow!(eve) + + list.accounts << alice + list.accounts << bob + end + it "does not push when the given status's reblog is already inserted" do - list = Fabricate(:list) reblog = Fabricate(:status) status = Fabricate(:status, reblog: reblog) FeedManager.instance.push_to_list(list, status) expect(FeedManager.instance.push_to_list(list, reblog)).to eq false end - end - describe '#merge_into_timeline' do - it "does not push source account's statuses whose reblogs are already inserted" do - account = Fabricate(:account, id: 0) - reblog = Fabricate(:status) - status = Fabricate(:status, reblog: reblog) - FeedManager.instance.push_to_home(account, status) + context 'when replies policy is set to no replies' do + before do + list.replies_policy = :none + end - FeedManager.instance.merge_into_timeline(account, reblog.account) + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end - expect(Redis.current.zscore("feed:home:0", reblog.id)).to eq nil + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'does not push replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq false + end end - end - describe '#trim' do - let(:receiver) { Fabricate(:account) } + context 'when replies policy is set to list-only replies' do + before do + list.replies_policy = :list + end - it 'cleans up reblog tracking keys' do - reblogged = Fabricate(:status) - status = Fabricate(:status, reblog: reblogged) - another_status = Fabricate(:status, reblog: reblogged) - reblogs_key = FeedManager.instance.key('home', receiver.id, 'reblogs') - reblog_set_key = FeedManager.instance.key('home', receiver.id, "reblogs:#{reblogged.id}") + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end - FeedManager.instance.push_to_home(receiver, status) - FeedManager.instance.push_to_home(receiver, another_status) + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end - # We should have a tracking set and an entry in reblogs. - expect(Redis.current.exists(reblog_set_key)).to be true - expect(Redis.current.zrange(reblogs_key, 0, -1)).to eq [reblogged.id.to_s] + it 'pushes replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end - # Push everything off the end of the feed. - FeedManager::MAX_ITEMS.times do - FeedManager.instance.push_to_home(receiver, Fabricate(:status)) + it 'does not push replies to someone not a member of the list' do + status = Fabricate(:status, text: 'Hello world', account: eve) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq false end + end - # `trim` should be called automatically, but do it anyway, as - # we're testing `trim`, not side effects of `push`. - FeedManager.instance.trim('home', receiver.id) + context 'when replies policy is set to any reply' do + before do + list.replies_policy = :followed + end + + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end + + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'pushes replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end - # We should not have any reblog tracking data. - expect(Redis.current.exists(reblog_set_key)).to be false - expect(Redis.current.zrange(reblogs_key, 0, -1)).to be_empty + it 'pushes replies to someone not a member of the list' do + status = Fabricate(:status, text: 'Hello world', account: eve) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + end + end + + describe '#merge_into_home' do + it "does not push source account's statuses whose reblogs are already inserted" do + account = Fabricate(:account, id: 0) + reblog = Fabricate(:status) + status = Fabricate(:status, reblog: reblog) + FeedManager.instance.push_to_home(account, status) + + FeedManager.instance.merge_into_home(account, reblog.account) + + expect(Redis.current.zscore("feed:home:0", reblog.id)).to eq nil end end - describe '#unpush' do + describe '#unpush_from_home' do let(:receiver) { Fabricate(:account) } it 'leaves a reblogged status if original was on feed' do @@ -430,7 +494,7 @@ RSpec.describe FeedManager do end end - describe '#clear_from_timeline' do + describe '#clear_from_home' do let(:account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) } let(:target_account) { Fabricate(:account) } @@ -448,8 +512,8 @@ RSpec.describe FeedManager do end end - it 'correctly cleans the timeline' do - FeedManager.instance.clear_from_timeline(account, target_account) + it 'correctly cleans the home timeline' do + FeedManager.instance.clear_from_home(account, target_account) expect(Redis.current.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_1.id.to_s, status_7.id.to_s] end diff --git a/spec/lib/spam_check_spec.rb b/spec/lib/spam_check_spec.rb index d4d66a49930737df8fe489c48871d5151e400b4d..159d83257353db4445cede3f043c82e1cb996e25 100644 --- a/spec/lib/spam_check_spec.rb +++ b/spec/lib/spam_check_spec.rb @@ -150,9 +150,9 @@ RSpec.describe SpamCheck do let(:redis_key) { spam_check.send(:redis_key) } it 'remembers' do - expect(Redis.current.exists(redis_key)).to be true + expect(Redis.current.exists?(redis_key)).to be true spam_check.remember! - expect(Redis.current.exists(redis_key)).to be true + expect(Redis.current.exists?(redis_key)).to be true end end @@ -166,9 +166,9 @@ RSpec.describe SpamCheck do end it 'resets' do - expect(Redis.current.exists(redis_key)).to be true + expect(Redis.current.exists?(redis_key)).to be true spam_check.reset! - expect(Redis.current.exists(redis_key)).to be false + expect(Redis.current.exists?(redis_key)).to be false end end diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb index 313666412af308320996a9569287cceffb4420e8..6d87fd706e0be25bbc7135147bfcfa20a2d1a35f 100644 --- a/spec/mailers/previews/user_mailer_preview.rb +++ b/spec/mailers/previews/user_mailer_preview.rb @@ -33,6 +33,28 @@ class UserMailerPreview < ActionMailer::Preview UserMailer.two_factor_recovery_codes_changed(User.first) end + # Preview this email at http://localhost:3000/rails/mailers/user_mailer/webauthn_enabled + def webauthn_enabled + UserMailer.webauthn_enabled(User.first) + end + + # Preview this email at http://localhost:3000/rails/mailers/user_mailer/webauthn_disabled + def webauthn_disabled + UserMailer.webauthn_disabled(User.first) + end + + # Preview this email at http://localhost:3000/rails/mailers/user_mailer/webauthn_credential_added + def webauthn_credential_added + webauthn_credential = WebauthnCredential.new(nickname: 'USB Key') + UserMailer.webauthn_credential_added(User.first, webauthn_credential) + end + + # Preview this email at http://localhost:3000/rails/mailers/user_mailer/webauthn_credential_deleted + def webauthn_credential_deleted + webauthn_credential = WebauthnCredential.new(nickname: 'USB Key') + UserMailer.webauthn_credential_deleted(User.first, webauthn_credential) + end + # Preview this email at http://localhost:3000/rails/mailers/user_mailer/reconfirmation_instructions def reconfirmation_instructions user = User.first diff --git a/spec/models/account_deletion_request_spec.rb b/spec/models/account_deletion_request_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..afaecbe2289eaffd5f2b76063fcfb39e7407db3f --- /dev/null +++ b/spec/models/account_deletion_request_spec.rb @@ -0,0 +1,4 @@ +require 'rails_helper' + +RSpec.describe AccountDeletionRequest, type: :model do +end diff --git a/spec/models/account_filter_spec.rb b/spec/models/account_filter_spec.rb index 176a0eeacd0ce055c8f71f664a689b2553eec8a5..0cdb373f6ac5a3d9cf49869b0df727e02a06e99f 100644 --- a/spec/models/account_filter_spec.rb +++ b/spec/models/account_filter_spec.rb @@ -5,7 +5,7 @@ describe AccountFilter do it 'defaults to recent local not-suspended account list' do filter = described_class.new({}) - expect(filter.results).to eq Account.local.recent.without_suspended + expect(filter.results).to eq Account.local.without_instance_actor.recent.without_suspended end end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 98d29e6f3d37defe194fe2d3d8922ca50e9214ad..1d000ed4d2eb878ea3bc6c8475dd3f8e6b8fd148 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -440,13 +440,6 @@ RSpec.describe Account, type: :model do end end - describe '.domains' do - it 'returns domains' do - Fabricate(:account, domain: 'domain') - expect(Account.remote.domains).to match_array(['domain']) - end - end - describe '#statuses_count' do subject { Fabricate(:account) } @@ -737,20 +730,6 @@ RSpec.describe Account, type: :model do end end - describe 'by_domain_accounts' do - it 'returns accounts grouped by domain sorted by accounts' do - 2.times { Fabricate(:account, domain: 'example.com') } - Fabricate(:account, domain: 'example2.com') - - results = Account.where('id > 0').by_domain_accounts - expect(results.length).to eq 2 - expect(results.first.domain).to eq 'example.com' - expect(results.first.accounts_count).to eq 2 - expect(results.last.domain).to eq 'example2.com' - expect(results.last.accounts_count).to eq 1 - end - end - describe 'local' do it 'returns an array of accounts who do not have a domain' do account_1 = Fabricate(:account, domain: nil) @@ -817,4 +796,27 @@ RSpec.describe Account, type: :model do include_examples 'AccountAvatar', :account include_examples 'AccountHeader', :account + + describe '#increment_count!' do + subject { Fabricate(:account) } + + it 'increments the count in multi-threaded an environment when account_stat is not yet initialized' do + subject + + increment_by = 15 + wait_for_start = true + + threads = Array.new(increment_by) do + Thread.new do + true while wait_for_start + Account.find(subject.id).increment_count!(:followers_count) + end + end + + wait_for_start = false + threads.each(&:join) + + expect(subject.reload.followers_count).to eq 15 + end + end end diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb index 87fc285007867a129ec9a1baae59194cff9194e8..2366b9ca4af23c8dfb1c21b8411ce4217b329423 100644 --- a/spec/models/admin/account_action_spec.rb +++ b/spec/models/admin/account_action_spec.rb @@ -115,16 +115,16 @@ RSpec.describe Admin::AccountAction, type: :model do context 'account.local?' do let(:account) { Fabricate(:account, domain: nil) } - it 'returns ["none", "disable", "silence", "suspend"]' do - expect(subject).to eq %w(none disable silence suspend) + it 'returns ["none", "disable", "sensitive", "silence", "suspend"]' do + expect(subject).to eq %w(none disable sensitive silence suspend) end end context '!account.local?' do let(:account) { Fabricate(:account, domain: 'hoge.com') } - it 'returns ["silence", "suspend"]' do - expect(subject).to eq %w(silence suspend) + it 'returns ["sensitive", "silence", "suspend"]' do + expect(subject).to eq %w(sensitive silence suspend) end end end diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb index e8ef61f66cc1a14419259628f3bec6c81613c865..85fbf7e79ca513c5be92889067bcab643315dcb9 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account_interactions_spec.rb @@ -14,7 +14,7 @@ describe AccountInteractions do context 'account with Follow' do it 'returns { target_account_id => true }' do Fabricate(:follow, account: account, target_account: target_account) - is_expected.to eq(target_account_id => { reblogs: true }) + is_expected.to eq(target_account_id => { reblogs: true, notify: false }) end end @@ -539,6 +539,49 @@ describe AccountInteractions do end end + describe '#followers_hash' do + let(:me) { Fabricate(:account, username: 'Me') } + let(:remote_1) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') } + let(:remote_2) { Fabricate(:account, username: 'bob', domain: 'example.org', uri: 'https://example.org/users/bob') } + let(:remote_3) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') } + + before do + remote_1.follow!(me) + remote_2.follow!(me) + remote_3.follow!(me) + me.follow!(remote_1) + end + + context 'on a local user' do + it 'returns correct hash for remote domains' do + expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec' + expect(me.remote_followers_hash('https://foo.org/')).to eq 'ccb9c18a67134cfff9d62c7f7e7eb88e6b803446c244b84265565f4eba29df0e' + end + + it 'invalidates cache as needed when removing or adding followers' do + expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec' + remote_1.unfollow!(me) + expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff' + remote_1.follow!(me) + expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec' + end + end + + context 'on a remote user' do + it 'returns correct hash for remote domains' do + expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) + end + + it 'invalidates cache as needed when removing or adding followers' do + expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) + me.unfollow!(remote_1) + expect(remote_1.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000' + me.follow!(remote_1) + expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) + end + end + end + describe 'muting an account' do let(:me) { Fabricate(:account, username: 'Me') } let(:you) { Fabricate(:account, username: 'You') } diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb index 2cf28b263cd58e97d08854e8edb73140bce12519..cc484a5b9216889b800cbbd7472b57c4a60232b3 100644 --- a/spec/models/follow_request_spec.rb +++ b/spec/models/follow_request_spec.rb @@ -7,7 +7,7 @@ RSpec.describe FollowRequest, type: :model do let(:target_account) { Fabricate(:account) } it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do - expect(account).to receive(:follow!).with(target_account, reblogs: true, uri: follow_request.uri) + expect(account).to receive(:follow!).with(target_account, reblogs: true, notify: false, uri: follow_request.uri) expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id) expect(follow_request).to receive(:destroy!) follow_request.authorize! diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index 0c84e5e7bfa2458455859733d850cb746e1c3bbd..e723a1ef21143f222e52f094c0d9a9deacd197d0 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Follow, type: :model do let(:bob) { Fabricate(:account, username: 'bob') } describe 'validations' do - subject { Follow.new(account: alice, target_account: bob) } + subject { Follow.new(account: alice, target_account: bob, rate_limit: true) } it 'has a valid fabricator' do follow = Fabricate.build(:follow) diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb index 321761166ec50a34e59dda7d80ed9f1618ca1994..a5eec172264a4e09c9b403bde8f6bc07507dbd36 100644 --- a/spec/models/import_spec.rb +++ b/spec/models/import_spec.rb @@ -20,5 +20,15 @@ RSpec.describe Import, type: :model do import = Import.create(account: account, type: type) expect(import).to model_have_error_on_field(:data) end + + it 'is invalid with too many rows in data' do + import = Import.create(account: account, type: type, data: StringIO.new("foo@bar.com\n" * (ImportService::ROWS_PROCESSING_LIMIT + 10))) + expect(import).to model_have_error_on_field(:data) + end + + it 'is invalid when there are more rows when following limit' do + import = Import.create(account: account, type: type, data: StringIO.new("foo@bar.com\n" * (FollowLimitValidator.limit_for_account(account) + 10))) + expect(import).to model_have_error_on_field(:data) + end end end diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb index 30abfb86bf4d882dd13add846b47c0e4408c4676..b0596c56123562792680f2dff0d28517e506f33f 100644 --- a/spec/models/invite_spec.rb +++ b/spec/models/invite_spec.rb @@ -29,7 +29,7 @@ RSpec.describe Invite, type: :model do it 'returns false when invite creator has been disabled' do invite = Fabricate(:invite, max_uses: nil, expires_at: nil) - SuspendAccountService.new.call(invite.user.account) + invite.user.account.suspend! expect(invite.valid_for_use?).to be false end end diff --git a/spec/models/ip_block_spec.rb b/spec/models/ip_block_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..6603c6417aac93a99ca6dd81d1574c3dfa85f2b9 --- /dev/null +++ b/spec/models/ip_block_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe IpBlock, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/public_feed_spec.rb b/spec/models/public_feed_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..0392a582c69cd12d4363e3b83d763e204e308d9d --- /dev/null +++ b/spec/models/public_feed_spec.rb @@ -0,0 +1,212 @@ +require 'rails_helper' + +RSpec.describe PublicFeed, type: :model do + let(:account) { Fabricate(:account) } + + describe '#get' do + subject { described_class.new(nil).get(20).map(&:id) } + + it 'only includes statuses with public visibility' do + public_status = Fabricate(:status, visibility: :public) + private_status = Fabricate(:status, visibility: :private) + + expect(subject).to include(public_status.id) + expect(subject).not_to include(private_status.id) + end + + it 'does not include replies' do + status = Fabricate(:status) + reply = Fabricate(:status, in_reply_to_id: status.id) + + expect(subject).to include(status.id) + expect(subject).not_to include(reply.id) + end + + it 'does not include boosts' do + status = Fabricate(:status) + boost = Fabricate(:status, reblog_of_id: status.id) + + expect(subject).to include(status.id) + expect(subject).not_to include(boost.id) + end + + it 'filters out silenced accounts' do + account = Fabricate(:account) + silenced_account = Fabricate(:account, silenced: true) + status = Fabricate(:status, account: account) + silenced_status = Fabricate(:status, account: silenced_account) + + expect(subject).to include(status.id) + expect(subject).not_to include(silenced_status.id) + end + + context 'without local_only option' do + let(:viewer) { nil } + + let!(:local_account) { Fabricate(:account, domain: nil) } + let!(:remote_account) { Fabricate(:account, domain: 'test.com') } + let!(:local_status) { Fabricate(:status, account: local_account) } + let!(:remote_status) { Fabricate(:status, account: remote_account) } + + subject { described_class.new(viewer).get(20).map(&:id) } + + context 'without a viewer' do + let(:viewer) { nil } + + it 'includes remote instances statuses' do + expect(subject).to include(remote_status.id) + end + + it 'includes local statuses' do + expect(subject).to include(local_status.id) + end + end + + context 'with a viewer' do + let(:viewer) { Fabricate(:account, username: 'viewer') } + + it 'includes remote instances statuses' do + expect(subject).to include(remote_status.id) + end + + it 'includes local statuses' do + expect(subject).to include(local_status.id) + end + end + end + + context 'with a local_only option set' do + let!(:local_account) { Fabricate(:account, domain: nil) } + let!(:remote_account) { Fabricate(:account, domain: 'test.com') } + let!(:local_status) { Fabricate(:status, account: local_account) } + let!(:remote_status) { Fabricate(:status, account: remote_account) } + + subject { described_class.new(viewer, local: true).get(20).map(&:id) } + + context 'without a viewer' do + let(:viewer) { nil } + + it 'does not include remote instances statuses' do + expect(subject).to include(local_status.id) + expect(subject).not_to include(remote_status.id) + end + end + + context 'with a viewer' do + let(:viewer) { Fabricate(:account, username: 'viewer') } + + it 'does not include remote instances statuses' do + expect(subject).to include(local_status.id) + expect(subject).not_to include(remote_status.id) + end + + it 'is not affected by personal domain blocks' do + viewer.block_domain!('test.com') + expect(subject).to include(local_status.id) + expect(subject).not_to include(remote_status.id) + end + end + end + + context 'with a remote_only option set' do + let!(:local_account) { Fabricate(:account, domain: nil) } + let!(:remote_account) { Fabricate(:account, domain: 'test.com') } + let!(:local_status) { Fabricate(:status, account: local_account) } + let!(:remote_status) { Fabricate(:status, account: remote_account) } + + subject { described_class.new(viewer, remote: true).get(20).map(&:id) } + + context 'without a viewer' do + let(:viewer) { nil } + + it 'does not include local instances statuses' do + expect(subject).not_to include(local_status.id) + expect(subject).to include(remote_status.id) + end + end + + context 'with a viewer' do + let(:viewer) { Fabricate(:account, username: 'viewer') } + + it 'does not include local instances statuses' do + expect(subject).not_to include(local_status.id) + expect(subject).to include(remote_status.id) + end + end + end + + describe 'with an account passed in' do + before do + @account = Fabricate(:account) + end + + subject { described_class.new(@account).get(20).map(&:id) } + + it 'excludes statuses from accounts blocked by the account' do + blocked = Fabricate(:account) + @account.block!(blocked) + blocked_status = Fabricate(:status, account: blocked) + + expect(subject).not_to include(blocked_status.id) + end + + it 'excludes statuses from accounts who have blocked the account' do + blocker = Fabricate(:account) + blocker.block!(@account) + blocked_status = Fabricate(:status, account: blocker) + + expect(subject).not_to include(blocked_status.id) + end + + it 'excludes statuses from accounts muted by the account' do + muted = Fabricate(:account) + @account.mute!(muted) + muted_status = Fabricate(:status, account: muted) + + expect(subject).not_to include(muted_status.id) + end + + it 'excludes statuses from accounts from personally blocked domains' do + blocked = Fabricate(:account, domain: 'example.com') + @account.block_domain!(blocked.domain) + blocked_status = Fabricate(:status, account: blocked) + + expect(subject).not_to include(blocked_status.id) + end + + context 'with language preferences' do + it 'excludes statuses in languages not allowed by the account user' do + user = Fabricate(:user, chosen_languages: [:en, :es]) + @account.update(user: user) + en_status = Fabricate(:status, language: 'en') + es_status = Fabricate(:status, language: 'es') + fr_status = Fabricate(:status, language: 'fr') + + expect(subject).to include(en_status.id) + expect(subject).to include(es_status.id) + expect(subject).not_to include(fr_status.id) + end + + it 'includes all languages when user does not have a setting' do + user = Fabricate(:user, chosen_languages: nil) + @account.update(user: user) + + en_status = Fabricate(:status, language: 'en') + es_status = Fabricate(:status, language: 'es') + + expect(subject).to include(en_status.id) + expect(subject).to include(es_status.id) + end + + it 'includes all languages when account does not have a user' do + expect(@account.user).to be_nil + en_status = Fabricate(:status, language: 'en') + es_status = Fabricate(:status, language: 'es') + + expect(subject).to include(en_status.id) + expect(subject).to include(es_status.id) + end + end + end + end +end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 4aee14cbd635384d2fb856f9bcf6ef07096abe14..20fb894e77f36988f18b1a49461a27b8ad5d35b5 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -267,241 +267,6 @@ RSpec.describe Status, type: :model do end end - describe '.as_public_timeline' do - it 'only includes statuses with public visibility' do - public_status = Fabricate(:status, visibility: :public) - private_status = Fabricate(:status, visibility: :private) - - results = Status.as_public_timeline - expect(results).to include(public_status) - expect(results).not_to include(private_status) - end - - it 'does not include replies' do - status = Fabricate(:status) - reply = Fabricate(:status, in_reply_to_id: status.id) - - results = Status.as_public_timeline - expect(results).to include(status) - expect(results).not_to include(reply) - end - - it 'does not include boosts' do - status = Fabricate(:status) - boost = Fabricate(:status, reblog_of_id: status.id) - - results = Status.as_public_timeline - expect(results).to include(status) - expect(results).not_to include(boost) - end - - it 'filters out silenced accounts' do - account = Fabricate(:account) - silenced_account = Fabricate(:account, silenced: true) - status = Fabricate(:status, account: account) - silenced_status = Fabricate(:status, account: silenced_account) - - results = Status.as_public_timeline - expect(results).to include(status) - expect(results).not_to include(silenced_status) - end - - context 'without local_only option' do - let(:viewer) { nil } - - let!(:local_account) { Fabricate(:account, domain: nil) } - let!(:remote_account) { Fabricate(:account, domain: 'test.com') } - let!(:local_status) { Fabricate(:status, account: local_account) } - let!(:remote_status) { Fabricate(:status, account: remote_account) } - - subject { Status.as_public_timeline(viewer, false) } - - context 'without a viewer' do - let(:viewer) { nil } - - it 'includes remote instances statuses' do - expect(subject).to include(remote_status) - end - - it 'includes local statuses' do - expect(subject).to include(local_status) - end - end - - context 'with a viewer' do - let(:viewer) { Fabricate(:account, username: 'viewer') } - - it 'includes remote instances statuses' do - expect(subject).to include(remote_status) - end - - it 'includes local statuses' do - expect(subject).to include(local_status) - end - end - end - - context 'with a local_only option set' do - let!(:local_account) { Fabricate(:account, domain: nil) } - let!(:remote_account) { Fabricate(:account, domain: 'test.com') } - let!(:local_status) { Fabricate(:status, account: local_account) } - let!(:remote_status) { Fabricate(:status, account: remote_account) } - - subject { Status.as_public_timeline(viewer, true) } - - context 'without a viewer' do - let(:viewer) { nil } - - it 'does not include remote instances statuses' do - expect(subject).to include(local_status) - expect(subject).not_to include(remote_status) - end - end - - context 'with a viewer' do - let(:viewer) { Fabricate(:account, username: 'viewer') } - - it 'does not include remote instances statuses' do - expect(subject).to include(local_status) - expect(subject).not_to include(remote_status) - end - - it 'is not affected by personal domain blocks' do - viewer.block_domain!('test.com') - expect(subject).to include(local_status) - expect(subject).not_to include(remote_status) - end - end - end - - context 'with a remote_only option set' do - let!(:local_account) { Fabricate(:account, domain: nil) } - let!(:remote_account) { Fabricate(:account, domain: 'test.com') } - let!(:local_status) { Fabricate(:status, account: local_account) } - let!(:remote_status) { Fabricate(:status, account: remote_account) } - - subject { Status.as_public_timeline(viewer, :remote) } - - context 'without a viewer' do - let(:viewer) { nil } - - it 'does not include local instances statuses' do - expect(subject).not_to include(local_status) - expect(subject).to include(remote_status) - end - end - - context 'with a viewer' do - let(:viewer) { Fabricate(:account, username: 'viewer') } - - it 'does not include local instances statuses' do - expect(subject).not_to include(local_status) - expect(subject).to include(remote_status) - end - end - end - - describe 'with an account passed in' do - before do - @account = Fabricate(:account) - end - - it 'excludes statuses from accounts blocked by the account' do - blocked = Fabricate(:account) - Fabricate(:block, account: @account, target_account: blocked) - blocked_status = Fabricate(:status, account: blocked) - - results = Status.as_public_timeline(@account) - expect(results).not_to include(blocked_status) - end - - it 'excludes statuses from accounts who have blocked the account' do - blocked = Fabricate(:account) - Fabricate(:block, account: blocked, target_account: @account) - blocked_status = Fabricate(:status, account: blocked) - - results = Status.as_public_timeline(@account) - expect(results).not_to include(blocked_status) - end - - it 'excludes statuses from accounts muted by the account' do - muted = Fabricate(:account) - Fabricate(:mute, account: @account, target_account: muted) - muted_status = Fabricate(:status, account: muted) - - results = Status.as_public_timeline(@account) - expect(results).not_to include(muted_status) - end - - it 'excludes statuses from accounts from personally blocked domains' do - blocked = Fabricate(:account, domain: 'example.com') - @account.block_domain!(blocked.domain) - blocked_status = Fabricate(:status, account: blocked) - - results = Status.as_public_timeline(@account) - expect(results).not_to include(blocked_status) - end - - context 'with language preferences' do - it 'excludes statuses in languages not allowed by the account user' do - user = Fabricate(:user, chosen_languages: [:en, :es]) - @account.update(user: user) - en_status = Fabricate(:status, language: 'en') - es_status = Fabricate(:status, language: 'es') - fr_status = Fabricate(:status, language: 'fr') - - results = Status.as_public_timeline(@account) - expect(results).to include(en_status) - expect(results).to include(es_status) - expect(results).not_to include(fr_status) - end - - it 'includes all languages when user does not have a setting' do - user = Fabricate(:user, chosen_languages: nil) - @account.update(user: user) - - en_status = Fabricate(:status, language: 'en') - es_status = Fabricate(:status, language: 'es') - - results = Status.as_public_timeline(@account) - expect(results).to include(en_status) - expect(results).to include(es_status) - end - - it 'includes all languages when account does not have a user' do - expect(@account.user).to be_nil - en_status = Fabricate(:status, language: 'en') - es_status = Fabricate(:status, language: 'es') - - results = Status.as_public_timeline(@account) - expect(results).to include(en_status) - expect(results).to include(es_status) - end - end - end - end - - describe '.as_tag_timeline' do - it 'includes statuses with a tag' do - tag = Fabricate(:tag) - status = Fabricate(:status, tags: [tag]) - other = Fabricate(:status) - - results = Status.as_tag_timeline(tag) - expect(results).to include(status) - expect(results).not_to include(other) - end - - it 'allows replies to be included' do - original = Fabricate(:status) - tag = Fabricate(:tag) - status = Fabricate(:status, tags: [tag], in_reply_to_id: original.id) - - results = Status.as_tag_timeline(tag) - expect(results).to include(status) - end - end - describe '.permitted_for' do subject { described_class.permitted_for(target_account, account).pluck(:visibility) } diff --git a/spec/services/hashtag_query_service_spec.rb b/spec/models/tag_feed_spec.rb similarity index 65% rename from spec/services/hashtag_query_service_spec.rb rename to spec/models/tag_feed_spec.rb index 24282d2f0672e1defd94bd4bcc100bfe736c04f0..17d88eb99938f0d528b721ac71212fb86fc9d7a8 100644 --- a/spec/services/hashtag_query_service_spec.rb +++ b/spec/models/tag_feed_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' -describe HashtagQueryService, type: :service do - describe '.call' do +describe TagFeed, type: :service do + describe '#get' do let(:account) { Fabricate(:account) } let(:tag1) { Fabricate(:tag) } let(:tag2) { Fabricate(:tag) } @@ -10,35 +10,35 @@ describe HashtagQueryService, type: :service do let!(:both) { Fabricate(:status, tags: [tag1, tag2]) } it 'can add tags in "any" mode' do - results = subject.call(tag1, { any: [tag2.name] }) + results = described_class.new(tag1, nil, any: [tag2.name]).get(20) expect(results).to include status1 expect(results).to include status2 expect(results).to include both end it 'can remove tags in "all" mode' do - results = subject.call(tag1, { all: [tag2.name] }) + results = described_class.new(tag1, nil, all: [tag2.name]).get(20) expect(results).to_not include status1 expect(results).to_not include status2 expect(results).to include both end it 'can remove tags in "none" mode' do - results = subject.call(tag1, { none: [tag2.name] }) + results = described_class.new(tag1, nil, none: [tag2.name]).get(20) expect(results).to include status1 expect(results).to_not include status2 expect(results).to_not include both end it 'ignores an invalid mode' do - results = subject.call(tag1, { wark: [tag2.name] }) + results = described_class.new(tag1, nil, wark: [tag2.name]).get(20) expect(results).to include status1 expect(results).to_not include status2 expect(results).to include both end it 'handles being passed non existant tag names' do - results = subject.call(tag1, { any: ['wark'] }) + results = described_class.new(tag1, nil, any: ['wark']).get(20) expect(results).to include status1 expect(results).to_not include status2 expect(results).to include both @@ -46,15 +46,23 @@ describe HashtagQueryService, type: :service do it 'can restrict to an account' do BlockService.new.call(account, status1.account) - results = subject.call(tag1, { none: [tag2.name] }, account) + results = described_class.new(tag1, account, none: [tag2.name]).get(20) expect(results).to_not include status1 end it 'can restrict to local' do status1.account.update(domain: 'example.com') status1.update(local: false, uri: 'example.com/toot') - results = subject.call(tag1, { any: [tag2.name] }, nil, true) + results = described_class.new(tag1, nil, any: [tag2.name], local: true).get(20) expect(results).to_not include status1 end + + it 'allows replies to be included' do + original = Fabricate(:status) + status = Fabricate(:status, tags: [tag1], in_reply_to_id: original.id) + + results = described_class.new(tag1, nil).get(20) + expect(results).to include(status) + end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5686ec909ea6af9d3707308c58c1104cfc70fcfd..cded4c99bdca2a7d602be7c2180b0b9536493adf 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -151,6 +151,12 @@ RSpec.describe User, type: :model do expect(user.reload.otp_required_for_login).to be false end + it 'saves nil for otp_secret' do + user = Fabricate.build(:user, otp_secret: 'oldotpcode') + user.disable_two_factor! + expect(user.reload.otp_secret).to be nil + end + it 'saves cleared otp_backup_codes' do user = Fabricate.build(:user, otp_backup_codes: %w(dummy dummy)) user.disable_two_factor! diff --git a/spec/models/webauthn_credentials_spec.rb b/spec/models/webauthn_credentials_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..a63ae6cd24893ea33c8169be9b526cd9ff75de60 --- /dev/null +++ b/spec/models/webauthn_credentials_spec.rb @@ -0,0 +1,80 @@ +require 'rails_helper' + +RSpec.describe WebauthnCredential, type: :model do + describe 'validations' do + it 'is invalid without an external id' do + webauthn_credential = Fabricate.build(:webauthn_credential, external_id: nil) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:external_id) + end + + it 'is invalid without a public key' do + webauthn_credential = Fabricate.build(:webauthn_credential, public_key: nil) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:public_key) + end + + it 'is invalid without a nickname' do + webauthn_credential = Fabricate.build(:webauthn_credential, nickname: nil) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:nickname) + end + + it 'is invalid without a sign_count' do + webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: nil) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:sign_count) + end + + it 'is invalid if already exist a webauthn credential with the same external id' do + existing_webauthn_credential = Fabricate(:webauthn_credential, external_id: "_Typ0ygudDnk9YUVWLQayw") + new_webauthn_credential = Fabricate.build(:webauthn_credential, external_id: "_Typ0ygudDnk9YUVWLQayw") + + new_webauthn_credential.valid? + + expect(new_webauthn_credential).to model_have_error_on_field(:external_id) + end + + it 'is invalid if user already registered a webauthn credential with the same nickname' do + user = Fabricate(:user) + existing_webauthn_credential = Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key') + new_webauthn_credential = Fabricate.build(:webauthn_credential, user_id: user.id, nickname: 'USB Key') + + new_webauthn_credential.valid? + + expect(new_webauthn_credential).to model_have_error_on_field(:nickname) + end + + it 'is invalid if sign_count is not a number' do + webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: 'invalid sign_count') + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:sign_count) + end + + it 'is invalid if sign_count is negative number' do + webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: -1) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:sign_count) + end + + it 'is invalid if sign_count is greater 2**63 - 1' do + webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: 2**63) + + webauthn_credential.valid? + + expect(webauthn_credential).to model_have_error_on_field(:sign_count) + end + end +end diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb index 6648b0888bf6e830379875285f7699de23e4aeaf..1347ca4a03c8f53cd31678fe0a690619a3949af7 100644 --- a/spec/policies/account_policy_spec.rb +++ b/spec/policies/account_policy_spec.rb @@ -7,8 +7,9 @@ RSpec.describe AccountPolicy do let(:subject) { described_class } let(:admin) { Fabricate(:user, admin: true).account } let(:john) { Fabricate(:user).account } + let(:alice) { Fabricate(:user).account } - permissions :index?, :show?, :unsuspend?, :unsilence?, :remove_avatar?, :remove_header? do + permissions :index? do context 'staff' do it 'permits' do expect(subject).to permit(admin) @@ -22,6 +23,38 @@ RSpec.describe AccountPolicy do end end + permissions :show?, :unsilence?, :unsensitive?, :remove_avatar?, :remove_header? do + context 'staff' do + it 'permits' do + expect(subject).to permit(admin, alice) + end + end + + context 'not staff' do + it 'denies' do + expect(subject).to_not permit(john, alice) + end + end + end + + permissions :unsuspend? do + before do + alice.suspend! + end + + context 'staff' do + it 'permits' do + expect(subject).to permit(admin, alice) + end + end + + context 'not staff' do + it 'denies' do + expect(subject).to_not permit(john, alice) + end + end + end + permissions :redownload?, :subscribe?, :unsubscribe? do context 'admin' do it 'permits' do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 40ddf1f95d76a2f3eefbe4e141b2d18c78ebed61..86c2a9c52fd9e806f61dde6bd3d0821a28847004 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -70,6 +70,8 @@ RSpec::Sidekiq.configure do |config| config.warn_when_jobs_not_processed_by_sidekiq = false end +RSpec::Matchers.define_negated_matcher :not_change, :change + def request_fixture(name) File.read(Rails.root.join('spec', 'fixtures', 'requests', name)) end diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index 5141e3f16568853048dc16dff00ed4f3daf75d6a..56e7f83211b4e069ebb896dec0d79d42a9eaae3b 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -73,4 +73,84 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do expect(ProofProvider::Keybase::Worker).to have_received(:perform_async) end end + + context 'when account is not suspended' do + let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com') } + + let(:payload) do + { + id: 'https://foo.test', + type: 'Actor', + inbox: 'https://foo.test/inbox', + suspended: true, + }.with_indifferent_access + end + + before do + allow(Admin::SuspensionWorker).to receive(:perform_async) + end + + subject { described_class.new.call('alice', 'example.com', payload) } + + it 'suspends account remotely' do + expect(subject.suspended?).to be true + expect(subject.suspension_origin_remote?).to be true + end + + it 'queues suspension worker' do + subject + expect(Admin::SuspensionWorker).to have_received(:perform_async) + end + end + + context 'when account is suspended' do + let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com', display_name: '') } + + let(:payload) do + { + id: 'https://foo.test', + type: 'Actor', + inbox: 'https://foo.test/inbox', + suspended: false, + name: 'Hoge', + }.with_indifferent_access + end + + before do + allow(Admin::UnsuspensionWorker).to receive(:perform_async) + + account.suspend!(origin: suspension_origin) + end + + subject { described_class.new.call('alice', 'example.com', payload) } + + context 'locally' do + let(:suspension_origin) { :local } + + it 'does not unsuspend it' do + expect(subject.suspended?).to be true + end + + it 'does not update any attributes' do + expect(subject.display_name).to_not eq 'Hoge' + end + end + + context 'remotely' do + let(:suspension_origin) { :remote } + + it 'unsuspends it' do + expect(subject.suspended?).to be false + end + + it 'queues unsuspension worker' do + subject + expect(Admin::UnsuspensionWorker).to have_received(:perform_async) + end + + it 'updates attributes' do + expect(subject.display_name).to eq 'Hoge' + end + end + end end diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb index b3baf6b6b545140891cfdf533ebf0967b5d22b14..00d71a86ab13bdc2509cc2ccf21cfb699462f27b 100644 --- a/spec/services/activitypub/process_collection_service_spec.rb +++ b/spec/services/activitypub/process_collection_service_spec.rb @@ -22,7 +22,48 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do subject { described_class.new } describe '#call' do - context 'when actor is the sender' + context 'when actor is suspended' do + before do + actor.suspend!(origin: :remote) + end + + %w(Accept Add Announce Block Create Flag Follow Like Move Remove).each do |activity_type| + context "with #{activity_type} activity" do + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: activity_type, + actor: ActivityPub::TagManager.instance.uri_for(actor), + } + end + + it 'does not process payload' do + expect(ActivityPub::Activity).not_to receive(:factory) + subject.call(json, actor) + end + end + end + + %w(Delete Reject Undo Update).each do |activity_type| + context "with #{activity_type} activity" do + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: activity_type, + actor: ActivityPub::TagManager.instance.uri_for(actor), + } + end + + it 'processes the payload' do + expect(ActivityPub::Activity).to receive(:factory) + subject.call(json, actor) + end + end + end + end + context 'when actor differs from sender' do let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') } diff --git a/spec/services/activitypub/synchronize_followers_service_spec.rb b/spec/services/activitypub/synchronize_followers_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..75dcf204b79517e4f641966a7acebc19278aff9b --- /dev/null +++ b/spec/services/activitypub/synchronize_followers_service_spec.rb @@ -0,0 +1,105 @@ +require 'rails_helper' + +RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do + let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account', inbox_url: 'http://example.com/inbox') } + let(:alice) { Fabricate(:account, username: 'alice') } + let(:bob) { Fabricate(:account, username: 'bob') } + let(:eve) { Fabricate(:account, username: 'eve') } + let(:mallory) { Fabricate(:account, username: 'mallory') } + let(:collection_uri) { 'http://example.com/partial-followers' } + + let(:items) do + [ + ActivityPub::TagManager.instance.uri_for(alice), + ActivityPub::TagManager.instance.uri_for(eve), + ActivityPub::TagManager.instance.uri_for(mallory), + ] + end + + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'Collection', + id: collection_uri, + items: items, + }.with_indifferent_access + end + + subject { described_class.new } + + shared_examples 'synchronizes followers' do + before do + alice.follow!(actor) + bob.follow!(actor) + mallory.request_follow!(actor) + + allow(ActivityPub::DeliveryWorker).to receive(:perform_async) + + subject.call(actor, collection_uri) + end + + it 'keeps expected followers' do + expect(alice.following?(actor)).to be true + end + + it 'removes local followers not in the remote list' do + expect(bob.following?(actor)).to be false + end + + it 'converts follow requests to follow relationships when they have been accepted' do + expect(mallory.following?(actor)).to be true + end + + it 'sends an Undo Follow to the actor' do + expect(ActivityPub::DeliveryWorker).to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) + end + end + + describe '#call' do + context 'when the endpoint is a Collection of actor URIs' do + before do + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + end + + it_behaves_like 'synchronizes followers' + end + + context 'when the endpoint is an OrderedCollection of actor URIs' do + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'OrderedCollection', + id: collection_uri, + orderedItems: items, + }.with_indifferent_access + end + + before do + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + end + + it_behaves_like 'synchronizes followers' + end + + context 'when the endpoint is a paginated Collection of actor URIs' do + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + type: 'Collection', + id: collection_uri, + first: { + type: 'CollectionPage', + partOf: collection_uri, + items: items, + } + }.with_indifferent_access + end + + before do + stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) + end + + it_behaves_like 'synchronizes followers' + end + end +end diff --git a/spec/services/app_sign_up_service_spec.rb b/spec/services/app_sign_up_service_spec.rb index e7c7f3ba15e6bfcb69df2996297f7e556be44cb7..e0c83b7041d1602560d62be5179be5342d606e1c 100644 --- a/spec/services/app_sign_up_service_spec.rb +++ b/spec/services/app_sign_up_service_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' RSpec.describe AppSignUpService, type: :service do let(:app) { Fabricate(:application, scopes: 'read write') } let(:good_params) { { username: 'alice', password: '12345678', email: 'good@email.com', agreement: true } } + let(:remote_ip) { IPAddr.new('198.0.2.1') } subject { described_class.new } @@ -10,16 +11,16 @@ RSpec.describe AppSignUpService, type: :service do it 'returns nil when registrations are closed' do tmp = Setting.registrations_mode Setting.registrations_mode = 'none' - expect(subject.call(app, good_params)).to be_nil + expect(subject.call(app, remote_ip, good_params)).to be_nil Setting.registrations_mode = tmp end it 'raises an error when params are missing' do - expect { subject.call(app, {}) }.to raise_error ActiveRecord::RecordInvalid + expect { subject.call(app, remote_ip, {}) }.to raise_error ActiveRecord::RecordInvalid end it 'creates an unconfirmed user with access token' do - access_token = subject.call(app, good_params) + access_token = subject.call(app, remote_ip, good_params) expect(access_token).to_not be_nil user = User.find_by(id: access_token.resource_owner_id) expect(user).to_not be_nil @@ -27,13 +28,13 @@ RSpec.describe AppSignUpService, type: :service do end it 'creates access token with the app\'s scopes' do - access_token = subject.call(app, good_params) + access_token = subject.call(app, remote_ip, good_params) expect(access_token).to_not be_nil expect(access_token.scopes.to_s).to eq 'read write' end it 'creates an account' do - access_token = subject.call(app, good_params) + access_token = subject.call(app, remote_ip, good_params) expect(access_token).to_not be_nil user = User.find_by(id: access_token.resource_owner_id) expect(user).to_not be_nil @@ -42,7 +43,7 @@ RSpec.describe AppSignUpService, type: :service do end it 'creates an account with invite request text' do - access_token = subject.call(app, good_params.merge(reason: 'Foo bar')) + access_token = subject.call(app, remote_ip, good_params.merge(reason: 'Foo bar')) expect(access_token).to_not be_nil user = User.find_by(id: access_token.resource_owner_id) expect(user).to_not be_nil diff --git a/spec/services/batched_remove_status_service_spec.rb b/spec/services/batched_remove_status_service_spec.rb index f84256f187e17238b4b95026b65d9de32d9a005a..c1f54a6fd2a6b2b9d14c27ba088bb9675c5b3040 100644 --- a/spec/services/batched_remove_status_service_spec.rb +++ b/spec/services/batched_remove_status_service_spec.rb @@ -26,6 +26,11 @@ RSpec.describe BatchedRemoveStatusService, type: :service do subject.call([status1, status2]) end + it 'removes statuses' do + expect { Status.find(status1.id) }.to raise_error ActiveRecord::RecordNotFound + expect { Status.find(status2.id) }.to raise_error ActiveRecord::RecordNotFound + end + it 'removes statuses from author\'s home feed' do expect(HomeFeed.new(alice).get(10)).to_not include([status1.id, status2.id]) end @@ -38,10 +43,6 @@ RSpec.describe BatchedRemoveStatusService, type: :service do expect(Redis.current).to have_received(:publish).with("timeline:#{jeff.id}", any_args).at_least(:once) end - it 'notifies streaming API of author' do - expect(Redis.current).to have_received(:publish).with("timeline:#{alice.id}", any_args).at_least(:once) - end - it 'notifies streaming API of public timeline' do expect(Redis.current).to have_received(:publish).with('timeline:public', any_args).at_least(:once) end diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..cd7d32d5921940049015f2727b28ec57bf654b9a --- /dev/null +++ b/spec/services/delete_account_service_spec.rb @@ -0,0 +1,96 @@ +require 'rails_helper' + +RSpec.describe DeleteAccountService, type: :service do + shared_examples 'common behavior' do + let!(:status) { Fabricate(:status, account: account) } + let!(:mention) { Fabricate(:mention, account: local_follower) } + let!(:status_with_mention) { Fabricate(:status, account: account, mentions: [mention]) } + let!(:media_attachment) { Fabricate(:media_attachment, account: account) } + let!(:notification) { Fabricate(:notification, account: account) } + let!(:favourite) { Fabricate(:favourite, account: account, status: Fabricate(:status, account: local_follower)) } + let!(:poll) { Fabricate(:poll, account: account) } + let!(:poll_vote) { Fabricate(:poll_vote, account: local_follower, poll: poll) } + + let!(:active_relationship) { Fabricate(:follow, account: account, target_account: local_follower) } + let!(:passive_relationship) { Fabricate(:follow, account: local_follower, target_account: account) } + let!(:endorsement) { Fabricate(:account_pin, account: local_follower, target_account: account) } + + let!(:mention_notification) { Fabricate(:notification, account: local_follower, activity: mention, type: :mention) } + let!(:status_notification) { Fabricate(:notification, account: local_follower, activity: status, type: :status) } + let!(:poll_notification) { Fabricate(:notification, account: local_follower, activity: poll, type: :poll) } + let!(:favourite_notification) { Fabricate(:notification, account: local_follower, activity: favourite, type: :favourite) } + let!(:follow_notification) { Fabricate(:notification, account: local_follower, activity: active_relationship, type: :follow) } + + subject do + -> { described_class.new.call(account) } + end + + it 'deletes associated owned records' do + is_expected.to change { + [ + account.statuses, + account.media_attachments, + account.notifications, + account.favourites, + account.active_relationships, + account.passive_relationships, + account.polls, + ].map(&:count) + }.from([2, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0]) + end + + it 'deletes associated target records' do + is_expected.to change { + [ + AccountPin.where(target_account: account), + ].map(&:count) + }.from([1]).to([0]) + end + + it 'deletes associated target notifications' do + is_expected.to change { + [ + 'poll', 'favourite', 'status', 'mention', 'follow' + ].map { |type| Notification.where(type: type).count } + }.from([1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0]) + end + end + + describe '#call on local account' do + before do + stub_request(:post, "https://alice.com/inbox").to_return(status: 201) + stub_request(:post, "https://bob.com/inbox").to_return(status: 201) + end + + let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', protocol: :activitypub) } + let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } + + include_examples 'common behavior' do + let!(:account) { Fabricate(:account) } + let!(:local_follower) { Fabricate(:account) } + + it 'sends a delete actor activity to all known inboxes' do + subject.call + expect(a_request(:post, "https://alice.com/inbox")).to have_been_made.once + expect(a_request(:post, "https://bob.com/inbox")).to have_been_made.once + end + end + end + + describe '#call on remote account' do + before do + stub_request(:post, "https://alice.com/inbox").to_return(status: 201) + stub_request(:post, "https://bob.com/inbox").to_return(status: 201) + end + + include_examples 'common behavior' do + let!(:account) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } + let!(:local_follower) { Fabricate(:account) } + + it 'sends a reject follow to follwer inboxes' do + subject.call + expect(a_request(:post, account.inbox_url)).to have_been_made.once + end + end + end +end diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index b7fc7f7eda284cf25c300c2316f2627ab8f2d2bc..538dc25922bf80c874f06659b15f1b1537bdd930 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -28,10 +28,10 @@ RSpec.describe FanOutOnWriteService, type: :service do end it 'delivers status to hashtag' do - expect(Tag.find_by!(name: 'test').statuses.pluck(:id)).to include status.id + expect(TagFeed.new(Tag.find_by(name: 'test'), alice).get(20).map(&:id)).to include status.id end it 'delivers status to public timeline' do - expect(Status.as_public_timeline(alice).map(&:id)).to include status.id + expect(PublicFeed.new(alice).get(20).map(&:id)).to include status.id end end diff --git a/spec/services/import_service_spec.rb b/spec/services/import_service_spec.rb index 7618e9076184b90fb9ecb5f1593ff6adfbc1ecb0..764225aa7296c73e0ce3f41b12822bf2e6a64bc3 100644 --- a/spec/services/import_service_spec.rb +++ b/spec/services/import_service_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' RSpec.describe ImportService, type: :service do + include RoutingHelper + let!(:account) { Fabricate(:account, locked: false) } let!(:bob) { Fabricate(:account, username: 'bob', locked: false) } let!(:eve) { Fabricate(:account, username: 'eve', domain: 'example.com', locked: false, protocol: :activitypub, inbox_url: 'https://example.com/inbox') } @@ -95,6 +97,7 @@ RSpec.describe ImportService, type: :service do let(:import) { Import.create(account: account, type: 'following', data: csv) } it 'follows the listed accounts, including boosts' do subject.call(import) + expect(account.following.count).to eq 1 expect(account.follow_requests.count).to eq 1 expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true @@ -168,4 +171,44 @@ RSpec.describe ImportService, type: :service do end end end + + context 'import bookmarks' do + subject { ImportService.new } + + let(:csv) { attachment_fixture('bookmark-imports.txt') } + + around(:each) do |example| + local_before = Rails.configuration.x.local_domain + web_before = Rails.configuration.x.web_domain + Rails.configuration.x.local_domain = 'local.com' + Rails.configuration.x.web_domain = 'local.com' + example.run + Rails.configuration.x.web_domain = web_before + Rails.configuration.x.local_domain = local_before + end + + let(:local_account) { Fabricate(:account, username: 'foo', domain: '') } + let!(:remote_status) { Fabricate(:status, uri: 'https://example.com/statuses/1312') } + let!(:direct_status) { Fabricate(:status, uri: 'https://example.com/statuses/direct', visibility: :direct) } + + before do + service = double + allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service) + allow(service).to receive(:call).with('https://unknown-remote.com/users/bar/statuses/1') do + Fabricate(:status, uri: 'https://unknown-remote.com/users/bar/statuses/1') + end + end + + describe 'when no bookmarks are set' do + let(:import) { Import.create(account: account, type: 'bookmarks', data: csv) } + it 'adds the toots the user has access to to bookmarks' do + local_status = Fabricate(:status, account: local_account, uri: 'https://local.com/users/foo/statuses/42', id: 42, local: true) + subject.call(import) + expect(account.bookmarks.map(&:status).map(&:id)).to include(local_status.id) + expect(account.bookmarks.map(&:status).map(&:id)).to include(remote_status.id) + expect(account.bookmarks.map(&:status).map(&:id)).not_to include(direct_status.id) + expect(account.bookmarks.count).to eq 3 + end + end + end end diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index 440018ac93d282994330367d64d28d57cd8d5373..f2cb22c5ef7508d1fd0a535dd379ecf0aec8a550 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -2,13 +2,14 @@ require 'rails_helper' RSpec.describe NotifyService, type: :service do subject do - -> { described_class.new.call(recipient, activity) } + -> { described_class.new.call(recipient, type, activity) } end let(:user) { Fabricate(:user) } let(:recipient) { user.account } let(:sender) { Fabricate(:account, domain: 'example.com') } let(:activity) { Fabricate(:follow, account: sender, target_account: recipient) } + let(:type) { :follow } it { is_expected.to change(Notification, :count).by(1) } @@ -50,6 +51,7 @@ RSpec.describe NotifyService, type: :service do context 'for direct messages' do let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct)) } + let(:type) { :mention } before do user.settings.interactions = user.settings.interactions.merge('must_be_following_dm' => enabled) @@ -93,6 +95,7 @@ RSpec.describe NotifyService, type: :service do describe 'reblogs' do let(:status) { Fabricate(:status, account: Fabricate(:account)) } let(:activity) { Fabricate(:status, account: sender, reblog: status) } + let(:type) { :reblog } it 'shows reblogs by default' do recipient.follow!(sender) @@ -114,6 +117,7 @@ RSpec.describe NotifyService, type: :service do let(:asshole) { Fabricate(:account, username: 'asshole') } let(:reply_to) { Fabricate(:status, account: asshole) } let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, thread: reply_to)) } + let(:type) { :mention } it 'does not notify when conversation is muted' do recipient.mute_conversation!(activity.status.conversation) diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 06676ec45e20dd4120ab40fa7e2c9f749010ae02..7ce75b2c72b7b9fec6e7ae600f79be18246b84cb 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe RemoveStatusService, type: :service do subject { RemoveStatusService.new } - let!(:alice) { Fabricate(:account) } + let!(:alice) { Fabricate(:account, user: Fabricate(:user)) } let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://example.com/salmon') } let!(:jeff) { Fabricate(:account) } let!(:hank) { Fabricate(:account, username: 'hank', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } @@ -17,23 +17,33 @@ RSpec.describe RemoveStatusService, type: :service do hank.follow!(alice) @status = PostStatusService.new.call(alice, text: 'Hello @bob@example.com') + FavouriteService.new.call(jeff, @status) Fabricate(:status, account: bill, reblog: @status, uri: 'hoge') - subject.call(@status) end it 'removes status from author\'s home feed' do + subject.call(@status) expect(HomeFeed.new(alice).get(10)).to_not include(@status.id) end it 'removes status from local follower\'s home feed' do + subject.call(@status) expect(HomeFeed.new(jeff).get(10)).to_not include(@status.id) end it 'sends delete activity to followers' do + subject.call(@status) expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.twice end it 'sends delete activity to rebloggers' do + subject.call(@status) expect(a_request(:post, 'http://example2.com/inbox')).to have_been_made end + + it 'remove status from notifications' do + expect { subject.call(@status) }.to change { + Notification.where(activity_type: 'Favourite', from_account: jeff, account: alice).count + }.from(1).to(0) + end end diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index cea942e39cb8b0aab2d7b628819fd6b65268b827..a604e90b549794e33836b0ace0d091ca02c53c81 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -4,23 +4,101 @@ RSpec.describe ResolveAccountService, type: :service do subject { described_class.new } before do - stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt')) - stub_request(:get, "https://example.com/.well-known/webfinger?resource=acct:catsrgr8@example.com").to_return(status: 404) stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 404) stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt')) - stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:catsrgr8@quitter.no").to_return(status: 404) stub_request(:get, "https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com").to_return(request_fixture('activitypub-webfinger.txt')) stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor.txt')) stub_request(:get, "https://ap.example.com/users/foo.atom").to_return(request_fixture('activitypub-feed.txt')) stub_request(:get, %r{https://ap.example.com/users/foo/\w+}).to_return(status: 404) + stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:hoge@example.com').to_return(status: 410) end - it 'raises error if no such user can be resolved via webfinger' do - expect(subject.call('catsrgr8@quitter.no')).to be_nil + context 'when there is an LRDD endpoint but no resolvable account' do + before do + stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt')) + stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:catsrgr8@quitter.no").to_return(status: 404) + end + + it 'returns nil' do + expect(subject.call('catsrgr8@quitter.no')).to be_nil + end + end + + context 'when there is no LRDD endpoint nor resolvable account' do + before do + stub_request(:get, "https://example.com/.well-known/webfinger?resource=acct:catsrgr8@example.com").to_return(status: 404) + end + + it 'returns nil' do + expect(subject.call('catsrgr8@example.com')).to be_nil + end + end + + context 'when webfinger returns http gone' do + context 'for a previously known account' do + before do + Fabricate(:account, username: 'hoge', domain: 'example.com', last_webfingered_at: nil) + allow(AccountDeletionWorker).to receive(:perform_async) + end + + it 'returns nil' do + expect(subject.call('hoge@example.com')).to be_nil + end + + it 'queues account deletion worker' do + subject.call('hoge@example.com') + expect(AccountDeletionWorker).to have_received(:perform_async) + end + end + + context 'for a previously unknown account' do + it 'returns nil' do + expect(subject.call('hoge@example.com')).to be_nil + end + end + end + + context 'with a legitimate webfinger redirection' do + before do + webfinger = { subject: 'acct:foo@ap.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } + stub_request(:get, 'https://redirected.example.com/.well-known/webfinger?resource=acct:Foo@redirected.example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + end + + it 'returns new remote account' do + account = subject.call('Foo@redirected.example.com') + + expect(account.activitypub?).to eq true + expect(account.acct).to eq 'foo@ap.example.com' + expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + end + end + + context 'with a misconfigured redirection' do + before do + webfinger = { subject: 'acct:Foo@redirected.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } + stub_request(:get, 'https://redirected.example.com/.well-known/webfinger?resource=acct:Foo@redirected.example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + end + + it 'returns new remote account' do + account = subject.call('Foo@redirected.example.com') + + expect(account.activitypub?).to eq true + expect(account.acct).to eq 'foo@ap.example.com' + expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + end end - it 'raises error if the domain does not have webfinger' do - expect(subject.call('catsrgr8@example.com')).to be_nil + context 'with too many webfinger redirections' do + before do + webfinger = { subject: 'acct:foo@evil.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } + stub_request(:get, 'https://redirected.example.com/.well-known/webfinger?resource=acct:Foo@redirected.example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) + webfinger2 = { subject: 'acct:foo@ap.example.com', links: [{ rel: 'self', href: 'https://ap.example.com/users/foo', type: 'application/activity+json' }] } + stub_request(:get, 'https://evil.example.com/.well-known/webfinger?resource=acct:foo@evil.example.com').to_return(body: Oj.dump(webfinger2), headers: { 'Content-Type': 'application/jrd+json' }) + end + + it 'returns new remote account' do + expect { subject.call('Foo@redirected.example.com') }.to raise_error Webfinger::RedirectError + end end context 'with an ActivityPub account' do @@ -48,6 +126,41 @@ RSpec.describe ResolveAccountService, type: :service do end end + context 'with an already-known actor changing acct: URI' do + let!(:duplicate) { Fabricate(:account, username: 'foo', domain: 'old.example.com', uri: 'https://ap.example.com/users/foo') } + let!(:status) { Fabricate(:status, account: duplicate, text: 'foo') } + + it 'returns new remote account' do + account = subject.call('foo@ap.example.com') + + expect(account.activitypub?).to eq true + expect(account.domain).to eq 'ap.example.com' + expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + expect(account.uri).to eq 'https://ap.example.com/users/foo' + end + + it 'merges accounts' do + account = subject.call('foo@ap.example.com') + + expect(status.reload.account_id).to eq account.id + expect(Account.where(uri: account.uri).count).to eq 1 + end + end + + context 'with an already-known acct: URI changing ActivityPub id' do + let!(:old_account) { Fabricate(:account, username: 'foo', domain: 'ap.example.com', uri: 'https://old.example.com/users/foo', last_webfingered_at: nil) } + let!(:status) { Fabricate(:status, account: old_account, text: 'foo') } + + it 'returns new remote account' do + account = subject.call('foo@ap.example.com') + + expect(account.activitypub?).to eq true + expect(account.domain).to eq 'ap.example.com' + expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + expect(account.uri).to eq 'https://ap.example.com/users/foo' + end + end + it 'processes one remote account at a time using locks' do wait_for_start = true fail_occurred = false diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb index aa4204637187d980ef2fc705fc4b442d63ff1375..a38b23590055f1cbd1076986da2753181e6bc821 100644 --- a/spec/services/resolve_url_service_spec.rb +++ b/spec/services/resolve_url_service_spec.rb @@ -15,5 +15,102 @@ describe ResolveURLService, type: :service do expect(subject.call(url)).to be_nil end + + context 'searching for a remote private status' do + let(:account) { Fabricate(:account) } + let(:poster) { Fabricate(:account, domain: 'example.com') } + let(:url) { 'https://example.com/@foo/42' } + let(:uri) { 'https://example.com/users/foo/statuses/42' } + let!(:status) { Fabricate(:status, url: url, uri: uri, account: poster, visibility: :private) } + + before do + stub_request(:get, url).to_return(status: 404) if url.present? + stub_request(:get, uri).to_return(status: 404) + end + + context 'when the account follows the poster' do + before do + account.follow!(poster) + end + + context 'when the status uses Mastodon-style URLs' do + let(:url) { 'https://example.com/@foo/42' } + let(:uri) { 'https://example.com/users/foo/statuses/42' } + + it 'returns status by url' do + expect(subject.call(url, on_behalf_of: account)).to eq(status) + end + + it 'returns status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to eq(status) + end + end + + context 'when the status uses pleroma-style URLs' do + let(:url) { nil } + let(:uri) { 'https://example.com/objects/0123-456-789-abc-def' } + + it 'returns status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to eq(status) + end + end + end + + context 'when the account does not follow the poster' do + context 'when the status uses Mastodon-style URLs' do + let(:url) { 'https://example.com/@foo/42' } + let(:uri) { 'https://example.com/users/foo/statuses/42' } + + it 'does not return the status by url' do + expect(subject.call(url, on_behalf_of: account)).to be_nil + end + + it 'does not return the status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to be_nil + end + end + + context 'when the status uses pleroma-style URLs' do + let(:url) { nil } + let(:uri) { 'https://example.com/objects/0123-456-789-abc-def' } + + it 'returns status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to be_nil + end + end + end + end + + context 'searching for a local private status' do + let(:account) { Fabricate(:account) } + let(:poster) { Fabricate(:account) } + let!(:status) { Fabricate(:status, account: poster, visibility: :private) } + let(:url) { ActivityPub::TagManager.instance.url_for(status) } + let(:uri) { ActivityPub::TagManager.instance.uri_for(status) } + + context 'when the account follows the poster' do + before do + account.follow!(poster) + end + + it 'returns status by url' do + expect(subject.call(url, on_behalf_of: account)).to eq(status) + end + + it 'returns status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to eq(status) + end + end + + context 'when the account does not follow the poster' do + it 'does not return the status by url' do + expect(subject.call(url, on_behalf_of: account)).to be_nil + end + + it 'does not return the status by uri' do + expect(subject.call(uri, on_behalf_of: account)).to be_nil + end + end + end end end diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb deleted file mode 100644 index 32726d7639786356411ea06f3aa5720d16bf9d0f..0000000000000000000000000000000000000000 --- a/spec/services/suspend_account_service_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -require 'rails_helper' - -RSpec.describe SuspendAccountService, type: :service do - describe '#call on local account' do - before do - stub_request(:post, "https://alice.com/inbox").to_return(status: 201) - stub_request(:post, "https://bob.com/inbox").to_return(status: 201) - end - - subject do - -> { described_class.new.call(account) } - end - - let!(:account) { Fabricate(:account) } - let!(:status) { Fabricate(:status, account: account) } - let!(:media_attachment) { Fabricate(:media_attachment, account: account) } - let!(:notification) { Fabricate(:notification, account: account) } - let!(:favourite) { Fabricate(:favourite, account: account) } - let!(:active_relationship) { Fabricate(:follow, account: account) } - let!(:passive_relationship) { Fabricate(:follow, target_account: account) } - let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', protocol: :activitypub) } - let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } - let!(:endorsment) { Fabricate(:account_pin, account: passive_relationship.account, target_account: account) } - - it 'deletes associated records' do - is_expected.to change { - [ - account.statuses, - account.media_attachments, - account.notifications, - account.favourites, - account.active_relationships, - account.passive_relationships, - AccountPin.where(target_account: account), - ].map(&:count) - }.from([1, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0]) - end - - it 'sends a delete actor activity to all known inboxes' do - subject.call - expect(a_request(:post, "https://alice.com/inbox")).to have_been_made.once - expect(a_request(:post, "https://bob.com/inbox")).to have_been_made.once - end - end - - describe '#call on remote account' do - before do - stub_request(:post, "https://alice.com/inbox").to_return(status: 201) - stub_request(:post, "https://bob.com/inbox").to_return(status: 201) - end - - subject do - -> { described_class.new.call(remote_bob) } - end - - let!(:account) { Fabricate(:account) } - let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', protocol: :activitypub) } - let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) } - let!(:status) { Fabricate(:status, account: remote_bob) } - let!(:media_attachment) { Fabricate(:media_attachment, account: remote_bob) } - let!(:notification) { Fabricate(:notification, account: remote_bob) } - let!(:favourite) { Fabricate(:favourite, account: remote_bob) } - let!(:active_relationship) { Fabricate(:follow, account: remote_bob, target_account: account) } - let!(:passive_relationship) { Fabricate(:follow, target_account: remote_bob) } - - it 'deletes associated records' do - is_expected.to change { - [ - remote_bob.statuses, - remote_bob.media_attachments, - remote_bob.notifications, - remote_bob.favourites, - remote_bob.active_relationships, - remote_bob.passive_relationships, - ].map(&:count) - }.from([1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0]) - end - - it 'sends a reject follow to follwer inboxes' do - subject.call - expect(a_request(:post, remote_bob.inbox_url)).to have_been_made.once - end - end -end diff --git a/spec/services/unallow_domain_service_spec.rb b/spec/services/unallow_domain_service_spec.rb index 559e152fb250e033b018ec6746c2ed7750c07d73..b93945b9a2ae45e04f7d1f5b6be133627982ca1d 100644 --- a/spec/services/unallow_domain_service_spec.rb +++ b/spec/services/unallow_domain_service_spec.rb @@ -55,9 +55,9 @@ RSpec.describe UnallowDomainService, type: :service do end it 'removes the remote accounts\'s statuses and media attachments' do - expect { bad_status1.reload }.to_not raise_exception ActiveRecord::RecordNotFound - expect { bad_status2.reload }.to_not raise_exception ActiveRecord::RecordNotFound - expect { bad_attachment.reload }.to_not raise_exception ActiveRecord::RecordNotFound + expect { bad_status1.reload }.to_not raise_error + expect { bad_status2.reload }.to_not raise_error + expect { bad_attachment.reload }.to_not raise_error end end end diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb index ccc5dc0f485050fb017d3df4b9f8270250950bad..f0708dc4623724aa6b7c09dc4a3d38442ebbcfe6 100644 --- a/spec/validators/blacklisted_email_validator_spec.rb +++ b/spec/validators/blacklisted_email_validator_spec.rb @@ -17,7 +17,7 @@ RSpec.describe BlacklistedEmailValidator, type: :validator do let(:blocked_email) { true } it 'calls errors.add' do - expect(errors).to have_received(:add).with(:email, I18n.t('users.invalid_email')) + expect(errors).to have_received(:add).with(:email, I18n.t('users.blocked_email_provider')) end end @@ -25,7 +25,7 @@ RSpec.describe BlacklistedEmailValidator, type: :validator do let(:blocked_email) { false } it 'not calls errors.add' do - expect(errors).not_to have_received(:add).with(:email, I18n.t('users.invalid_email')) + expect(errors).not_to have_received(:add).with(:email, I18n.t('users.blocked_email_provider')) end end end diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb index 351be185cd6939f533cc1dab5406272f27b54cac..f4633731e506769c19ea4f140b515aa7215b5d9c 100644 --- a/spec/workers/activitypub/delivery_worker_spec.rb +++ b/spec/workers/activitypub/delivery_worker_spec.rb @@ -3,16 +3,22 @@ require 'rails_helper' describe ActivityPub::DeliveryWorker do + include RoutingHelper + subject { described_class.new } let(:sender) { Fabricate(:account) } let(:payload) { 'test' } + before do + allow_any_instance_of(Account).to receive(:remote_followers_hash).with('https://example.com/').and_return('somehash') + end + describe 'perform' do it 'performs a request' do stub_request(:post, 'https://example.com/api').to_return(status: 200) - subject.perform(payload, sender.id, 'https://example.com/api') - expect(a_request(:post, 'https://example.com/api')).to have_been_made.once + subject.perform(payload, sender.id, 'https://example.com/api', { synchronize_followers: true }) + expect(a_request(:post, 'https://example.com/api').with(headers: { 'Collection-Synchronization' => "collectionId=\"#{account_followers_url(sender)}\", digest=\"somehash\", url=\"#{account_followers_synchronization_url(sender)}\"" })).to have_been_made.once end it 'raises when request fails' do diff --git a/spec/workers/refollow_worker_spec.rb b/spec/workers/refollow_worker_spec.rb index 29771aa59b7e396948bc861157e421a163b9103b..df6731b6400041db44247083945c7618ff166528 100644 --- a/spec/workers/refollow_worker_spec.rb +++ b/spec/workers/refollow_worker_spec.rb @@ -23,8 +23,8 @@ describe RefollowWorker do result = subject.perform(account.id) expect(result).to be_nil - expect(service).to have_received(:call).with(alice, account, reblogs: true) - expect(service).to have_received(:call).with(bob, account, reblogs: false) + expect(service).to have_received(:call).with(alice, account, reblogs: true, notify: false, bypass_limit: true) + expect(service).to have_received(:call).with(bob, account, reblogs: false, notify: false, bypass_limit: true) end end end diff --git a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb b/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb index 7fae680ba66a5df4ea96d8ef6bffe6520a416625..914eed829d298ee6ddca9c2d4512f25a983ec4f3 100644 --- a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb @@ -16,8 +16,8 @@ describe Scheduler::FeedCleanupScheduler do expect(Redis.current.zcard(feed_key_for(inactive_user))).to eq 0 expect(Redis.current.zcard(feed_key_for(active_user))).to eq 1 - expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs'))).to be false - expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs:2'))).to be false + expect(Redis.current.exists?(feed_key_for(inactive_user, 'reblogs'))).to be false + expect(Redis.current.exists?(feed_key_for(inactive_user, 'reblogs:2'))).to be false end def feed_key_for(user, subtype = nil) diff --git a/streaming/index.js b/streaming/index.js index 39e70c1ba7ef9ad1a1760b07616fe60c22773710..3279bd94ebc977a3195f06eb4ac7173c10488ca3 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -1,3 +1,5 @@ +// @ts-check + const os = require('os'); const throng = require('throng'); const dotenv = require('dotenv'); @@ -12,7 +14,7 @@ const uuid = require('uuid'); const fs = require('fs'); const env = process.env.NODE_ENV || 'development'; -const alwaysRequireAuth = process.env.WHITELIST_MODE === 'true' || process.env.AUTHORIZED_FETCH === 'true'; +const alwaysRequireAuth = process.env.LIMITED_FEDERATION_MODE === 'true' || process.env.WHITELIST_MODE === 'true' || process.env.AUTHORIZED_FETCH === 'true'; dotenv.config({ path: env === 'production' ? '.env.production' : '.env', @@ -20,6 +22,10 @@ dotenv.config({ log.level = process.env.LOG_LEVEL || 'verbose'; +/** + * @param {string} dbUrl + * @return {Object.<string, any>} + */ const dbUrlToConfig = (dbUrl) => { if (!dbUrl) { return {}; @@ -53,6 +59,10 @@ const dbUrlToConfig = (dbUrl) => { return config; }; +/** + * @param {Object.<string, any>} defaultConfig + * @param {string} redisUrl + */ const redisUrlToClient = (defaultConfig, redisUrl) => { const config = defaultConfig; @@ -71,6 +81,19 @@ const redisUrlToClient = (defaultConfig, redisUrl) => { const numWorkers = +process.env.STREAMING_CLUSTER_NUM || (env === 'development' ? 1 : Math.max(os.cpus().length - 1, 1)); +/** + * @param {string} json + * @return {Object.<string, any>|null} + */ +const parseJSON = (json) => { + try { + return JSON.parse(json); + } catch (err) { + log.error(err); + return null; + } +}; + const startMaster = () => { if (!process.env.SOCKET && process.env.PORT && isNaN(+process.env.PORT)) { log.warn('UNIX domain socket is now supported by using SOCKET. Please migrate from PORT hack.'); @@ -108,6 +131,7 @@ const startWorker = (workerId) => { } const app = express(); + app.set('trusted proxy', process.env.TRUSTED_PROXY_IP || 'loopback,uniquelocal'); const pgPool = new pg.Pool(Object.assign(pgConfigs[env], dbUrlToConfig(process.env.DATABASE_URL))); @@ -130,6 +154,9 @@ const startWorker = (workerId) => { const redisSubscribeClient = redisUrlToClient(redisParams, process.env.REDIS_URL); const redisClient = redisUrlToClient(redisParams, process.env.REDIS_URL); + /** + * @type {Object.<string, Array.<function(string): void>>} + */ const subs = {}; redisSubscribeClient.on('message', (channel, message) => { @@ -144,11 +171,11 @@ const startWorker = (workerId) => { callbacks.forEach(callback => callback(message)); }); + /** + * @param {string[]} channels + * @return {function(): void} + */ const subscriptionHeartbeat = channels => { - if (!Array.isArray(channels)) { - channels = [channels]; - } - const interval = 6 * 60; const tellSubscribed = () => { @@ -164,25 +191,66 @@ const startWorker = (workerId) => { }; }; + /** + * @param {string} channel + * @param {function(string): void} callback + */ const subscribe = (channel, callback) => { log.silly(`Adding listener for ${channel}`); subs[channel] = subs[channel] || []; + if (subs[channel].length === 0) { log.verbose(`Subscribe ${channel}`); redisSubscribeClient.subscribe(channel); } + subs[channel].push(callback); }; + /** + * @param {string} channel + * @param {function(string): void} callback + */ const unsubscribe = (channel, callback) => { log.silly(`Removing listener for ${channel}`); + + if (!subs[channel]) { + return; + } + subs[channel] = subs[channel].filter(item => item !== callback); + if (subs[channel].length === 0) { log.verbose(`Unsubscribe ${channel}`); redisSubscribeClient.unsubscribe(channel); + delete subs[channel]; } }; + const FALSE_VALUES = [ + false, + 0, + '0', + 'f', + 'F', + 'false', + 'FALSE', + 'off', + 'OFF', + ]; + + /** + * @param {any} value + * @return {boolean} + */ + const isTruthy = value => + value && !FALSE_VALUES.includes(value); + + /** + * @param {any} req + * @param {any} res + * @param {function(Error=): void} + */ const allowCrossDomain = (req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Authorization, Accept, Cache-Control'); @@ -191,6 +259,11 @@ const startWorker = (workerId) => { next(); }; + /** + * @param {any} req + * @param {any} res + * @param {function(Error=): void} + */ const setRequestId = (req, res, next) => { req.requestId = uuid.v4(); res.header('X-Request-Id', req.requestId); @@ -198,79 +271,118 @@ const startWorker = (workerId) => { next(); }; + /** + * @param {any} req + * @param {any} res + * @param {function(Error=): void} + */ const setRemoteAddress = (req, res, next) => { req.remoteAddress = req.connection.remoteAddress; next(); }; - const accountFromToken = (token, allowedScopes, req, next) => { + /** + * @param {string} token + * @param {any} req + * @return {Promise.<void>} + */ + const accountFromToken = (token, req) => new Promise((resolve, reject) => { pgPool.connect((err, client, done) => { if (err) { - next(err); + reject(err); return; } - client.query('SELECT oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token], (err, result) => { + client.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token], (err, result) => { done(); if (err) { - next(err); + reject(err); return; } if (result.rows.length === 0) { err = new Error('Invalid access token'); - err.statusCode = 401; - - next(err); - return; - } - - const scopes = result.rows[0].scopes.split(' '); + err.status = 401; - if (allowedScopes.size > 0 && !scopes.some(scope => allowedScopes.includes(scope))) { - err = new Error('Access token does not cover required scopes'); - err.statusCode = 401; - - next(err); + reject(err); return; } + req.accessTokenId = result.rows[0].id; + req.scopes = result.rows[0].scopes.split(' '); req.accountId = result.rows[0].account_id; req.chosenLanguages = result.rows[0].chosen_languages; - req.allowNotifications = scopes.some(scope => ['read', 'read:notifications'].includes(scope)); + req.allowNotifications = req.scopes.some(scope => ['read', 'read:notifications'].includes(scope)); req.deviceId = result.rows[0].device_id; - next(); + resolve(); }); }); - }; + }); - const accountFromRequest = (req, next, required = true, allowedScopes = ['read']) => { + /** + * @param {any} req + * @param {boolean=} required + * @return {Promise.<void>} + */ + const accountFromRequest = (req, required = true) => new Promise((resolve, reject) => { const authorization = req.headers.authorization; - const location = url.parse(req.url, true); - const accessToken = location.query.access_token || req.headers['sec-websocket-protocol']; + const location = url.parse(req.url, true); + const accessToken = location.query.access_token || req.headers['sec-websocket-protocol']; if (!authorization && !accessToken) { if (required) { const err = new Error('Missing access token'); - err.statusCode = 401; + err.status = 401; - next(err); + reject(err); return; } else { - next(); + resolve(); return; } } const token = authorization ? authorization.replace(/^Bearer /, '') : accessToken; - accountFromToken(token, allowedScopes, req, next); + resolve(accountFromToken(token, req)); + }); + + /** + * @param {any} req + * @return {string} + */ + const channelNameFromPath = req => { + const { path, query } = req; + const onlyMedia = isTruthy(query.only_media); + + switch(path) { + case '/api/v1/streaming/user': + return 'user'; + case '/api/v1/streaming/user/notification': + return 'user:notification'; + case '/api/v1/streaming/public': + return onlyMedia ? 'public:media' : 'public'; + case '/api/v1/streaming/public/local': + return onlyMedia ? 'public:local:media' : 'public:local'; + case '/api/v1/streaming/public/remote': + return onlyMedia ? 'public:remote:media' : 'public:remote'; + case '/api/v1/streaming/hashtag': + return 'hashtag'; + case '/api/v1/streaming/hashtag/local': + return 'hashtag:local'; + case '/api/v1/streaming/direct': + return 'direct'; + case '/api/v1/streaming/list': + return 'list'; + default: + return undefined; + } }; - const PUBLIC_STREAMS = [ + const PUBLIC_CHANNELS = [ 'public', 'public:media', 'public:local', @@ -281,99 +393,208 @@ const startWorker = (workerId) => { 'hashtag:local', ]; - const wsVerifyClient = (info, cb) => { - const location = url.parse(info.req.url, true); - const authRequired = alwaysRequireAuth || !PUBLIC_STREAMS.some(stream => stream === location.query.stream); - const allowedScopes = []; + /** + * @param {any} req + * @param {string} channelName + * @return {Promise.<void>} + */ + const checkScopes = (req, channelName) => new Promise((resolve, reject) => { + log.silly(req.requestId, `Checking OAuth scopes for ${channelName}`); + + // When accessing public channels, no scopes are needed + if (PUBLIC_CHANNELS.includes(channelName)) { + resolve(); + return; + } - if (authRequired) { - allowedScopes.push('read'); - if (location.query.stream === 'user:notification') { - allowedScopes.push('read:notifications'); - } else { - allowedScopes.push('read:statuses'); - } + // The `read` scope has the highest priority, if the token has it + // then it can access all streams + const requiredScopes = ['read']; + + // When accessing specifically the notifications stream, + // we need a read:notifications, while in all other cases, + // we can allow access with read:statuses. Mind that the + // user stream will not contain notifications unless + // the token has either read or read:notifications scope + // as well, this is handled separately. + if (channelName === 'user:notification') { + requiredScopes.push('read:notifications'); + } else { + requiredScopes.push('read:statuses'); } - accountFromRequest(info.req, err => { - if (!err) { - cb(true, undefined, undefined); - } else { - log.error(info.req.requestId, err.toString()); - cb(false, 401, 'Unauthorized'); + if (requiredScopes.some(requiredScope => req.scopes.includes(requiredScope))) { + resolve(); + return; + } + + const err = new Error('Access token does not cover required scopes'); + err.status = 401; + + reject(err); + }); + + /** + * @param {any} info + * @param {function(boolean, number, string): void} callback + */ + const wsVerifyClient = (info, callback) => { + // When verifying the websockets connection, we no longer pre-emptively + // check OAuth scopes and drop the connection if they're missing. We only + // drop the connection if access without token is not allowed by environment + // variables. OAuth scope checks are moved to the point of subscription + // to a specific stream. + + accountFromRequest(info.req, alwaysRequireAuth).then(() => { + callback(true, undefined, undefined); + }).catch(err => { + log.error(info.req.requestId, err.toString()); + callback(false, 401, 'Unauthorized'); + }); + }; + + /** + * @typedef SystemMessageHandlers + * @property {function(): void} onKill + */ + + /** + * @param {any} req + * @param {SystemMessageHandlers} eventHandlers + * @return {function(string): void} + */ + const createSystemMessageListener = (req, eventHandlers) => { + return message => { + const json = parseJSON(message); + + if (!json) return; + + const { event } = json; + + log.silly(req.requestId, `System message for ${req.accountId}: ${event}`); + + if (event === 'kill') { + log.verbose(req.requestId, `Closing connection for ${req.accountId} due to expired access token`); + eventHandlers.onKill(); } - }, authRequired, allowedScopes); + }; }; - const PUBLIC_ENDPOINTS = [ - '/api/v1/streaming/public', - '/api/v1/streaming/public/local', - '/api/v1/streaming/public/remote', - '/api/v1/streaming/hashtag', - '/api/v1/streaming/hashtag/local', - ]; + /** + * @param {any} req + * @param {any} res + */ + const subscribeHttpToSystemChannel = (req, res) => { + const systemChannelId = `timeline:access_token:${req.accessTokenId}`; + + const listener = createSystemMessageListener(req, { + + onKill () { + res.end(); + }, + + }); + + res.on('close', () => { + unsubscribe(`${redisPrefix}${systemChannelId}`, listener); + }); + subscribe(`${redisPrefix}${systemChannelId}`, listener); + }; + + /** + * @param {any} req + * @param {any} res + * @param {function(Error=): void} next + */ const authenticationMiddleware = (req, res, next) => { if (req.method === 'OPTIONS') { next(); return; } - const authRequired = alwaysRequireAuth || !PUBLIC_ENDPOINTS.some(endpoint => endpoint === req.path); - const allowedScopes = []; - - if (authRequired) { - allowedScopes.push('read'); - if (req.path === '/api/v1/streaming/user/notification') { - allowedScopes.push('read:notifications'); - } else { - allowedScopes.push('read:statuses'); - } - } - - accountFromRequest(req, next, authRequired, allowedScopes); + accountFromRequest(req, alwaysRequireAuth).then(() => checkScopes(req, channelNameFromPath(req))).then(() => { + subscribeHttpToSystemChannel(req, res); + }).then(() => { + next(); + }).catch(err => { + next(err); + }); }; - const errorMiddleware = (err, req, res, {}) => { + /** + * @param {Error} err + * @param {any} req + * @param {any} res + * @param {function(Error=): void} next + */ + const errorMiddleware = (err, req, res, next) => { log.error(req.requestId, err.toString()); - res.writeHead(err.statusCode || 500, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: err.statusCode ? err.toString() : 'An unexpected error occurred' })); + + if (res.headersSent) { + next(err); + return; + } + + res.writeHead(err.status || 500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: err.status ? err.toString() : 'An unexpected error occurred' })); }; + /** + * @param {array} + * @param {number=} shift + * @return {string} + */ const placeholders = (arr, shift = 0) => arr.map((_, i) => `$${i + 1 + shift}`).join(', '); - const authorizeListAccess = (id, req, next) => { + /** + * @param {string} listId + * @param {any} req + * @return {Promise.<void>} + */ + const authorizeListAccess = (listId, req) => new Promise((resolve, reject) => { + const { accountId } = req; + pgPool.connect((err, client, done) => { if (err) { - next(false); + reject(); return; } - client.query('SELECT id, account_id FROM lists WHERE id = $1 LIMIT 1', [id], (err, result) => { + client.query('SELECT id, account_id FROM lists WHERE id = $1 LIMIT 1', [listId], (err, result) => { done(); - if (err || result.rows.length === 0 || result.rows[0].account_id !== req.accountId) { - next(false); + if (err || result.rows.length === 0 || result.rows[0].account_id !== accountId) { + reject(); return; } - next(true); + resolve(); }); }); - }; + }); + /** + * @param {string[]} ids + * @param {any} req + * @param {function(string, string): void} output + * @param {function(string[], function(string): void): void} attachCloseHandler + * @param {boolean=} needsFiltering + * @param {boolean=} notificationOnly + * @return {function(string): void} + */ const streamFrom = (ids, req, output, attachCloseHandler, needsFiltering = false, notificationOnly = false) => { const accountId = req.accountId || req.remoteAddress; const streamType = notificationOnly ? ' (notification)' : ''; - if (!Array.isArray(ids)) { - ids = [ids]; - } - log.verbose(req.requestId, `Starting stream from ${ids.join(', ')} for ${accountId}${streamType}`); const listener = message => { - const { event, payload, queued_at } = JSON.parse(message); + const json = parseJSON(message); + + if (!json) return; + + const { event, payload, queued_at } = json; const transmit = () => { const now = new Date().getTime(); @@ -447,10 +668,18 @@ const startWorker = (workerId) => { subscribe(`${redisPrefix}${id}`, listener); }); - attachCloseHandler(ids.map(id => `${redisPrefix}${id}`), listener); + if (attachCloseHandler) { + attachCloseHandler(ids.map(id => `${redisPrefix}${id}`), listener); + } + + return listener; }; - // Setup stream output to HTTP + /** + * @param {any} req + * @param {any} res + * @return {function(string, string): void} + */ const streamToHttp = (req, res) => { const accountId = req.accountId || req.remoteAddress; @@ -473,12 +702,12 @@ const startWorker = (workerId) => { }; }; - // Setup stream end for HTTP - const streamHttpEnd = (req, closeHandler = false) => (ids, listener) => { - if (!Array.isArray(ids)) { - ids = [ids]; - } - + /** + * @param {any} req + * @param {function(): void} [closeHandler] + * @return {function(string[], function(string): void)} + */ + const streamHttpEnd = (req, closeHandler = undefined) => (ids, listener) => { req.on('close', () => { ids.forEach(id => { unsubscribe(id, listener); @@ -490,37 +719,24 @@ const startWorker = (workerId) => { }); }; - // Setup stream output to WebSockets - const streamToWs = (req, ws) => (event, payload) => { + /** + * @param {any} req + * @param {any} ws + * @param {string[]} streamName + * @return {function(string, string): void} + */ + const streamToWs = (req, ws, streamName) => (event, payload) => { if (ws.readyState !== ws.OPEN) { log.error(req.requestId, 'Tried writing to closed socket'); return; } - ws.send(JSON.stringify({ event, payload })); - }; - - // Setup stream end for WebSockets - const streamWsEnd = (req, ws, closeHandler = false) => (id, listener) => { - const accountId = req.accountId || req.remoteAddress; - - ws.on('close', () => { - log.verbose(req.requestId, `Ending stream for ${accountId}`); - unsubscribe(id, listener); - if (closeHandler) { - closeHandler(); - } - }); - - ws.on('error', () => { - log.verbose(req.requestId, `Ending stream for ${accountId}`); - unsubscribe(id, listener); - if (closeHandler) { - closeHandler(); - } - }); + ws.send(JSON.stringify({ stream: streamName, event, payload })); }; + /** + * @param {any} res + */ const httpNotFound = res => { res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Not found' })); @@ -538,157 +754,297 @@ const startWorker = (workerId) => { app.use(authenticationMiddleware); app.use(errorMiddleware); - app.get('/api/v1/streaming/user', (req, res) => { - const channels = [`timeline:${req.accountId}`]; - - if (req.deviceId) { - channels.push(`timeline:${req.accountId}:${req.deviceId}`); - } - - streamFrom(channels, req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channels))); - }); - - app.get('/api/v1/streaming/user/notification', (req, res) => { - streamFrom(`timeline:${req.accountId}`, req, streamToHttp(req, res), streamHttpEnd(req), false, true); - }); - - app.get('/api/v1/streaming/public', (req, res) => { - const onlyMedia = req.query.only_media === '1' || req.query.only_media === 'true'; - const channel = onlyMedia ? 'timeline:public:media' : 'timeline:public'; - - streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req), true); - }); - - app.get('/api/v1/streaming/public/local', (req, res) => { - const onlyMedia = req.query.only_media === '1' || req.query.only_media === 'true'; - const channel = onlyMedia ? 'timeline:public:local:media' : 'timeline:public:local'; - - streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req), true); - }); - - app.get('/api/v1/streaming/public/remote', (req, res) => { - const onlyMedia = req.query.only_media === '1' || req.query.only_media === 'true'; - const channel = onlyMedia ? 'timeline:public:remote:media' : 'timeline:public:remote'; - - streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req), true); - }); - - app.get('/api/v1/streaming/direct', (req, res) => { - const channel = `timeline:direct:${req.accountId}`; - streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channel)), true); - }); - - app.get('/api/v1/streaming/hashtag', (req, res) => { - const { tag } = req.query; - - if (!tag || tag.length === 0) { - httpNotFound(res); - return; - } - - streamFrom(`timeline:hashtag:${tag.toLowerCase()}`, req, streamToHttp(req, res), streamHttpEnd(req), true); - }); - - app.get('/api/v1/streaming/hashtag/local', (req, res) => { - const { tag } = req.query; + app.get('/api/v1/streaming/*', (req, res) => { + channelNameToIds(req, channelNameFromPath(req), req.query).then(({ channelIds, options }) => { + const onSend = streamToHttp(req, res); + const onEnd = streamHttpEnd(req, subscriptionHeartbeat(channelIds)); - if (!tag || tag.length === 0) { + streamFrom(channelIds, req, onSend, onEnd, options.needsFiltering, options.notificationOnly); + }).catch(err => { + log.verbose(req.requestId, 'Subscription error:', err.toString()); httpNotFound(res); - return; - } - - streamFrom(`timeline:hashtag:${tag.toLowerCase()}:local`, req, streamToHttp(req, res), streamHttpEnd(req), true); - }); - - app.get('/api/v1/streaming/list', (req, res) => { - const listId = req.query.list; - - authorizeListAccess(listId, req, authorized => { - if (!authorized) { - httpNotFound(res); - return; - } - - const channel = `timeline:list:${listId}`; - streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channel))); }); }); const wss = new WebSocketServer({ server, verifyClient: wsVerifyClient }); - wss.on('connection', (ws, req) => { - const location = url.parse(req.url, true); - req.requestId = uuid.v4(); - req.remoteAddress = ws._socket.remoteAddress; - - let channel; - - switch(location.query.stream) { + /** + * @typedef StreamParams + * @property {string} [tag] + * @property {string} [list] + * @property {string} [only_media] + */ + + /** + * @param {any} req + * @param {string} name + * @param {StreamParams} params + * @return {Promise.<{ channelIds: string[], options: { needsFiltering: boolean, notificationOnly: boolean } }>} + */ + const channelNameToIds = (req, name, params) => new Promise((resolve, reject) => { + switch(name) { case 'user': - channel = [`timeline:${req.accountId}`]; - - if (req.deviceId) { - channel.push(`timeline:${req.accountId}:${req.deviceId}`); - } + resolve({ + channelIds: req.deviceId ? [`timeline:${req.accountId}`, `timeline:${req.accountId}:${req.deviceId}`] : [`timeline:${req.accountId}`], + options: { needsFiltering: false, notificationOnly: false }, + }); - streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel))); break; case 'user:notification': - streamFrom(`timeline:${req.accountId}`, req, streamToWs(req, ws), streamWsEnd(req, ws), false, true); + resolve({ + channelIds: [`timeline:${req.accountId}`], + options: { needsFiltering: false, notificationOnly: true }, + }); + break; case 'public': - streamFrom('timeline:public', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'public:local': - streamFrom('timeline:public:local', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public:local'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'public:remote': - streamFrom('timeline:public:remote', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public:remote'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'public:media': - streamFrom('timeline:public:media', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public:media'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'public:local:media': - streamFrom('timeline:public:local:media', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public:local:media'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'public:remote:media': - streamFrom('timeline:public:remote:media', req, streamToWs(req, ws), streamWsEnd(req, ws), true); + resolve({ + channelIds: ['timeline:public:remote:media'], + options: { needsFiltering: true, notificationOnly: false }, + }); + break; case 'direct': - channel = `timeline:direct:${req.accountId}`; - streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel)), true); + resolve({ + channelIds: [`timeline:direct:${req.accountId}`], + options: { needsFiltering: false, notificationOnly: false }, + }); + break; case 'hashtag': - if (!location.query.tag || location.query.tag.length === 0) { - ws.close(); - return; + if (!params.tag || params.tag.length === 0) { + reject('No tag for stream provided'); + } else { + resolve({ + channelIds: [`timeline:hashtag:${params.tag.toLowerCase()}`], + options: { needsFiltering: true, notificationOnly: false }, + }); } - streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}`, req, streamToWs(req, ws), streamWsEnd(req, ws), true); break; case 'hashtag:local': - if (!location.query.tag || location.query.tag.length === 0) { - ws.close(); - return; + if (!params.tag || params.tag.length === 0) { + reject('No tag for stream provided'); + } else { + resolve({ + channelIds: [`timeline:hashtag:${params.tag.toLowerCase()}:local`], + options: { needsFiltering: true, notificationOnly: false }, + }); } - streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}:local`, req, streamToWs(req, ws), streamWsEnd(req, ws), true); break; case 'list': - const listId = location.query.list; - - authorizeListAccess(listId, req, authorized => { - if (!authorized) { - ws.close(); - return; - } - - channel = `timeline:list:${listId}`; - streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel))); + authorizeListAccess(params.list, req).then(() => { + resolve({ + channelIds: [`timeline:list:${params.list}`], + options: { needsFiltering: false, notificationOnly: false }, + }); + }).catch(() => { + reject('Not authorized to stream this list'); }); + break; default: - ws.close(); + reject('Unknown stream type'); + } + }); + + /** + * @param {string} channelName + * @param {StreamParams} params + * @return {string[]} + */ + const streamNameFromChannelName = (channelName, params) => { + if (channelName === 'list') { + return [channelName, params.list]; + } else if (['hashtag', 'hashtag:local'].includes(channelName)) { + return [channelName, params.tag]; + } else { + return [channelName]; + } + }; + + /** + * @typedef WebSocketSession + * @property {any} socket + * @property {any} request + * @property {Object.<string, { listener: function(string): void, stopHeartbeat: function(): void }>} subscriptions + */ + + /** + * @param {WebSocketSession} session + * @param {string} channelName + * @param {StreamParams} params + */ + const subscribeWebsocketToChannel = ({ socket, request, subscriptions }, channelName, params) => + checkScopes(request, channelName).then(() => channelNameToIds(request, channelName, params)).then(({ channelIds, options }) => { + if (subscriptions[channelIds.join(';')]) { + return; + } + + const onSend = streamToWs(request, socket, streamNameFromChannelName(channelName, params)); + const stopHeartbeat = subscriptionHeartbeat(channelIds); + const listener = streamFrom(channelIds, request, onSend, undefined, options.needsFiltering, options.notificationOnly); + + subscriptions[channelIds.join(';')] = { + listener, + stopHeartbeat, + }; + }).catch(err => { + log.verbose(request.requestId, 'Subscription error:', err.toString()); + socket.send(JSON.stringify({ error: err.toString() })); + }); + + /** + * @param {WebSocketSession} session + * @param {string} channelName + * @param {StreamParams} params + */ + const unsubscribeWebsocketFromChannel = ({ socket, request, subscriptions }, channelName, params) => + channelNameToIds(request, channelName, params).then(({ channelIds }) => { + log.verbose(request.requestId, `Ending stream from ${channelIds.join(', ')} for ${request.accountId}`); + + const subscription = subscriptions[channelIds.join(';')]; + + if (!subscription) { + return; + } + + const { listener, stopHeartbeat } = subscription; + + channelIds.forEach(channelId => { + unsubscribe(`${redisPrefix}${channelId}`, listener); + }); + + stopHeartbeat(); + + delete subscriptions[channelIds.join(';')]; + }).catch(err => { + log.verbose(request.requestId, 'Unsubscription error:', err); + socket.send(JSON.stringify({ error: err.toString() })); + }); + + /** + * @param {WebSocketSession} session + */ + const subscribeWebsocketToSystemChannel = ({ socket, request, subscriptions }) => { + const systemChannelId = `timeline:access_token:${request.accessTokenId}`; + + const listener = createSystemMessageListener(request, { + + onKill () { + socket.close(); + }, + + }); + + subscribe(`${redisPrefix}${systemChannelId}`, listener); + + subscriptions[systemChannelId] = { + listener, + stopHeartbeat: () => {}, + }; + }; + + /** + * @param {string|string[]} arrayOrString + * @return {string} + */ + const firstParam = arrayOrString => { + if (Array.isArray(arrayOrString)) { + return arrayOrString[0]; + } else { + return arrayOrString; + } + }; + + wss.on('connection', (ws, req) => { + const location = url.parse(req.url, true); + + req.requestId = uuid.v4(); + req.remoteAddress = ws._socket.remoteAddress; + + /** + * @type {WebSocketSession} + */ + const session = { + socket: ws, + request: req, + subscriptions: {}, + }; + + const onEnd = () => { + const keys = Object.keys(session.subscriptions); + + keys.forEach(channelIds => { + const { listener, stopHeartbeat } = session.subscriptions[channelIds]; + + channelIds.split(';').forEach(channelId => { + unsubscribe(`${redisPrefix}${channelId}`, listener); + }); + + stopHeartbeat(); + }); + }; + + ws.on('close', onEnd); + ws.on('error', onEnd); + + ws.on('message', data => { + const json = parseJSON(data); + + if (!json) return; + + const { type, stream, ...params } = json; + + if (type === 'subscribe') { + subscribeWebsocketToChannel(session, firstParam(stream), params); + } else if (type === 'unsubscribe') { + unsubscribeWebsocketFromChannel(session, firstParam(stream), params); + } else { + // Unknown action type + } + }); + + subscribeWebsocketToSystemChannel(session); + + if (location.query.stream) { + subscribeWebsocketToChannel(session, firstParam(location.query.stream), location.query); } }); @@ -716,6 +1072,10 @@ const startWorker = (workerId) => { process.on('uncaughtException', onError); }; +/** + * @param {any} server + * @param {function(string): void} [onSuccess] + */ const attachServerWithConfig = (server, onSuccess) => { if (process.env.SOCKET || process.env.PORT && isNaN(+process.env.PORT)) { server.listen(process.env.SOCKET || process.env.PORT, () => { @@ -733,6 +1093,9 @@ const attachServerWithConfig = (server, onSuccess) => { } }; +/** + * @param {function(Error=): void} onSuccess + */ const onPortAvailable = onSuccess => { const testServer = http.createServer(); diff --git a/yarn.lock b/yarn.lock index 5449ae10ff52ab922630698b29fbb57ebb0842a1..450363e3046b3c9a6e6d18135b73f592bf882db7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,91 +2,46 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.3.tgz#324bcfd8d35cd3d47dae18cde63d752086435e9a" - integrity sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg== - dependencies: - "@babel/highlight" "^7.10.3" +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== -"@babel/compat-data@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.4.tgz#706a6484ee6f910b719b696a9194f8da7d7ac241" - integrity sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw== - dependencies: - browserslist "^4.12.0" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/core@^7.1.0", "@babel/core@^7.7.5": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" - integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== +"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.7.2", "@babel/core@^7.7.5": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.10.3", "@babel/core@^7.7.2": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.3.tgz#73b0e8ddeec1e3fdd7a2de587a60e17c440ec77e" - integrity sha512-5YqWxYE3pyhIi84L84YcwjeEgS+fa7ZjK6IBVGTjDVfm64njkR2lfDhVR5OudLk8x2GK59YoSyVv+L/03k1q9w== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helpers" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/traverse" "^7.10.3" - "@babel/types" "^7.10.3" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" + lodash "^4.17.19" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.3.tgz#32b9a0d963a71d7a54f5f6c15659c3dbc2a523a5" - integrity sha512-drt8MUHbEqRzNR0xnF8nMehbY11b1SDkRw03PSNH/3Rb2Z35oxkddVSi3rcaak0YJQ86PCuE7Qx1jSFhbLNBMA== +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.12.11" jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" - integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== - dependencies: - "@babel/types" "^7.10.4" - jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/helper-annotate-as-pure@^7.10.4": @@ -96,6 +51,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -104,14 +66,23 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.4.tgz#d0ffb875184d749c63ffe1f4f65be15143ec322d" - integrity sha512-LyacH/kgQPgLAuaWrvvq1+E7f5bLyT8jXCh7nM67sRsy2cpIGfgWJ+FCnAKQXfY+F0tXUaN6FqLkp4JiCzdK8Q== +"@babel/helper-builder-react-jsx-experimental@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.10.tgz#a58cb96a793dc0fcd5c9ed3bb36d62fdc60534c2" + integrity sha512-3Kcr2LGpL7CTRDTTYm1bzeor9qZbxbvU2AxsLA6mUG9gYarSfIKMK0UlU+azLWI+s0+BH768bwyaziWB2NOJlQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/types" "^7.12.10" + +"@babel/helper-builder-react-jsx-experimental@^7.12.4": + version "7.12.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" + integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/helper-module-imports" "^7.12.1" + "@babel/types" "^7.12.1" "@babel/helper-builder-react-jsx@^7.10.4": version "7.10.4" @@ -121,49 +92,35 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" - integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== +"@babel/helper-compilation-targets@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: - "@babel/compat-data" "^7.10.4" - browserslist "^4.12.0" - invariant "^2.2.4" - levenary "^1.1.1" + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.3.tgz#2783daa6866822e3d5ed119163b50f0fc3ae4b35" - integrity sha512-iRT9VwqtdFmv7UheJWthGc/h2s7MqoweBF9RUj77NFZsg9VfISvBTum3k6coAhJ8RWv2tj3yUjA03HxPd0vfpQ== - dependencies: - "@babel/helper-function-name" "^7.10.3" - "@babel/helper-member-expression-to-functions" "^7.10.3" - "@babel/helper-optimise-call-expression" "^7.10.3" - "@babel/helper-plugin-utils" "^7.10.3" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - -"@babel/helper-create-class-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz#2d4015d0136bd314103a70d84a7183e4b344a355" - integrity sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ== +"@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== dependencies: "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" -"@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== +"@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" + integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" + regexpu-core "^4.7.1" "@babel/helper-define-map@^7.10.4": version "7.10.4" @@ -182,15 +139,6 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-function-name@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.3.tgz#79316cd75a9fa25ba9787ff54544307ed444f197" - integrity sha512-FvSj2aiOd8zbeqijjgqdMDSyxsGHaMt5Tr0XjQsGKHD3/1FP3wksjnLAWzxw7lvXiej8W1Jt47SKTZ6upQNiRw== - dependencies: - "@babel/helper-get-function-arity" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/types" "^7.10.3" - "@babel/helper-function-name@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" @@ -200,12 +148,14 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-get-function-arity@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.3.tgz#3a28f7b28ccc7719eacd9223b659fdf162e4c45e" - integrity sha512-iUD/gFsR+M6uiy69JA6fzM5seno8oE85IYZdbVVEuQaZlEzMO2MXblh+KSPJgsZAUx0EEbWXU0yJaW7C9CdAVg== +"@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: - "@babel/types" "^7.10.3" + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" "@babel/helper-get-function-arity@^7.10.4": version "7.10.4" @@ -214,6 +164,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" @@ -221,59 +178,34 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.1", "@babel/helper-member-expression-to-functions@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.3.tgz#bc3663ac81ac57c39148fef4c69bf48a77ba8dd6" - integrity sha512-q7+37c4EPLSjNb2NmWOjNwj0+BOyYlssuQ58kHEWk1Z78K5i8vTUsteq78HMieRPQSl/NtpQyJfdjt3qZ5V2vw== +"@babel/helper-member-expression-to-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.12.1" -"@babel/helper-member-expression-to-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz#7cd04b57dfcf82fce9aeae7d4e4452fa31b8c7c4" - integrity sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A== +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.5" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.10.1", "@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-module-transforms@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" - integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== - dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" - -"@babel/helper-module-transforms@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" - integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.10.1", "@babel/helper-optimise-call-expression@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.3.tgz#f53c4b6783093195b0f69330439908841660c530" - integrity sha512-kT2R3VBH/cnSz+yChKpaKRJQJWxdGoc6SjioRId2wkeV3bK0wLLioFpJROrX0U4xr/NmxSSAWT/9Ih5snwIIzg== - dependencies: - "@babel/types" "^7.10.3" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" @@ -282,7 +214,7 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.1", "@babel/helper-plugin-utils@^7.10.3", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== @@ -294,59 +226,38 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" - integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== +"@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-wrap-function" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" -"@babel/helper-replace-supers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" - integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== +"@babel/helper-replace-supers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" + integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-simple-access@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" - integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== - dependencies: - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" - integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.10.4": version "7.10.4" @@ -355,16 +266,35 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-validator-identifier@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" - integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + dependencies: + "@babel/types" "^7.12.11" "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -375,32 +305,14 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" - integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== - dependencies: - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== +"@babel/helpers@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/highlight@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.3.tgz#c633bb34adf07c5c13156692f5922c81ec53f28d" - integrity sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw== - dependencies: - "@babel/helper-validator-identifier" "^7.10.3" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" "@babel/highlight@^7.10.4": version "7.10.4" @@ -411,113 +323,125 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" - integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== -"@babel/parser@^7.10.3", "@babel/parser@^7.7.0": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" - integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== - -"@babel/plugin-proposal-async-generator-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" - integrity sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg== +"@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" + integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" - integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-decorators@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.3.tgz#2fc6b5696028adccfcd14bc826c184c578b857f8" - integrity sha512-Rzwn5tcYFTdWWK3IrhMZkMDjzFQLIGYqHvv9XuzNnEB91Y6gHr/JjazYV1Yec9g0yMLhy1p/21eiW1P7f5UN4A== +"@babel/plugin-proposal-decorators@^7.12.12": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.12.12.tgz#067a6d3d6ca86d54cf56bb183239199c20daeafe" + integrity sha512-fhkE9lJYpw2mjHelBpM2zCbaA11aov2GJs7q4cFaXNrWx0H3bW58H9Esy2rdtYOghFBEYUDRIpvlgi+ZD+AvvQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.3" - "@babel/helper-plugin-utils" "^7.10.3" - "@babel/plugin-syntax-decorators" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-decorators" "^7.12.1" -"@babel/plugin-proposal-dynamic-import@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" - integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== +"@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" - integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== +"@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== +"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" - integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== +"@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" - integrity sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA== +"@babel/plugin-proposal-object-rest-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-optional-catch-binding@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" - integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== +"@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" - integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== +"@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-private-methods@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" - integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== +"@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" - integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": @@ -534,19 +458,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.10.4", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" - integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== +"@babel/plugin-syntax-class-properties@^7.12.1", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-decorators@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.1.tgz#16b869c4beafc9a442565147bda7ce0967bd4f13" - integrity sha512-a9OAbQhKOwSle1Vr0NJu/ISg1sPfdEkfRKWpgPuzhnWWzForou2gIeUIIwjAMHRekhhpJ7eulZlYs0H14Cbi+g== +"@babel/plugin-syntax-decorators@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.1.tgz#81a8b535b284476c41be6de06853a8802b98c5dd" + integrity sha512-ir9YW5daRrTYiy9UJ2TzdNIJEZu8KclVzDcfSt4iEmOtwQ4llPtWInNKJyKnVXp1vE4bbVd5S31M/im3mYMO1w== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" @@ -555,6 +479,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -569,14 +500,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" - integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== +"@babel/plugin-syntax-jsx@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -618,400 +549,383 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" - integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== +"@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" - integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== +"@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" - integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== +"@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== dependencies: - "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-module-imports" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" -"@babel/plugin-transform-block-scoped-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" - integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== +"@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz#a670d1364bb5019a621b9ea2001482876d734787" - integrity sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A== +"@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" - integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== +"@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-define-map" "^7.10.4" "@babel/helper-function-name" "^7.10.4" "@babel/helper-optimise-call-expression" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" - integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== +"@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" - integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== +"@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" - integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" - integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== +"@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" - integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== +"@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-for-of@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" - integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== +"@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" - integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== +"@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== dependencies: "@babel/helper-function-name" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" - integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== +"@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" - integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== +"@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz#cb407c68b862e4c1d13a2fc738c7ec5ed75fc520" - integrity sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA== +"@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" - integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== +"@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz#8f576afd943ac2f789b35ded0a6312f929c633f9" - integrity sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ== +"@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== dependencies: "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" - integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== +"@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== dependencies: - "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" - integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" -"@babel/plugin-transform-new-target@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" - integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== +"@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" - integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== +"@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" -"@babel/plugin-transform-parameters@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz#7b4d137c87ea7adc2a0f3ebf53266871daa6fced" - integrity sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ== +"@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== dependencies: - "@babel/helper-get-function-arity" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" - integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== +"@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" - integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== +"@babel/plugin-transform-react-display-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-inline-elements@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.10.4.tgz#9b7ea0051d3d10520bd7e0d5b021eb49fa311674" - integrity sha512-Pu5eO9xGwtsPA7N7Qp36D0BKdfmuh0rmWKBEoJHfzPWICOSkJX/UPwqLr1myCnjccpvkOhBcP2WFbEAPTAkYiA== +"@babel/plugin-transform-react-inline-elements@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.12.1.tgz#f7d507200923adbbdacb107feec7ad09cefae631" + integrity sha512-9ZuH22V68nUyLkhSJYKBqQr10d/gqmyAEeffpGXh3cRkETDUVDaY5PgX/dg8id419KoyWc5VCwsCgJVmxxAk3g== dependencies: "@babel/helper-builder-react-jsx" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" - integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== - dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" - -"@babel/plugin-transform-react-jsx-self@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" - integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" - -"@babel/plugin-transform-react-jsx-source@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.4.tgz#86baf0fcccfe58084e06446a80858e1deae8f291" - integrity sha512-FTK3eQFrPv2aveerUSazFmGygqIdTtvskG50SnGnbEUnRPcGx2ylBhdFIzoVS1ty44hEgcPoCAyw5r3VDEq+Ug== +"@babel/plugin-transform-react-jsx-development@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.7.tgz#4c2a647de79c7e2b16bfe4540677ba3121e82a08" + integrity sha512-Rs3ETtMtR3VLXFeYRChle5SsP/P9Jp/6dsewBQfokDSzKJThlsuFcnzLTDRALiUmTC48ej19YD9uN1mupEeEDg== dependencies: + "@babel/helper-builder-react-jsx-experimental" "^7.12.4" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" -"@babel/plugin-transform-react-jsx@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" - integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== +"@babel/plugin-transform-react-jsx@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.10.tgz#a7af3097c73479123594c8c8fe39545abebd44e3" + integrity sha512-MM7/BC8QdHXM7Qc1wdnuk73R4gbuOpfrSUgfV/nODGc86sPY1tgmY2M9E9uAnf2e4DOIp8aKGWqgZfQxnTNGuw== dependencies: "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.12.10" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" -"@babel/plugin-transform-react-pure-annotations@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" - integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== +"@babel/plugin-transform-react-pure-annotations@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" - integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== +"@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" - integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== +"@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-runtime@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.4.tgz#594fb53453ea1b6f0779cceb48ce0718a447feb7" - integrity sha512-8ULlGv8p+Vuxu+kz2Y1dk6MYS2b/Dki+NO6/0ZlfSj5tMalfDL7jI/o/2a+rrWLqSXvnadEqc2WguB4gdQIxZw== +"@babel/plugin-transform-runtime@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" + integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== dependencies: - "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" - resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" - integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== +"@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-spread@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz#4e2c85ea0d6abaee1b24dcfbbae426fe8d674cff" - integrity sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ== +"@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== dependencies: "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" -"@babel/plugin-transform-sticky-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" - integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== +"@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-regex" "^7.10.4" -"@babel/plugin-transform-template-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz#e6375407b30fcb7fcfdbba3bb98ef3e9d36df7bc" - integrity sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ== +"@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" - integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-escapes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" - integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== +"@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" - integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== +"@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/preset-env@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" - integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== +"@babel/preset-env@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: - "@babel/compat-data" "^7.10.4" - "@babel/helper-compilation-targets" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-proposal-async-generator-functions" "^7.10.4" - "@babel/plugin-proposal-class-properties" "^7.10.4" - "@babel/plugin-proposal-dynamic-import" "^7.10.4" - "@babel/plugin-proposal-json-strings" "^7.10.4" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" - "@babel/plugin-proposal-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread" "^7.10.4" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" - "@babel/plugin-proposal-optional-chaining" "^7.10.4" - "@babel/plugin-proposal-private-methods" "^7.10.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" + "@babel/helper-validator-option" "^7.12.11" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.4" + "@babel/plugin-syntax-class-properties" "^7.12.1" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.10.4" - "@babel/plugin-transform-arrow-functions" "^7.10.4" - "@babel/plugin-transform-async-to-generator" "^7.10.4" - "@babel/plugin-transform-block-scoped-functions" "^7.10.4" - "@babel/plugin-transform-block-scoping" "^7.10.4" - "@babel/plugin-transform-classes" "^7.10.4" - "@babel/plugin-transform-computed-properties" "^7.10.4" - "@babel/plugin-transform-destructuring" "^7.10.4" - "@babel/plugin-transform-dotall-regex" "^7.10.4" - "@babel/plugin-transform-duplicate-keys" "^7.10.4" - "@babel/plugin-transform-exponentiation-operator" "^7.10.4" - "@babel/plugin-transform-for-of" "^7.10.4" - "@babel/plugin-transform-function-name" "^7.10.4" - "@babel/plugin-transform-literals" "^7.10.4" - "@babel/plugin-transform-member-expression-literals" "^7.10.4" - "@babel/plugin-transform-modules-amd" "^7.10.4" - "@babel/plugin-transform-modules-commonjs" "^7.10.4" - "@babel/plugin-transform-modules-systemjs" "^7.10.4" - "@babel/plugin-transform-modules-umd" "^7.10.4" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" - "@babel/plugin-transform-new-target" "^7.10.4" - "@babel/plugin-transform-object-super" "^7.10.4" - "@babel/plugin-transform-parameters" "^7.10.4" - "@babel/plugin-transform-property-literals" "^7.10.4" - "@babel/plugin-transform-regenerator" "^7.10.4" - "@babel/plugin-transform-reserved-words" "^7.10.4" - "@babel/plugin-transform-shorthand-properties" "^7.10.4" - "@babel/plugin-transform-spread" "^7.10.4" - "@babel/plugin-transform-sticky-regex" "^7.10.4" - "@babel/plugin-transform-template-literals" "^7.10.4" - "@babel/plugin-transform-typeof-symbol" "^7.10.4" - "@babel/plugin-transform-unicode-escapes" "^7.10.4" - "@babel/plugin-transform-unicode-regex" "^7.10.4" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.10.4" - browserslist "^4.12.0" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" semver "^5.5.0" "@babel/preset-modules@^0.1.3": @@ -1025,18 +939,16 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" - integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== +"@babel/preset-react@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-display-name" "^7.10.4" - "@babel/plugin-transform-react-jsx" "^7.10.4" - "@babel/plugin-transform-react-jsx-development" "^7.10.4" - "@babel/plugin-transform-react-jsx-self" "^7.10.4" - "@babel/plugin-transform-react-jsx-source" "^7.10.4" - "@babel/plugin-transform-react-pure-annotations" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.10" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" + "@babel/plugin-transform-react-pure-annotations" "^7.12.1" "@babel/runtime-corejs3@^7.10.2": version "7.10.3" @@ -1046,14 +958,6 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime-corejs3@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d" - integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - "@babel/runtime@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c" @@ -1061,68 +965,44 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.3.tgz#670d002655a7c366540c67f6fd3342cd09500364" - integrity sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw== +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.1", "@babel/template@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.3.tgz#4d13bc8e30bf95b0ce9d175d30306f42a2c9a7b8" - integrity sha512-5BjI4gdtD+9fHZUsaxPHPNpwa+xRkDO7c7JbhYn2afvrkDu5SfAAbi9AIMXw2xEhO/BR35TqiW97IqNvCo/GqA== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" - -"@babel/template@^7.10.4", "@babel/template@^7.3.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" - integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== +"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.3.3": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.4" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/traverse@^7.10.1", "@babel/traverse@^7.10.3", "@babel/traverse@^7.7.0": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" - integrity sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-function-name" "^7.10.3" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.3", "@babel/types@^7.10.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" - integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== +"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -1130,10 +1010,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@clusterws/cws@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-2.0.0.tgz#73e6ee97b2dcb561d294caa47d48a195234e18a9" - integrity sha512-ZKG2vR0XJyyaXEvcV8cxzuspYnEl4owyqkdcMcHd/Pza9nAKQ5iH+yrEg1JsScg/zBIqTZ9D/3rWJavVwTy0mw== +"@clusterws/cws@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-3.0.0.tgz#518fc8e7d9066e220f6f6aef3158cc14d5a1e98e" + integrity sha512-6RO7IUbSlTO3l8XPN/9g21YGPF4HjfkidDzchkP0h6iwq5jYtji+KUCgyxcSYiuN7aWu8nGJDjBer7XJilPnOg== "@cnakazawa/watch@^1.0.3": version "1.0.4" @@ -1225,6 +1105,22 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== +"@eslint/eslintrc@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" + integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@formatjs/intl-unified-numberformat@^3.3.3": version "3.3.6" resolved "https://registry.yarnpkg.com/@formatjs/intl-unified-numberformat/-/intl-unified-numberformat-3.3.6.tgz#ab69818f7568894023cb31fdb5b5c7eed62c6537" @@ -1242,6 +1138,11 @@ resolved "https://registry.yarnpkg.com/@gamestdio/websocket/-/websocket-0.3.2.tgz#321ba0976ee30fd14e51dbf8faa85ce7b325f76a" integrity sha512-J3n5SKim+ZoLbe44hRGI/VYAwSMCeIJuBy+FfP6EZaujEpNchPRFcIsVQLWAwpU1bP2Ji63rC+rEUOd1vjUB6Q== +"@github/webauthn-json@^0.5.7": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@github/webauthn-json/-/webauthn-json-0.5.7.tgz#143bc67f6e0f75f8d188e565741507bb08c31214" + integrity sha512-SUYsttDxFSvWvvJssJpwzjmRCqYfdfqC9VCmAHQYfdKCVelyJteCHo9/lK1CB72mx/jrl6cFNY08aua4J2jIyg== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1258,89 +1159,93 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.1.0.tgz#f67c89e4f4d04dbcf7b052aed5ab9c74f915b954" - integrity sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A== +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" + "@types/node" "*" chalk "^4.0.0" - jest-message-util "^26.1.0" - jest-util "^26.1.0" + jest-message-util "^26.6.2" + jest-util "^26.6.2" slash "^3.0.0" -"@jest/core@^26.0.1", "@jest/core@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.1.0.tgz#4580555b522de412a7998b3938c851e4f9da1c18" - integrity sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw== +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== dependencies: - "@jest/console" "^26.1.0" - "@jest/reporters" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.1.0" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-resolve-dependencies "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" - jest-watcher "^26.1.0" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.1.0.tgz#378853bcdd1c2443b4555ab908cfbabb851e96da" - integrity sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA== +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== dependencies: - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" -"@jest/fake-timers@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.1.0.tgz#9a76b7a94c351cdbc0ad53e5a748789f819a65fe" - integrity sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA== +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" "@sinonjs/fake-timers" "^6.0.1" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" + "@types/node" "*" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" -"@jest/globals@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.1.0.tgz#6cc5d7cbb79b76b120f2403d7d755693cf063ab1" - integrity sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw== +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== dependencies: - "@jest/environment" "^26.1.0" - "@jest/types" "^26.1.0" - expect "^26.1.0" + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" -"@jest/reporters@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.1.0.tgz#08952e90c90282e14ff49e927bdf1873617dae78" - integrity sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg== +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -1351,63 +1256,63 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.1.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" - v8-to-istanbul "^4.1.3" + v8-to-istanbul "^7.0.0" optionalDependencies: - node-notifier "^7.0.0" + node-notifier "^8.0.0" -"@jest/source-map@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.1.0.tgz#a6a020d00e7d9478f4b690167c5e8b77e63adb26" - integrity sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA== +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.1.0.tgz#a93fa15b21ad3c7ceb21c2b4c35be2e407d8e971" - integrity sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw== +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== dependencies: - "@jest/console" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz#41a6fc8b850c3f33f48288ea9ea517c047e7f14e" - integrity sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q== +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== dependencies: - "@jest/test-result" "^26.1.0" + "@jest/test-result" "^26.6.2" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" - jest-runner "^26.1.0" - jest-runtime "^26.1.0" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" -"@jest/transform@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.1.0.tgz#697f48898c2a2787c9b4cb71d09d7e617464e509" - integrity sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw== +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.1.0" + jest-haste-map "^26.6.2" jest-regex-util "^26.0.0" - jest-util "^26.1.0" + jest-util "^26.6.2" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" @@ -1424,37 +1329,17 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.1.0.tgz#f8afaaaeeb23b5cad49dd1f7779689941dcb6057" - integrity sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ== +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@nodelib/fs.scandir@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" - integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== - dependencies: - "@nodelib/fs.stat" "2.0.3" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" - integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== - dependencies: - "@nodelib/fs.scandir" "2.1.3" - fastq "^1.6.0" - "@npmcli/move-file@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" @@ -1462,15 +1347,20 @@ dependencies: mkdirp "^1.0.4" -"@rails/ujs@^6.0.3": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.0.3.tgz#e68a03278e30daea6a110aac5dfa33c60c53055d" - integrity sha512-CM9OEvoN9eXkaX7PXEnbsQLULJ97b9rVmwliZbz/iBOERLJ68Rk3ClJe+fQEMKU4CBZfky2lIRnfslOdUs9SLQ== +"@polka/url@^1.0.0-next.9": + version "1.0.0-next.11" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71" + integrity sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA== + +"@rails/ujs@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.0.tgz#9a48df6511cb2b472c9f596c1f37dc0af022e751" + integrity sha512-kQNKyM4ePAc4u9eR1c4OqrbAHH+3SJXt++8izIjeaZeg+P7yBtgoF/dogMD/JPPowNC74ACFpM/4op0Ggp/fPw== "@sinonjs/commons@^1.7.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" - integrity sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q== + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== dependencies: type-detect "4.0.8" @@ -1481,39 +1371,46 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@testing-library/dom@^7.17.1": - version "7.18.1" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.18.1.tgz#c49530410fb184522b3b59c4f9cd6397dc5b462d" - integrity sha512-tGq4KAFjaI7j375sMM1RRVleWA0viJWs/w69B+nyDkqYLNkhdTHdV6mGkspJlkn3PUfyBDi3rERDv4PA/LrpVA== +"@testing-library/dom@^7.28.1": + version "7.28.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.28.1.tgz#dea78be6e1e6db32ddcb29a449e94d9700c79eb9" + integrity sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg== dependencies: - "@babel/runtime" "^7.10.3" + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" aria-query "^4.2.2" - dom-accessibility-api "^0.4.5" - pretty-format "^25.5.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.4" + lz-string "^1.4.4" + pretty-format "^26.6.2" -"@testing-library/jest-dom@^5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.0.tgz#1439f08dc85ce7c6d3bbad0ee5d53b2206f55768" - integrity sha512-mhaCySy7dZlyfcxcYy+0jLllODHEiHkVdmwQ00wD0HrWiSx0fSVHz/0WmdlRkvhfSOuqsRsBUreXOtBvruWGQA== +"@testing-library/jest-dom@^5.11.8": + version "5.11.8" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.8.tgz#433a84d6f9a089485101b9e112ef03e5c30bcbfc" + integrity sha512-ScyKrWQM5xNcr79PkSewnA79CLaoxVskE+f7knTOhDD9ftZSA1Jw8mj+pneqhEu3x37ncNfW84NUr7lqK+mXjA== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" aria-query "^4.2.2" chalk "^3.0.0" - css "^2.2.4" + css "^3.0.0" css.escape "^1.5.1" - jest-diff "^25.1.0" - jest-matcher-utils "^25.1.0" lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^10.4.3": - version "10.4.3" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.4.3.tgz#c6f356688cffc51f6b35385583d664bb11a161f4" - integrity sha512-A/ydYXcwAcfY7vkPrfUkUTf9HQLL3/GtixTefcu3OyGQtAYQ7XBQj1S9FWbLEhfWa0BLwFwTBFS3Ao1O0tbMJg== +"@testing-library/react@^11.2.2": + version "11.2.2" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.2.tgz#099c6c195140ff069211143cb31c0f8337bdb7b7" + integrity sha512-jaxm0hwUjv+hzC+UFEywic7buDC9JQ1q3cDsrWVSDAPmLotfA6E6kUHlYm/zOeGCac6g48DR36tFHxl7Zb+N5A== dependencies: - "@babel/runtime" "^7.10.3" - "@testing-library/dom" "^7.17.1" + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^7.28.1" + +"@types/aria-query@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" + integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.3", "@types/babel__core@^7.1.7": version "7.1.9" @@ -1542,9 +1439,16 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.12.tgz#22f49a028e69465390f87bb103ebd61bd086b8f5" - integrity sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA== + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" + integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== + dependencies: + "@babel/types" "^7.3.0" + +"@types/babel__traverse@^7.0.4": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.15.tgz#db9e4238931eb69ef8aab0ad6523d4d4caa39d03" + integrity sha512-Pzh9O3sTK8V6I1olsXpCfj2k/ygO2q1X0vhhnDrEQyYLHZesWz+zMZMVcwXLCYf0U36EtmyYaFGPfXlTtDHe3A== dependencies: "@babel/types" "^7.3.0" @@ -1594,6 +1498,13 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/jest@*": version "26.0.3" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.3.tgz#79534e0e94857171c0edc596db0ebe7cb7863251" @@ -1602,10 +1513,10 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" -"@types/json-schema@^7.0.4": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" - integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/json5@^0.0.29": version "0.0.29" @@ -1618,9 +1529,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== + version "14.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.1.tgz#56af902ad157e763f9ba63d671c39cda3193c835" + integrity sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1633,9 +1544,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d" - integrity sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" + integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== "@types/q@^1.5.1": version "1.5.2" @@ -1647,10 +1558,10 @@ resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-1.0.0.tgz#295d36f01e2cb8bc3207ca1d9a68e210db6b40cb" integrity sha512-YesPanU1+WCigC/Aj1Mga8UCOjHIfMNHZ3zzDsUY7lI8GlKnh/Kv2QwJOQ+jNQ36Ru7IfzSedlG14hppYaN13A== -"@types/stack-utils@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" - integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/stack-utils@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" + integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== "@types/testing-library__jest-dom@^5.9.1": version "5.9.1" @@ -1827,9 +1738,9 @@ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== abab@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" @@ -1854,16 +1765,21 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-jsx@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.0.tgz#56ae4c0f434a45fff4a125e7ea95fa9c98f67a16" + integrity sha512-oZRad/3SMOI/pxbbmqyurIx7jHw1wZDcR9G44L8pUVFEomX/0dH89SrM1KaDXuv1NpzAXz6Op/Xu/Qd5XXzdEA== + acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" @@ -1879,20 +1795,20 @@ acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== +acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +acorn@^8.0.4: + version "8.0.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354" + integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ== aggregate-error@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" @@ -1907,10 +1823,10 @@ ajv-keywords@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv@^4.7.0: version "4.11.8" @@ -1920,20 +1836,10 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.9.1: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.5.5: - version "6.12.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" - integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1950,6 +1856,11 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -2043,6 +1954,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + aria-query@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" @@ -2076,13 +1992,15 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-includes@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" - integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== +array-includes@^3.1.1, array-includes@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" + integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0" + es-abstract "^1.18.0-next.1" + get-intrinsic "^1.0.1" is-string "^1.0.5" array-union@^1.0.1: @@ -2092,11 +2010,6 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -2115,19 +2028,29 @@ array.prototype.flat@^1.2.3: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +array.prototype.flatmap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" + integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + arrow-key-navigation@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/arrow-key-navigation/-/arrow-key-navigation-1.2.0.tgz#edefc5f8b4fc4e384e7c20ddecf81db7ffc970a9" integrity sha512-ch4WOwtjXHFisaa7ey2duW1Qf2VJxoa+8llbsbWDP6wsCzm0DGAi8upv6GDhf5xGvbxhKW3Co9SDEhXq34xCtg== -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -2159,10 +2082,10 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async-each@^1.0.1: version "1.0.3" @@ -2191,17 +2114,17 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.8.0: - version "9.8.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.0.tgz#68e2d2bef7ba4c3a65436f662d0a56a741e56511" - integrity sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A== +autoprefixer@^9.8.6: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: browserslist "^4.12.0" - caniuse-lite "^1.0.30001061" - chalk "^2.4.2" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.30" + postcss "^7.0.32" postcss-value-parser "^4.1.0" aws-sign2@~0.7.0: @@ -2210,31 +2133,23 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" - integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== -axe-core@^3.5.4: - version "3.5.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227" - integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q== - -axios@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" - integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== - dependencies: - follow-redirects "1.5.10" - is-buffer "^2.0.2" +axe-core@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb" + integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA== -axios@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" - integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== dependencies: - follow-redirects "1.5.10" + follow-redirects "^1.10.0" -axobject-query@^2.1.2: +axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== @@ -2251,29 +2166,28 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.1.0.tgz#b20751185fc7569a0f135730584044d1cb934328" - integrity sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg== +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== dependencies: - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.1.0" + babel-preset-jest "^26.6.2" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" -babel-loader@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" - integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== +babel-loader@^8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== dependencies: - find-cache-dir "^2.1.0" + find-cache-dir "^3.3.1" loader-utils "^1.4.0" - mkdirp "^0.5.3" - pify "^4.0.1" + make-dir "^3.1.0" schema-utils "^2.6.5" babel-plugin-dynamic-import-node@^2.3.3: @@ -2310,10 +2224,10 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz#c6a774da08247a28285620a64dfadbd05dd5233a" - integrity sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw== +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -2372,10 +2286,10 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== -babel-preset-current-node-syntax@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" - integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== +babel-preset-current-node-syntax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.0.tgz#cf5feef29551253471cfa82fc8e0f5063df07a77" + integrity sha512-mGkvkpocWJes1CmMKtgGUwCeeq0pOhALyymozzDWYomHTbDLwueDYG6p4TK1YOeYHCzBzYPsWkgTto10JubI1Q== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -2388,14 +2302,15 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz#612f714e5b457394acfd863793c564cbcdb7d1c1" - integrity sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w== +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== dependencies: - babel-plugin-jest-hoist "^26.1.0" - babel-preset-current-node-syntax "^0.1.2" + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" babel-runtime@^6.26.0: version "6.26.0" @@ -2440,16 +2355,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bfj@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" - integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== - dependencies: - bluebird "^3.5.5" - check-types "^8.0.3" - hoopy "^0.1.4" - tryer "^1.0.1" - big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -2466,9 +2371,9 @@ binary-extensions@^1.0.0: integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== bindings@^1.5.0: version "1.5.0" @@ -2498,9 +2403,9 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== bn.js@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0" - integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA== + version "5.1.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" + integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== body-parser@1.19.0: version "1.19.0" @@ -2623,15 +2528,15 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.0.tgz#545d0b1b07e6b2c99211082bf1b12cce7a0b0e11" - integrity sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA== + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== dependencies: bn.js "^5.1.1" browserify-rsa "^4.0.1" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.2" + elliptic "^6.5.3" inherits "^2.0.4" parse-asn1 "^5.1.5" readable-stream "^3.6.0" @@ -2644,15 +2549,37 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5: - version "4.12.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" - integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== - dependencies: - caniuse-lite "^1.0.30001043" - electron-to-chromium "^1.3.413" - node-releases "^1.1.53" - pkg-up "^2.0.0" +browserslist@^4.0.0, browserslist@^4.12.0: + version "4.14.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" + integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== + dependencies: + caniuse-lite "^1.0.30001135" + electron-to-chromium "^1.3.571" + escalade "^3.1.0" + node-releases "^1.1.61" + +browserslist@^4.14.5: + version "4.14.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" + integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== + dependencies: + caniuse-lite "^1.0.30001157" + colorette "^1.2.1" + electron-to-chromium "^1.3.591" + escalade "^3.1.1" + node-releases "^1.1.66" + +browserslist@^4.15.0: + version "4.16.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.0.tgz#410277627500be3cb28a1bfe037586fbedf9488b" + integrity sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ== + dependencies: + caniuse-lite "^1.0.30001165" + colorette "^1.2.1" + electron-to-chromium "^1.3.621" + escalade "^3.1.1" + node-releases "^1.1.67" bser@2.1.1: version "2.1.1" @@ -2726,17 +2653,17 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^15.0.3, cacache@^15.0.4: - version "15.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1" - integrity sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw== +cacache@^15.0.5: + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== dependencies: "@npmcli/move-file" "^1.0.1" chownr "^2.0.0" fs-minipass "^2.0.0" glob "^7.1.4" infer-owner "^1.0.4" - lru-cache "^5.1.1" + lru-cache "^6.0.0" minipass "^3.1.1" minipass-collect "^1.0.2" minipass-flush "^1.0.5" @@ -2764,6 +2691,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -2805,10 +2740,10 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" - integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-api@^3.0.0: version "3.0.0" @@ -2820,10 +2755,20 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001061: - version "1.0.30001094" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001094.tgz#0b11d02e1cdc201348dbd8e3e57bd9b6ce82b175" - integrity sha512-ufHZNtMaDEuRBpTbqD93tIQnngmJ+oBknjvr0IbFympSdtFpAUFmNv4mVKbb53qltxFx0nK3iy32S9AqkLzUNA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135: + version "1.0.30001143" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001143.tgz#560f2cfb9f313d1d7e52eb8dac0e4e36c8821c0d" + integrity sha512-p/PO5YbwmCpBJPxjOiKBvAlUPgF8dExhfEpnsH+ys4N/791WHrYrGg0cyHiAURl5hSbx5vIcjKmQAP6sHDYH3w== + +caniuse-lite@^1.0.30001157: + version "1.0.30001159" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz#bebde28f893fa9594dadcaa7d6b8e2aa0299df20" + integrity sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA== + +caniuse-lite@^1.0.30001165: + version "1.0.30001171" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001171.tgz#3291e11e02699ad0a29e69b8d407666fc843eba7" + integrity sha512-5Alrh8TTYPG9IH4UkRqEBZoEToWRLvPbSQokvzSz0lii8/FOWKG4keO1HoYfPWs8IF/NH/dyNPg1cmJGvV3Zlg== capture-exit@^2.0.0: version "2.0.0" @@ -2848,7 +2793,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0, chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2865,7 +2810,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -2878,25 +2823,10 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -check-types@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" - integrity sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg== - -check-types@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== - -"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2962,6 +2892,11 @@ circular-json@^0.3.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2989,13 +2924,6 @@ cli-cursor@^1.0.1: dependencies: restore-cursor "^1.0.1" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-width@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" @@ -3019,6 +2947,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.3.tgz#ef180f26c8d9bff3927ee52428bfec2090427981" + integrity sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -3060,6 +2997,11 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" +color-blend@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/color-blend/-/color-blend-3.0.1.tgz#3882ed1190ca18760ffe11570d8537960171172b" + integrity sha512-KueDvNiKHAvVeApic0SxHZLyy4x3NELfTLzMHRpRRLi+9e2kWhpeWvtuH3Sjb92mOJYEUhRjb8z7lr4OqDv17Q== + color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -3100,6 +3042,11 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3107,11 +3054,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.18.0, commander@^2.20.0, commander@^2.8.1: +commander@^2.20.0, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" + integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3129,15 +3081,15 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.43.0 < 2" -compression-webpack-plugin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-4.0.0.tgz#7599f592050002a49cd3ad3ee18ae7371e266bca" - integrity sha512-DRoFQNTkQ8gadlk117Y2wxANU+MDY56b1FIZj/yJXucBOTViTHXjthM7G9ocnitksk4kLzt1N2RLF0gDjxI+hg== +compression-webpack-plugin@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-6.1.1.tgz#ae8e4b2ffdb7396bb776e66918d751a20d8ccf0e" + integrity sha512-BEHft9M6lwOqVIQFMS/YJGmeCYXVOakC5KzQk05TFpMBlODByh1qNsZCWjUBxCQhUP9x0WfGidxTbGkjbWO/TQ== dependencies: - cacache "^15.0.3" + cacache "^15.0.5" find-cache-dir "^3.3.1" - schema-utils "^2.6.6" - serialize-javascript "^3.0.0" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" webpack-sources "^1.4.3" compression@^1.7.4: @@ -3239,29 +3191,12 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-webpack-plugin@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.2.tgz#10efc6ad219a61acbf2f5fb50af83da38431bc34" - integrity sha512-9Gm8X0c6eXlKnmltMPFCBeGOKjtcRIyTt4VaO3k1TkNgVTe5Ov2lYsYVuyLp0kp8DItO3apewflM+1GYgh6V2Q== - dependencies: - cacache "^15.0.4" - fast-glob "^3.2.2" - find-cache-dir "^3.3.1" - glob-parent "^5.1.1" - globby "^11.0.1" - loader-utils "^2.0.0" - normalize-path "^3.0.0" - p-limit "^2.3.0" - schema-utils "^2.7.0" - serialize-javascript "^3.1.0" - webpack-sources "^1.4.3" - -core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== +core-js-compat@^3.8.0: + version "3.8.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.1.tgz#8d1ddd341d660ba6194cbe0ce60f4c794c87a36e" + integrity sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ== dependencies: - browserslist "^4.8.5" + browserslist "^4.15.0" semver "7.0.0" core-js-pure@^3.0.0: @@ -3270,9 +3205,9 @@ core-js-pure@^3.0.0: integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== core-js@^2.4.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042" - integrity sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg== + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -3301,12 +3236,12 @@ cosmiconfig@^6.0.0: yaml "^1.7.2" create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" - elliptic "^6.0.0" + elliptic "^6.5.3" create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" @@ -3331,10 +3266,10 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-env@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.2.tgz#bd5ed31339a93a3418ac4f3ca9ca3403082ae5f9" - integrity sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw== +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== dependencies: cross-spawn "^7.0.1" @@ -3349,7 +3284,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3420,24 +3355,23 @@ css-list-helpers@^1.0.1: dependencies: tcomb "^2.5.0" -css-loader@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" - integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== +css-loader@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.1.tgz#9e4de0d6636a6266a585bd0900b422c85539d25f" + integrity sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw== dependencies: - camelcase "^5.3.1" + camelcase "^6.2.0" cssesc "^3.0.0" - icss-utils "^4.1.1" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.32" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.2.0" - postcss-modules-values "^3.0.0" + icss-utils "^5.0.0" + loader-utils "^2.0.0" + postcss "^8.1.4" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" postcss-value-parser "^4.1.0" - schema-utils "^2.7.0" - semver "^6.3.0" + schema-utils "^3.0.0" + semver "^7.3.2" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -3476,24 +3410,23 @@ css-tree@1.0.0-alpha.39: source-map "^0.6.1" css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" + integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== css.escape@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= -css@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== +css@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" + integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== dependencies: - inherits "^2.0.3" + inherits "^2.0.4" source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" + source-map-resolve "^0.6.0" cssesc@^3.0.0: version "3.0.0" @@ -3593,9 +3526,9 @@ cssstyle@^2.2.0: cssom "~0.3.6" csstype@^2.5.7, csstype@^2.6.7: - version "2.6.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" - integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== + version "2.6.13" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f" + integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A== cyclist@^1.0.1: version "1.0.1" @@ -3638,17 +3571,10 @@ debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== +debug@^3.1.1, debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -3664,17 +3590,10 @@ decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decamelize@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-3.2.0.tgz#84b8e8f4f8c579f938e35e2cc7024907e0090851" - integrity sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw== - dependencies: - xregexp "^4.2.4" - decimal.js@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" - integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== decode-uri-component@^0.2.0: version "0.2.0" @@ -3698,7 +3617,7 @@ deep-extend@^0.5.1: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w== -deep-is@~0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -3716,7 +3635,7 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -define-properties@^1.1.2, define-properties@^1.1.3: +define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -3806,20 +3725,20 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== -detect-passive-events@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-1.0.4.tgz#6ed477e6e5bceb79079735dcd357789d37f9a91a" - integrity sha1-btR35uW863kHlzXc01d4nTf5qRo= +detect-passive-events@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-2.0.2.tgz#229d02a20c47371194a2def84144c07d83e324c2" + integrity sha512-Ru7Eiz+pCy++QpqaNOgaIjlM0PzxEsh3Etg3wtntNhW2r3H1/8KkcR8bX9ApPIZChiNO2Pz//60uUg29DPNh3Q== diff-sequences@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== -diff-sequences@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" - integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== diffie-hellman@^5.0.0: version "5.0.3" @@ -3830,13 +3749,6 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -3879,10 +3791,10 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-accessibility-api@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.4.5.tgz#d9c1cefa89f509d8cf132ab5d250004d755e76e3" - integrity sha512-HcPDilI95nKztbVikaN2vzwvmv0sE8Y2ZJFODy/m15n7mGXLeOKGiys9qWVbFbh+aq/KYj2lqMLybBOkYAEXqg== +dom-accessibility-api@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166" + integrity sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ== dom-helpers@^3.2.1, dom-helpers@^3.4.0: version "3.4.0" @@ -3938,9 +3850,9 @@ domutils@^1.7.0: domelementtype "1" dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" @@ -3949,10 +3861,10 @@ dotenv@^8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== -duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -3977,17 +3889,27 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.3.4, ejs@^2.6.1: +ejs@^2.3.4: version "2.7.4" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.413: - version "1.3.488" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.488.tgz#9226229f5fbc825959210e81e0bb3e63035d1c06" - integrity sha512-NReBdOugu1yl8ly+0VDtiQ6Yw/1sLjnvflWq0gvY1nfUXU2PbA+1XAVuEb7ModnwL/MfUPjby7e4pAFnSHiy6Q== +electron-to-chromium@^1.3.571: + version "1.3.574" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.574.tgz#bdd87f62fe70165e5c862a0acf0cee9889e23aa3" + integrity sha512-kF8Bfe1h8X1pPwlw6oRoIXj0DevowviP6fl0wcljm+nZjy/7+Fos4THo1N/7dVGEJlyEqK9C8qNnbheH+Eazfw== + +electron-to-chromium@^1.3.591: + version "1.3.603" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.603.tgz#1b71bec27fb940eccd79245f6824c63d5f7e8abf" + integrity sha512-J8OHxOeJkoSLgBXfV9BHgKccgfLMHh+CoeRo6wJsi6m0k3otaxS/5vrHpMNSEYY4MISwewqanPOuhAtuE8riQQ== + +electron-to-chromium@^1.3.621: + version "1.3.633" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe" + integrity sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA== -elliptic@^6.0.0, elliptic@^6.5.2: +elliptic@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== @@ -4000,6 +3922,11 @@ elliptic@^6.0.0, elliptic@^6.5.2: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emittery@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" + integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ== + emoji-mart@Gargron/emoji-mart#build: version "2.6.3" resolved "https://codeload.github.com/Gargron/emoji-mart/tar.gz/934f314fd8322276765066e8a2a6be5bac61b1cf" @@ -4041,19 +3968,26 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.1.0, enhanced-resolve@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz#5d43bda4a0fd447cb0ebbe71bef8deff8805ad0d" - integrity sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ== +enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -4077,19 +4011,37 @@ error-stack-parser@^2.0.6: stackframe "^1.1.1" es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" @@ -4169,6 +4121,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +escalade@^3.1.0, escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -4206,7 +4163,7 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-import-resolver-node@^0.3.3: +eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== @@ -4222,17 +4179,17 @@ eslint-module-utils@^2.6.0: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-import@~2.21.2: - version "2.21.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.21.2.tgz#8fef77475cc5510801bedc95f84b932f7f334a7c" - integrity sha512-FEmxeGI6yaz+SnEB6YgNHlQK1Bs2DKLM+YF+vuTk5H8J9CLbJLtlPvRFgZZ2+sXiKAlN5dpdlrWOjK8ZoZJpQA== +eslint-plugin-import@~2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== dependencies: array-includes "^3.1.1" array.prototype.flat "^1.2.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.3" + eslint-import-resolver-node "^0.3.4" eslint-module-utils "^2.6.0" has "^1.0.3" minimatch "^3.0.4" @@ -4241,21 +4198,21 @@ eslint-plugin-import@~2.21.2: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-jsx-a11y@~6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660" - integrity sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g== +eslint-plugin-jsx-a11y@~6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== dependencies: - "@babel/runtime" "^7.10.2" + "@babel/runtime" "^7.11.2" aria-query "^4.2.2" array-includes "^3.1.1" ast-types-flow "^0.0.7" - axe-core "^3.5.4" - axobject-query "^2.1.2" + axe-core "^4.0.2" + axobject-query "^2.2.0" damerau-levenshtein "^1.0.6" emoji-regex "^9.0.0" has "^1.0.3" - jsx-ast-utils "^2.4.1" + jsx-ast-utils "^3.1.0" language-tags "^1.0.5" eslint-plugin-promise@~4.2.1: @@ -4263,22 +4220,22 @@ eslint-plugin-promise@~4.2.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== -eslint-plugin-react@~7.20.0: - version "7.20.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz#f98712f0a5e57dfd3e5542ef0604b8739cd47be3" - integrity sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA== +eslint-plugin-react@~7.22.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" + integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== dependencies: array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.1" + jsx-ast-utils "^2.4.1 || ^3.0.0" + object.entries "^1.1.2" object.fromentries "^2.0.2" object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.15.1" + resolve "^1.18.1" string.prototype.matchall "^4.0.2" - xregexp "^4.3.0" eslint-scope@^4.0.3: version "4.0.3" @@ -4288,25 +4245,30 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" - integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== eslint@^2.7.0: version "2.13.1" @@ -4347,46 +4309,46 @@ eslint@^2.7.0: text-table "~0.2.0" user-home "^2.0.0" -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint@^7.17.0: + version "7.17.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0" + integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.2" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.2.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash "^4.17.19" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" text-table "^0.2.0" v8-compile-cache "^2.0.3" @@ -4398,43 +4360,43 @@ espree@^3.1.6: acorn "^5.5.0" acorn-jsx "^3.0.0" -espree@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: +esquery@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== esutils@^2.0.2: version "2.0.3" @@ -4455,14 +4417,14 @@ event-emitter@~0.3.5: es5-ext "~0.10.14" eventemitter3@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" - integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" + integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== eventsource@^1.0.7: version "1.0.7" @@ -4498,9 +4460,9 @@ execa@^1.0.0: strip-eof "^1.0.0" execa@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" - integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -4547,19 +4509,19 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -expect@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.1.0.tgz#8c62e31d0f8d5a8ebb186ee81473d15dd2fbf7c8" - integrity sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw== +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" ansi-styles "^4.0.0" - jest-get-type "^26.0.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" jest-regex-util "^26.0.0" -express@^4.16.3, express@^4.17.1: +express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== @@ -4622,15 +4584,6 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -4660,43 +4613,17 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" - integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: +faye-websocket@^0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== @@ -4723,13 +4650,6 @@ figures@^1.3.5: escape-string-regexp "^1.0.5" object-assign "^4.1.0" -figures@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" - integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^1.1.1: version "1.3.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" @@ -4738,36 +4658,31 @@ file-entry-cache@^1.1.1: flat-cache "^1.2.1" object-assign "^4.0.1" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" -file-loader@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" - integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== dependencies: loader-utils "^2.0.0" - schema-utils "^2.6.5" + schema-utils "^3.0.0" -file-type@^10.5.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" - integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== +file-type@^12.4.1: + version "12.4.2" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" + integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filesize@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -4863,19 +4778,18 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + flatted "^3.1.0" + rimraf "^3.0.2" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" + integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== flush-write-stream@^1.0.0: version "1.1.1" @@ -4885,19 +4799,10 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - -follow-redirects@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb" - integrity sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA== - dependencies: - debug "^3.0.0" +follow-redirects@^1.0.0, follow-redirects@^1.10.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== font-awesome@^4.7.0: version "4.7.0" @@ -5056,11 +4961,20 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -5074,9 +4988,9 @@ get-stream@^4.0.0: pump "^3.0.0" get-stream@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -5100,7 +5014,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -5172,18 +5086,6 @@ globals@^9.2.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== -globby@^11.0.1: - version "11.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" - integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -5196,12 +5098,12 @@ globby@^6.1.0: pinkie-promise "^2.0.0" globule@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.1.tgz#90a25338f22b7fbeb527cee63c629aea754d33b9" - integrity sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g== + version "1.3.2" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" + integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== dependencies: glob "~7.1.1" - lodash "~4.17.12" + lodash "~4.17.10" minimatch "~3.0.2" gonzales-pe-sl@^4.2.3: @@ -5221,13 +5123,12 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gzip-size@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== dependencies: - duplexer "^0.1.1" - pify "^4.0.1" + duplexer "^0.1.2" handle-thing@^2.0.0: version "2.0.1" @@ -5240,11 +5141,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" has-ansi@^2.0.0: @@ -5269,7 +5170,7 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5376,10 +5277,10 @@ hoist-non-react-statics@^2.5.0: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" - integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" @@ -5390,11 +5291,6 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -5479,16 +5375,21 @@ http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -http-link-header@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-1.0.2.tgz#bea50f02e1c7996021f1013b428c63f77e0f4e11" - integrity sha512-z6YOZ8ZEnejkcCWlGZzYXNa6i+ZaTfiTg3WhlV/YvnNya3W/RbX1bMVUMTuCrg/DrtTCQxaFCkXCz4FtLpcebg== +http-link-header@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-1.0.3.tgz#abbc2cdc5e06dd7e196a4983adac08a2d085ec90" + integrity sha512-nARK1wSKoBBrtcoESlHBx36c1Ln/gnbNQi1eB6MeTUefJIT3NvUOsV15bClga0k38f0q/kN5xxrGSDS3EFnm9w== "http-parser-js@>=0.4.0 <0.4.11": version "0.4.10" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= +http-parser-js@>=0.5.1: + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" @@ -5527,21 +5428,19 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -icss-utils@^4.0.0, icss-utils@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== - dependencies: - postcss "^7.0.14" +icss-utils@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.0.0.tgz#03ed56c3accd32f9caaf1752ebf64ef12347bb84" + integrity sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg== -idb-keyval@^3.1.0: +idb-keyval@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-3.2.0.tgz#cbbf354deb5684b6cdc84376294fc05932845bd6" integrity sha512-slx8Q6oywCCSfKgPgL0sEsXtPVnSbTLWpyiDcu6msHOyKOLari1TD1qocXVCft80umnkk3/Qqh3lwoFt8T/BPQ== @@ -5566,11 +5465,6 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: - version "5.1.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.6.tgz#643194ad4bf2712f37852e386b6998eff0db2106" - integrity sha512-cgXgkypZBcCnOgSihyeqbo6gjIaIyDqPQB7Ra4vhE9m6kigdGoQDMHjviFhRZo3IMlRy6yElosoviMs5YxZXUA== - immutable@^3.8.2: version "3.8.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" @@ -5591,7 +5485,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0, import-fresh@^3.1.0: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -5622,13 +5516,15 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imports-loader@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.8.0.tgz#030ea51b8ca05977c40a3abfd9b4088fe0be9a69" - integrity sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ== +imports-loader@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-1.2.0.tgz#b06823d0bb42e6f5ff89bc893829000eda46693f" + integrity sha512-zPvangKEgrrPeqeUqH0Uhc59YqK07JqZBi9a9cQ3v/EKUIqrbJHY4CvUrDus2lgQa5AmPyXuGrWP8JJTqzE5RQ== dependencies: - loader-utils "^1.0.2" + loader-utils "^2.0.0" + schema-utils "^3.0.0" source-map "^0.6.1" + strip-comments "^2.0.1" imurmurhash@^0.1.4: version "0.1.4" @@ -5674,9 +5570,9 @@ inherits@2.0.3: integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== inquirer@^0.12.0: version "0.12.0" @@ -5697,25 +5593,6 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" - integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== - dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" @@ -5738,10 +5615,10 @@ interpret@^1.4.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -intersection-observer@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.10.0.tgz#4d11d63c1ff67e21e62987be24d55218da1a1a69" - integrity sha512-fn4bQ0Xq8FTej09YC/jqKZwtijpvARlRp6wxL5WTA6yPe2YWSJ5RJh7Nm79rK2qB0wr6iDQzH60XGq5V/7u8YQ== +intersection-observer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.0.tgz#6c84628f67ce8698e5f9ccf857d97718745837aa" + integrity sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ== intl-format-cache@^2.0.5: version "2.2.9" @@ -5859,15 +5736,10 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - -is-callable@^1.1.4, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== is-ci@^2.0.0: version "2.0.0" @@ -5888,6 +5760,13 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -5931,9 +5810,14 @@ is-directory@^0.3.1: integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" - integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== + +is-electron@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0" + integrity sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -5994,9 +5878,9 @@ is-my-ip-valid@^1.0.0: integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== is-my-json-valid@^2.10.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" - integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== + version "2.20.5" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz#5eca6a8232a687f68869b7361be1612e7512e5df" + integrity sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A== dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" @@ -6004,13 +5888,19 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" -is-nan@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03" - integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ== +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -6047,11 +5937,6 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -6064,23 +5949,25 @@ is-potential-custom-element-name@^1.0.0: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= -is-promise@^2.1.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - is-property@^1.0.0, is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= -is-regex@^1.0.4, is-regex@^1.1.0: +is-regex@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== dependencies: has-symbols "^1.0.1" +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -6120,11 +6007,6 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-url@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.2.tgz#498905a593bf47cc2d9e7f738372bbf7696c7f26" - integrity sha1-SYkFpZO/R8wtnn9zg3K792lsfyY= - is-url@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" @@ -6140,7 +6022,7 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= -is-wsl@^2.1.1: +is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -6220,59 +6102,59 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.1.0.tgz#de66b0f30453bca2aff98e9400f75905da495305" - integrity sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw== +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.0.1: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.1.0.tgz#eb9ec8a18cf3b6aa556d9deaa9e24be12b43ad87" - integrity sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw== +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== dependencies: - "@jest/core" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" prompts "^2.0.1" - yargs "^15.3.1" + yargs "^15.4.1" -jest-config@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.1.0.tgz#9074f7539acc185e0113ad6d22ed589c16a37a73" - integrity sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw== +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.1.0" - "@jest/types" "^26.1.0" - babel-jest "^26.1.0" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.1.0" - jest-environment-node "^26.1.0" - jest-get-type "^26.0.0" - jest-jasmine2 "^26.1.0" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.6.3" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" micromatch "^4.0.2" - pretty-format "^26.1.0" + pretty-format "^26.6.2" -jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: +jest-diff@^25.2.1: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== @@ -6282,15 +6164,15 @@ jest-diff@^25.1.0, jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.1.0.tgz#00a549bdc936c9691eb4dc25d1fbd78bf456abb2" - integrity sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg== +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== dependencies: chalk "^4.0.0" - diff-sequences "^26.0.0" - jest-get-type "^26.0.0" - pretty-format "^26.1.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" jest-docblock@^26.0.0: version "26.0.0" @@ -6299,143 +6181,139 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.1.0.tgz#e35449875009a22d74d1bda183b306db20f286f7" - integrity sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA== +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" chalk "^4.0.0" - jest-get-type "^26.0.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" - -jest-environment-jsdom@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz#9dc7313ffe1b59761dad1fedb76e2503e5d37c5b" - integrity sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw== - dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" - jsdom "^16.2.2" - -jest-environment-node@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.1.0.tgz#8bb387b3eefb132eab7826f9a808e4e05618960b" - integrity sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg== - dependencies: - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/types" "^26.1.0" - jest-mock "^26.1.0" - jest-util "^26.1.0" + jest-get-type "^26.3.0" + jest-util "^26.6.2" + pretty-format "^26.6.2" + +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + jsdom "^16.4.0" + +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" jest-get-type@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== -jest-get-type@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" - integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== -jest-haste-map@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.1.0.tgz#ef31209be73f09b0d9445e7d213e1b53d0d1476a" - integrity sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA== +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" "@types/graceful-fs" "^4.1.2" + "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" - jest-serializer "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" - which "^2.0.2" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz#4dfe349b2b2d3c6b3a27c024fd4cb57ac0ed4b6f" - integrity sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ== +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.1.0" - "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^26.1.0" + expect "^26.6.2" is-generator-fn "^2.0.0" - jest-each "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-runtime "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - pretty-format "^26.1.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" throat "^5.0.0" -jest-leak-detector@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz#039c3a07ebcd8adfa984b6ac015752c35792e0a6" - integrity sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw== - dependencies: - jest-get-type "^26.0.0" - pretty-format "^26.1.0" - -jest-matcher-utils@^25.1.0: - version "25.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz#fbc98a12d730e5d2453d7f1ed4a4d948e34b7867" - integrity sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw== +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== dependencies: - chalk "^3.0.0" - jest-diff "^25.5.0" - jest-get-type "^25.2.6" - pretty-format "^25.5.0" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-matcher-utils@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz#cf75a41bd413dda784f022de5a65a2a5c73a5c92" - integrity sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA== +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== dependencies: chalk "^4.0.0" - jest-diff "^26.1.0" - jest-get-type "^26.0.0" - pretty-format "^26.1.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" -jest-message-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.1.0.tgz#52573fbb8f5cea443c4d1747804d7a238a3e233c" - integrity sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g== +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.1.0" - "@types/stack-utils" "^1.0.1" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.2" + pretty-format "^26.6.2" slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.1.0.tgz#80d8286da1f05a345fbad1bfd6fa49a899465d3d" - integrity sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw== +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" + "@types/node" "*" -jest-pnp-resolver@^1.2.1: +jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== @@ -6445,170 +6323,186 @@ jest-regex-util@^26.0.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz#1ce36472f864a5dadf7dc82fa158e1c77955691b" - integrity sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g== +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" jest-regex-util "^26.0.0" - jest-snapshot "^26.1.0" + jest-snapshot "^26.6.2" -jest-resolve@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.1.0.tgz#a530eaa302b1f6fa0479079d1561dd69abc00e68" - integrity sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg== +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" chalk "^4.0.0" graceful-fs "^4.2.4" - jest-pnp-resolver "^1.2.1" - jest-util "^26.1.0" + jest-pnp-resolver "^1.2.2" + jest-util "^26.6.2" read-pkg-up "^7.0.1" - resolve "^1.17.0" + resolve "^1.18.1" slash "^3.0.0" -jest-runner@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.1.0.tgz#457f7fc522afe46ca6db1dccf19f87f500b3288d" - integrity sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw== +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" chalk "^4.0.0" + emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.1.0" + jest-config "^26.6.3" jest-docblock "^26.0.0" - jest-haste-map "^26.1.0" - jest-jasmine2 "^26.1.0" - jest-leak-detector "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" - jest-runtime "^26.1.0" - jest-util "^26.1.0" - jest-worker "^26.1.0" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.1.0.tgz#45a37af42115f123ed5c51f126c05502da2469cb" - integrity sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA== - dependencies: - "@jest/console" "^26.1.0" - "@jest/environment" "^26.1.0" - "@jest/fake-timers" "^26.1.0" - "@jest/globals" "^26.1.0" - "@jest/source-map" "^26.1.0" - "@jest/test-result" "^26.1.0" - "@jest/transform" "^26.1.0" - "@jest/types" "^26.1.0" +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/yargs" "^15.0.0" chalk "^4.0.0" + cjs-module-lexer "^0.6.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.1.0" - jest-haste-map "^26.1.0" - jest-message-util "^26.1.0" - jest-mock "^26.1.0" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" jest-regex-util "^26.0.0" - jest-resolve "^26.1.0" - jest-snapshot "^26.1.0" - jest-util "^26.1.0" - jest-validate "^26.1.0" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" slash "^3.0.0" strip-bom "^4.0.0" - yargs "^15.3.1" + yargs "^15.4.1" -jest-serializer@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.1.0.tgz#72a394531fc9b08e173dc7d297440ac610d95022" - integrity sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w== +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== dependencies: + "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.1.0.tgz#c36ed1e0334bd7bd2fe5ad07e93a364ead7e1349" - integrity sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw== +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.1.0" + expect "^26.6.2" graceful-fs "^4.2.4" - jest-diff "^26.1.0" - jest-get-type "^26.0.0" - jest-haste-map "^26.1.0" - jest-matcher-utils "^26.1.0" - jest-message-util "^26.1.0" - jest-resolve "^26.1.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" natural-compare "^1.4.0" - pretty-format "^26.1.0" + pretty-format "^26.6.2" semver "^7.3.2" -jest-util@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.1.0.tgz#80e85d4ba820decacf41a691c2042d5276e5d8d8" - integrity sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg== +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" + "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" micromatch "^4.0.2" -jest-validate@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.1.0.tgz#942c85ad3d60f78250c488a7f85d8f11a29788e7" - integrity sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw== +jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" camelcase "^6.0.0" chalk "^4.0.0" - jest-get-type "^26.0.0" + jest-get-type "^26.3.0" leven "^3.1.0" - pretty-format "^26.1.0" + pretty-format "^26.6.2" -jest-watcher@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.1.0.tgz#99812a0cd931f0cb3d153180426135ab83e4d8f2" - integrity sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ== +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== dependencies: - "@jest/test-result" "^26.1.0" - "@jest/types" "^26.1.0" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.1.0" + jest-util "^26.6.2" string-length "^4.0.1" -jest-worker@^26.0.0, jest-worker@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" - integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== +jest-worker@^26.5.0: + version "26.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.5.0.tgz#87deee86dbbc5f98d9919e0dadf2c40e3152fa30" + integrity sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.0.1.tgz#5c51a2e58dff7525b65f169721767173bf832694" - integrity sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg== +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== dependencies: - "@jest/core" "^26.0.1" + "@jest/core" "^26.6.3" import-local "^3.0.2" - jest-cli "^26.0.1" + jest-cli "^26.6.3" js-base64@^2.1.9: - version "2.6.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.2.tgz#cf9301bc5cc756892a9a6c8d7138322e5944fb0d" - integrity sha512-1hgLrLIrmCgZG+ID3VoLNLOSwjGnoZa8tyrUdEteMeIzsT6PH7PMLyUvbDwzNE56P3PNxyvuIOx4Uh2E5rzQIw== + version "2.6.4" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" + integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== js-string-escape@1.0.1: version "1.0.1" @@ -6620,31 +6514,30 @@ js-string-escape@1.0.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== +js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== +js-yaml@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== dependencies: - argparse "^1.0.7" - esprima "^4.0.0" + argparse "^2.0.1" jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.2.2: - version "16.2.2" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.2.2.tgz#76f2f7541646beb46a938f5dc476b88705bedf2b" - integrity sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg== +jsdom@^16.4.0: + version "16.4.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" + integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w== dependencies: abab "^2.0.3" acorn "^7.1.1" @@ -6666,7 +6559,7 @@ jsdom@^16.2.2: tough-cookie "^3.0.1" w3c-hr-time "^1.0.2" w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.0.0" + webidl-conversions "^6.1.0" whatwg-encoding "^1.0.5" whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" @@ -6715,7 +6608,7 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@^3.3.2: +json3@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== @@ -6759,9 +6652,9 @@ jsonify@~0.0.0: integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= + version "4.1.0" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.1.0.tgz#501fb89986a2389765ba09e6053299ceb4f2c2cc" + integrity sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg== jsprim@^1.2.2: version "1.4.1" @@ -6773,13 +6666,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.2.3, jsx-ast-utils@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" - integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" + integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== dependencies: array-includes "^3.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" keycode@^2.1.7: version "2.2.0" @@ -6801,6 +6694,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +klona@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" + integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== + knot.js@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/knot.js/-/knot.js-1.1.5.tgz#28e72522f703f50fe98812fde224dd72728fef5d" @@ -6828,13 +6726,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -6843,6 +6734,22 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +line-column@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" + integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= + dependencies: + isarray "^1.0.0" + isobject "^2.0.0" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -6873,7 +6780,7 @@ loader-utils@0.2.x: json5 "^0.5.0" object-assign "^4.0.1" -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -6969,15 +6876,15 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.3.0, lodash@~4.17.12: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.3.0, lodash@~4.17.10: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== loglevel@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" - integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -6993,6 +6900,18 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lz-string@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= + make-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -7001,7 +6920,7 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2: +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -7092,11 +7011,6 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - merge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" @@ -7159,6 +7073,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.3.1: + version "2.4.7" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74" + integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA== + mime@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" @@ -7174,14 +7093,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" - integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== +mini-css-extract-plugin@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.3.tgz#7802e62b34199aa7d1a62e654395859a836486a0" + integrity sha512-7lvliDSMiuZc81kI+5/qxvn47SCM7BehXex3f2c6l/pR3Goj58IQxZh9nuPQ3AkGQgoETyXuIqLDaO5Oa0TyBw== dependencies: - loader-utils "^1.1.0" - normalize-url "1.9.1" - schema-utils "^1.0.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" webpack-sources "^1.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: @@ -7226,9 +7144,9 @@ minipass-flush@^1.0.5: minipass "^3.0.0" minipass-pipeline@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" - integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" @@ -7239,10 +7157,10 @@ minipass@^3.0.0, minipass@^3.1.1: dependencies: yallist "^4.0.0" -minizlib@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" - integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" yallist "^4.0.0" @@ -7271,7 +7189,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: +mkdirp@^0.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -7333,16 +7251,16 @@ mute-stream@0.0.5: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nan@^2.12.1: version "2.14.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nanoid@^3.1.16: + version "3.1.16" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" + integrity sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7370,10 +7288,10 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== next-tick@~1.0.0: version "1.0.0" @@ -7385,10 +7303,15 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-forge@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" - integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== +node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== node-int64@^0.4.0: version "0.4.0" @@ -7429,22 +7352,27 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.1.tgz#a355e33e6bebacef9bf8562689aed0f4230ca6f9" - integrity sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg== +node-notifier@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1" + integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA== dependencies: growly "^1.3.0" - is-wsl "^2.1.1" - semver "^7.2.1" + is-wsl "^2.2.0" + semver "^7.3.2" shellwords "^0.1.1" - uuid "^7.0.3" + uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.53: - version "1.1.58" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935" - integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg== +node-releases@^1.1.61: + version "1.1.61" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" + integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== + +node-releases@^1.1.66, node-releases@^1.1.67: + version "1.1.67" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" + integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -7473,16 +7401,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -7563,20 +7481,20 @@ object-fit-images@^3.2.3: resolved "https://registry.yarnpkg.com/object-fit-images/-/object-fit-images-3.2.4.tgz#6c299d38fdf207746e5d2d46c2877f6f25d15b52" integrity sha512-G+7LzpYfTfqUyrZlfrou/PLLLAPNC52FTy5y1CBywX+1/FkxIloOyQXBmZ3Zxa2AWO+lMF0JTuvqbr7G5e5CWg== -object-inspect@^1.7.0: +object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== object-is@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + version "1.1.3" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" + integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7588,17 +7506,17 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" -object.entries@^1.1.1: +object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== @@ -7632,14 +7550,14 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0, object.values@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" - integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== +object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" + integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.18.0-next.1" has "^1.0.3" obuf@^1.0.0, obuf@^1.1.2: @@ -7683,9 +7601,9 @@ onetime@^1.0.0: integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" @@ -7694,10 +7612,10 @@ opencollective-postinstall@^2.0.2: resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== opn@^5.5.0: version "5.5.0" @@ -7706,7 +7624,7 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optionator@^0.8.1, optionator@^0.8.3: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -7718,6 +7636,18 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -7735,11 +7665,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - p-each-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" @@ -7757,17 +7682,17 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" -p-limit@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.1.tgz#584784ac0722d1aed09f19f90ed2999af6ce2839" - integrity sha512-mw/p92EyOzl2MhauKodw54Rx5ZK4624rNfgNaBguFZkHzyUG9WsDzFF5/yQVEJinbJDdP4jEfMN+uBquiGnaLg== +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== dependencies: p-try "^2.0.0" @@ -7848,13 +7773,12 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" safe-buffer "^5.1.1" @@ -7890,9 +7814,9 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" + integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" @@ -8119,26 +8043,19 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= portfinder@^1.0.26: - version "1.0.26" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70" - integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ== + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" - mkdirp "^0.5.1" + mkdirp "^0.5.5" posix-character-classes@^0.1.0: version "0.1.1" @@ -8146,9 +8063,9 @@ posix-character-classes@^0.1.0: integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + version "7.0.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.4.tgz#5e177ddb417341e6d4a193c5d9fd8ada79094f8b" + integrity sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -8202,9 +8119,9 @@ postcss-discard-overridden@^4.0.1: postcss "^7.0.0" postcss-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== dependencies: cosmiconfig "^5.0.0" import-cwd "^2.0.0" @@ -8281,38 +8198,33 @@ postcss-minify-selectors@^4.0.2: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -postcss-modules-extract-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== - dependencies: - postcss "^7.0.5" +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== -postcss-modules-local-by-default@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" - integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== dependencies: - icss-utils "^4.1.1" - postcss "^7.0.16" + icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.0" + postcss-value-parser "^4.1.0" -postcss-modules-scope@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" - integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" + postcss-selector-parser "^6.0.4" -postcss-modules-values@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" - integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== dependencies: - icss-utils "^4.0.0" - postcss "^7.0.6" + icss-utils "^5.0.0" postcss-normalize-charset@^4.0.1: version "4.0.1" @@ -8442,7 +8354,7 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: +postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== @@ -8451,6 +8363,16 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + util-deprecate "^1.0.2" + postcss-svgo@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" @@ -8475,7 +8397,7 @@ postcss-value-parser@^3.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -8490,7 +8412,7 @@ postcss@^5.0.16: source-map "^0.5.6" supports-color "^3.2.3" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.27, postcss@^7.0.30, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27, postcss@^7.0.32: version "7.0.32" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== @@ -8499,6 +8421,16 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.2 source-map "^0.6.1" supports-color "^6.1.0" +postcss@^8.1.4: + version "8.1.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.6.tgz#b022ba2cfb8701da234d073ed3128c5a384c35ff" + integrity sha512-JuifSl4h8dJ70SiMXKjzCxhalE6p2TnMHuq9G8ftyXj2jg6SXzqCsEuxMj9RkmJoO5D+Z9YrWunNkxqpRT02qg== + dependencies: + colorette "^1.2.1" + line-column "^1.0.2" + nanoid "^3.1.16" + source-map "^0.6.1" + postgres-array@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.3.tgz#c561fc3b266b21451fc6555384f4986d78ec80f5" @@ -8510,9 +8442,9 @@ postgres-bytea@~1.0.0: integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= postgres-date@~1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.5.tgz#710b27de5f27d550f6e80b5d34f7ba189213c2ee" - integrity sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA== + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== postgres-interval@^1.1.0: version "1.2.0" @@ -8521,16 +8453,16 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - pretty-format@^25.2.1, pretty-format@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" @@ -8541,20 +8473,15 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec" - integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg== +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.6.2" ansi-regex "^5.0.0" ansi-styles "^4.0.0" - react-is "^16.12.0" - -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + react-is "^17.0.1" process-nextick-args@~2.0.0: version "2.0.1" @@ -8700,14 +8627,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -8719,9 +8638,9 @@ querystring@0.2.0: integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== quote@^0.4.0: version "0.4.0" @@ -8765,10 +8684,10 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -react-dom@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" - integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== +react-dom@^16.14.0: + version "16.14.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" + integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -8842,11 +8761,16 @@ react-intl@^2.9.0: intl-relativeformat "^2.1.0" invariant "^2.1.1" -react-is@^16.12.0, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" + integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -8877,10 +8801,10 @@ react-notification@^6.8.5: dependencies: prop-types "^15.6.2" -react-overlays@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.9.1.tgz#d4702bfe5b5e9335b676ff5a940253771fdeed12" - integrity sha512-b0asy/zHtRd0i2+2/uNxe3YVprF3bRT1guyr791DORjCzE/HSBMog+ul83CdtKQ1kZ+pLnxWCu5W3BMysFhHdQ== +react-overlays@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.9.3.tgz#5bac8c1e9e7e057a125181dee2d784864dd62902" + integrity sha512-u2T7nOLnK+Hrntho4p0Nxh+BsJl0bl4Xuwj/Y0a56xywLMetgAfyjnDVrudLXsNcKGaspoC+t3C1V80W9QQTdQ== dependencies: classnames "^2.2.5" dom-helpers "^3.2.1" @@ -8897,16 +8821,16 @@ react-redux-loading-bar@^4.0.8: prop-types "^15.6.2" react-lifecycles-compat "^3.0.2" -react-redux@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== +react-redux@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736" + integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA== dependencies: - "@babel/runtime" "^7.5.5" - hoist-non-react-statics "^3.3.0" + "@babel/runtime" "^7.12.1" + hoist-non-react-statics "^3.3.2" loose-envify "^1.4.0" prop-types "^15.7.2" - react-is "^16.9.0" + react-is "^16.13.1" react-router-dom@^4.1.1: version "4.3.1" @@ -8941,10 +8865,10 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" -react-select@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27" - integrity sha512-wBFVblBH1iuCBprtpyGtd1dGMadsG36W5/t2Aj8OE6WbByDg5jIFyT7X5gT+l0qmT5TqWhxX+VsKJvCEl2uL9g== +react-select@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.1.1.tgz#156a5b4a6c22b1e3d62a919cb1fd827adb4060bc" + integrity sha512-HjC6jT2BhUxbIbxMZWqVcDibrEpdUJCfGicN0MMV+BQyKtCaPTgFekKWiOizSCy4jdsLMGjLqcFGJMhVGWB0Dg== dependencies: "@babel/runtime" "^7.4.4" "@emotion/cache" "^10.0.9" @@ -8993,20 +8917,20 @@ react-swipeable-views@^0.13.9: react-swipeable-views-utils "^0.13.9" warning "^4.0.1" -react-test-renderer@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1" - integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ== +react-test-renderer@^16.14.0: + version "16.14.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.14.0.tgz#e98360087348e260c56d4fe2315e970480c228ae" + integrity sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" react-is "^16.8.6" scheduler "^0.19.1" -react-textarea-autosize@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.1.1.tgz#d31dd1d04235af11161765782c70cb27c2c2832e" - integrity sha512-yJv7CbyXv8hb0xHpii9yQpMK0kwZ3A4TChRc5qGxQlHDR064oqStHbcuvexErRvJipTnDGNkcpGvE3hLnY0KAg== +react-textarea-autosize@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.0.tgz#e6e2fd186d9f61bb80ac6e2dcb4c55504f93c2fa" + integrity sha512-3GLWFAan2pbwBeoeNDoqGmSbrShORtgWfaWX0RJDivsUrpShh01saRM5RU/i4Zmf+whpBVEY5cA90Eq8Ub1N3w== dependencies: "@babel/runtime" "^7.10.2" use-composed-ref "^1.0.0" @@ -9039,10 +8963,10 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" - integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== +react@^16.14.0: + version "16.14.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -9140,9 +9064,9 @@ redent@^3.0.0: strip-indent "^3.0.0" redis-commands@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" - integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== + version "1.6.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.6.0.tgz#36d4ca42ae9ed29815cdb30ad9f97982eba1ce23" + integrity sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ== redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" @@ -9206,18 +9130,17 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== +regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" - private "^0.1.8" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -9235,15 +9158,15 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^8.2.0" @@ -9284,19 +9207,19 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: - lodash "^4.17.15" + lodash "^4.17.19" request-promise-native@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: - request-promise-core "1.1.3" + request-promise-core "1.1.4" stealthy-require "^1.1.1" tough-cookie "^2.3.3" @@ -9426,11 +9349,12 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: + is-core-module "^2.1.0" path-parse "^1.0.6" restore-cursor@^1.0.1: @@ -9441,14 +9365,6 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -9459,11 +9375,6 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" @@ -9474,13 +9385,6 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2.6.3, rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -9495,6 +9399,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -9515,18 +9426,6 @@ run-async@^0.1.0: dependencies: once "^1.3.0" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -9539,13 +9438,6 @@ rx-lite@^3.1.2: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= -rxjs@^6.4.0: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -9603,21 +9495,21 @@ sass-lint@^1.13.1: path-is-absolute "^1.0.0" util "^0.10.3" -sass-loader@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" - integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== +sass-loader@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.0.tgz#1727fcc0c32ab3eb197cda61d78adf4e9174a4b3" + integrity sha512-ZCKAlczLBbFd3aGAhowpYEy69Te3Z68cg8bnHHl6WnSCvnKpbM6pQrz957HWMa8LKVuhnD9uMplmMAHwGQtHeg== dependencies: - clone-deep "^4.0.1" - loader-utils "^1.2.3" - neo-async "^2.6.1" - schema-utils "^2.6.1" - semver "^6.3.0" + klona "^2.0.4" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^3.0.0" + semver "^7.3.2" -sass@^1.26.8: - version "1.26.8" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.8.tgz#312652530721f9568d4c4000b0db07ec6eb23325" - integrity sha512-yvtzyrKLGiXQu7H12ekXqsfoGT/aTKeMDyVzCB675k1HYuaj0py63i8Uf4SI9CHXj6apDhpfwbUr3gGOjdpu2Q== +sass@^1.32.0: + version "1.32.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.0.tgz#10101a026c13080b14e2b374d4e15ee24400a4d3" + integrity sha512-fhyqEbMIycQA4blrz/C0pYhv2o4x2y6FYYAH0CshBw3DXh5D5wyERgxw0ptdau1orc/GhNrhF7DFN2etyOCEng== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -9650,14 +9542,23 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.2.0, schema-utils@^2.6.1, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== +schema-utils@^2.2.0, schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== + dependencies: + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" scroll-behavior@^0.9.1: version "0.9.12" @@ -9672,12 +9573,12 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selfsigned@^1.10.7: - version "1.10.7" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" - integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== +selfsigned@^1.10.8: + version "1.10.8" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" + integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== dependencies: - node-forge "0.9.0" + node-forge "^0.10.0" "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" @@ -9694,15 +9595,17 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" send@0.17.1: version "0.17.1" @@ -9728,17 +9631,10 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== -serialize-javascript@^3.0.0, serialize-javascript@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" - integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== - dependencies: - randombytes "^2.1.0" - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== +serialize-javascript@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== dependencies: randombytes "^2.1.0" @@ -9850,12 +9746,12 @@ shellwords@^0.1.1: integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== side-channel@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" - integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" + integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== dependencies: - es-abstract "^1.17.0-next.1" - object-inspect "^1.7.0" + es-abstract "^1.18.0-next.0" + object-inspect "^1.8.0" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" @@ -9869,6 +9765,15 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sirv@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.10.tgz#3e591f5a9ae2520f50d5830f5fae38d97e7be194" + integrity sha512-H5EZCoZaggEUQy8ocKsF7WAToGuZhjJlLvM3XOef46CbdIgbNeQ1p32N1PCuCjkVYwrAVOSMacN6CXXgIzuspg== + dependencies: + "@polka/url" "^1.0.0-next.9" + mime "^2.3.1" + totalist "^1.0.0" + sisteransi@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -9889,14 +9794,14 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -9928,40 +9833,33 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== +sockjs-client@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" + integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q== dependencies: - debug "^3.2.5" + debug "^3.2.6" eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" + faye-websocket "^0.11.3" + inherits "^2.0.4" + json3 "^3.3.3" + url-parse "^1.4.7" -sockjs@0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" - integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== +sockjs@^0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: - faye-websocket "^0.10.0" + faye-websocket "^0.11.3" uuid "^3.4.0" - websocket-driver "0.6.5" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" + websocket-driver "^0.7.4" source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: +source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== @@ -9972,7 +9870,15 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.6, source-map-support@~0.5.12: +source-map-resolve@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + +source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -10000,7 +9906,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3: +source-map@^0.7.3, source-map@~0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -10027,9 +9933,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== spdy-transport@^3.0.0: version "3.0.0" @@ -10193,11 +10099,6 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - string-length@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" @@ -10328,6 +10229,11 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== +strip-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" + integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -10345,10 +10251,10 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strip-json-comments@~1.0.1: version "1.0.4" @@ -10396,9 +10302,9 @@ supports-color@^6.1.0: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" @@ -10451,15 +10357,15 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -table@^5.2.3: - version "5.4.1" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.1.tgz#0691ae2ebe8259858efb63e550b6d5f9300171e8" - integrity sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w== +table@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d" + integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw== dependencies: - ajv "^6.9.1" - lodash "^4.17.11" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^6.12.4" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" @@ -10467,14 +10373,14 @@ tapable@^1.0.0, tapable@^1.1.3: integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== tar@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" - integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== + version "6.0.5" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" + integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" minipass "^3.0.0" - minizlib "^2.1.0" + minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" @@ -10506,22 +10412,22 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-3.0.6.tgz#db0a108bbdd3680d72c9b491fbabad09ba207b99" - integrity sha512-z3HLOOPUHkCNGkeEHqqiMAIy1pjpHwS1o+i6Zn0Ws3EAvHJj46737efNNEvJ0Vx9BdDQM83d56qySDJOSORA0A== +terser-webpack-plugin@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" + integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== dependencies: - cacache "^15.0.4" + cacache "^15.0.5" find-cache-dir "^3.3.1" - jest-worker "^26.0.0" - p-limit "^3.0.1" - schema-utils "^2.6.6" - serialize-javascript "^4.0.0" + jest-worker "^26.5.0" + p-limit "^3.0.2" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" source-map "^0.6.1" - terser "^4.8.0" + terser "^5.3.4" webpack-sources "^1.4.3" -terser@^4.1.2, terser@^4.8.0: +terser@^4.1.2: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== @@ -10530,35 +10436,36 @@ terser@^4.1.2, terser@^4.8.0: source-map "~0.6.1" source-map-support "~0.5.12" -tesseract.js-core@^2.0.0-beta.12: +terser@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.4.tgz#e510e05f86e0bd87f01835c3238839193f77a60c" + integrity sha512-dxuB8KQo8Gt6OVOeLg/rxfcxdNZI/V1G6ze1czFUzPeCFWZRtvZMgSzlZZ5OYBZ4HoG607F6pFPNLekJyV+yVw== + dependencies: + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.19" + +tesseract.js-core@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz#6ef78051272a381969fac3e45a226e85022cffef" integrity sha512-a8L+OJTbUipBsEDsJhDPlnLB0TY1MkTZqw5dqUwmiDSjUzwvU7HWLg/2+WDRulKUi4LE+7PnHlaBlW0k+V0U0w== -tesseract.js-utils@^1.0.0-beta.8: - version "1.0.0-beta.8" - resolved "https://registry.yarnpkg.com/tesseract.js-utils/-/tesseract.js-utils-1.0.0-beta.8.tgz#d1ef25c12609a337c3e0ac12a33f9903f3145a68" - integrity sha512-qjHBfWfzo2o1ZY9XI0Wh2hmpp38+mIgCMOk60W5Yyie/pBl421VLBKOZUEwQgpbLnOJ24VU6Q8yXsVgtFFHcFg== +tesseract.js@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tesseract.js/-/tesseract.js-2.1.1.tgz#5c50fc95542ce8d834cb952bfb75a8fc85f1441d" + integrity sha512-utg0A8UzT1KwBvZf+UMGmM8LU6izeol6yIem0Z44+7Qqd/YWgRVQ99XOG18ApTOXX48lGE++PDwlcZYkv0ygRQ== dependencies: - axios "^0.18.0" bmp-js "^0.1.0" - file-type "^10.5.0" - idb-keyval "^3.1.0" + file-type "^12.4.1" + idb-keyval "^3.2.0" + is-electron "^2.2.0" is-url "^1.2.4" - zlibjs "^0.3.1" - -tesseract.js@2.0.0-alpha.16: - version "2.0.0-alpha.16" - resolved "https://registry.yarnpkg.com/tesseract.js/-/tesseract.js-2.0.0-alpha.16.tgz#1e17717234a1464481abe12283f2c3ac79603d2e" - integrity sha512-8g3je2Kl8rkAFtpmwilGGj+8rCiPClNQaCjW6IafOPNn7hzFnVdL6fU6rG1Xsrc4Twv0HOa75kbpx5u70/WbTA== - dependencies: - axios "^0.18.0" - check-types "^7.4.0" - is-url "1.2.2" + node-fetch "^2.6.0" opencollective-postinstall "^2.0.2" + regenerator-runtime "^0.13.3" resolve-url "^0.2.1" - tesseract.js-core "^2.0.0-beta.12" - tesseract.js-utils "^1.0.0-beta.8" + tesseract.js-core "^2.2.0" + zlibjs "^0.3.1" test-exclude@^6.0.0: version "6.0.0" @@ -10631,13 +10538,6 @@ tiny-warning@^1.0.0: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -10690,6 +10590,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -10714,11 +10619,6 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - ts-essentials@^2.0.3: version "2.0.12" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" @@ -10756,6 +10656,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -10899,9 +10806,9 @@ upath@^1.1.1: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -10910,7 +10817,7 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@^1.4.7: version "1.4.7" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== @@ -10933,10 +10840,17 @@ use-composed-ref@^1.0.0: dependencies: ts-essentials "^2.0.3" -use-latest@^1.0.0: +use-isomorphic-layout-effect@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.0.0.tgz#c86d2e4893b15f27def69da574a47136d107facb" - integrity sha512-CxmFi75KTXeTIBlZq3LhJ4Hz98pCaRKZHCpnbiaEHIr5QnuHvH8lKYoluPBt/ik7j/hFVPB8K3WqF6mQvLyQTg== + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.0.0.tgz#f56b4ed633e1c21cd9fc76fe249002a1c28989fb" + integrity sha512-JMwJ7Vd86NwAt1jH7q+OIozZSIxA4ND0fx6AsOe2q1H8ooBUp5aN6DvVCqZiIaYU6JaMRJGyR0FO7EBCIsb/Rg== + +use-latest@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.1.0.tgz#7bf9684555869c3f5f37e10d0884c8accf4d3aa6" + integrity sha512-gF04d0ZMV3AMB8Q7HtfkAWe+oq1tFXP6dZKwBHQF5nVXtGsh2oAYeeqma5ZzxtlpOcW8Ro/tLcfmEodjDeqtuw== + dependencies: + use-isomorphic-layout-effect "^1.0.0" use@^3.1.0: version "3.1.1" @@ -10950,7 +10864,7 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -10996,25 +10910,20 @@ uuid@^3.3.2, uuid@^3.4.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - -uuid@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e" - integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q== +uuid@^8.3.0, uuid@^8.3.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== -v8-to-istanbul@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" - integrity sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ== +v8-to-istanbul@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz#b4fe00e35649ef7785a9b7fcebcea05f37c332fc" + integrity sha512-fLL2rFuQpMtm9r8hrAV2apXX/WqHJ6+IC4/eQVdMDGBUgH/YMV4Gv3duk3kjmyg6uiQWBAA9nJwue4iJUOkHeA== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" @@ -11104,15 +11013,15 @@ watchpack-chokidar2@^2.0.0: dependencies: chokidar "^2.1.8" -watchpack@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa" - integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g== +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" optionalDependencies: - chokidar "^3.4.0" + chokidar "^3.4.1" watchpack-chokidar2 "^2.0.0" wbuf@^1.1.0, wbuf@^1.7.3: @@ -11127,7 +11036,7 @@ webidl-conversions@^5.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== -webidl-conversions@^6.0.0: +webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== @@ -11145,24 +11054,20 @@ webpack-assets-manifest@^3.1.1: tapable "^1.0.0" webpack-sources "^1.0.0" -webpack-bundle-analyzer@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz#ce6b3f908daf069fd1f7266f692cbb3bded9ba16" - integrity sha512-PODQhAYVEourCcOuU+NiYI7WdR8QyELZGgPvB1y2tjbUpbmcQOt5Q7jEK+ttd5se0KSBKD9SXHCEozS++Wllmw== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - bfj "^6.1.1" - chalk "^2.4.1" - commander "^2.18.0" - ejs "^2.6.1" - express "^4.16.3" - filesize "^3.6.1" - gzip-size "^5.0.0" - lodash "^4.17.15" - mkdirp "^0.5.1" - opener "^1.5.1" - ws "^6.0.0" +webpack-bundle-analyzer@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b" + integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^6.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" webpack-cli@^3.3.12: version "3.3.12" @@ -11192,10 +11097,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" - integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== +webpack-dev-server@^3.11.1: + version "3.11.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0" + integrity sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -11217,11 +11122,11 @@ webpack-dev-server@^3.11.0: p-retry "^3.0.1" portfinder "^1.0.26" schema-utils "^1.0.0" - selfsigned "^1.10.7" + selfsigned "^1.10.8" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.20" - sockjs-client "1.4.0" + sockjs "^0.3.21" + sockjs-client "^1.5.0" spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" @@ -11239,12 +11144,13 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== +webpack-merge@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213" + integrity sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA== dependencies: - lodash "^4.17.15" + clone-deep "^4.0.1" + wildcard "^2.0.0" webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" @@ -11254,10 +11160,10 @@ webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.43.0: - version "4.43.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" - integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== +webpack@^4.44.2: + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -11267,7 +11173,7 @@ webpack@^4.43.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -11280,16 +11186,9 @@ webpack@^4.43.0: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.1" + watchpack "^1.7.4" webpack-sources "^1.4.1" -websocket-driver@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" - integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= - dependencies: - websocket-extensions ">=0.1.1" - websocket-driver@>=0.5.1: version "0.7.3" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" @@ -11299,6 +11198,15 @@ websocket-driver@>=0.5.1: safe-buffer ">=5.1.0" websocket-extensions ">=0.1.1" +websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + websocket-extensions@>=0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" @@ -11317,13 +11225,13 @@ whatwg-mimetype@^2.3.0: integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== whatwg-url@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771" - integrity sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw== + version "8.2.2" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.2.2.tgz#85e7f9795108b53d554cec640b2e8aee2a0d4bfd" + integrity sha512-PcVnO6NiewhkmzV0qn7A+UZ9Xx4maNTI+O+TShmfE4pqjoCMwUMjkvoNhNHPTvgR7QH9Xt3R13iHuWy2sToFxQ== dependencies: lodash.sortby "^4.7.0" tr46 "^2.0.2" - webidl-conversions "^5.0.0" + webidl-conversions "^6.1.0" which-module@^2.0.0: version "2.0.0" @@ -11344,10 +11252,10 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -wicg-inert@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.0.3.tgz#7d05eaed64176887ee4c66fc0c4d6fe4b38ccce5" - integrity sha512-XwXf8K0NN4cpagjBlZ2/j/5Sjf6dW3HNbfywEy1y6Z8PJKvSHVGiuc5Id/9RZ6EmGq+GQCGTo7B2SK0Misbr6g== +wicg-inert@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.1.0.tgz#6525f12db188b83f0051bed2ddcf6c1aa5b17590" + integrity sha512-P0ZiWaN9SxOkJbYtF/PIwmIRO8UTqTJtyl33QTQlHfAb6h15T0Dp5m7WTJ8N6UWIoj+KU5M0a8EtfRZLlHiP0Q== wide-align@^1.1.0: version "1.1.3" @@ -11356,7 +11264,12 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -word-wrap@~1.2.3: +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -11386,6 +11299,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -11401,13 +11323,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -11415,17 +11330,17 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^6.0.0, ws@^6.2.1: +ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== dependencies: async-limiter "~1.0.0" -ws@^7.2.3: - version "7.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" - integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== +ws@^7.2.3, ws@^7.3.1: + version "7.4.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" + integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ== xml-name-validator@^3.0.0: version "3.0.0" @@ -11437,13 +11352,6 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xregexp@^4.2.4, xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== - dependencies: - "@babel/runtime-corejs3" "^7.8.3" - xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -11454,6 +11362,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -11485,6 +11398,11 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26" + integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww== + yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" @@ -11501,13 +11419,13 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.3.1, yargs@^15.4.0: - version "15.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.0.tgz#53949fb768309bac1843de9b17b80051e9805ec2" - integrity sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw== +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" - decamelize "^3.2.0" + decamelize "^1.2.0" find-up "^4.1.0" get-caller-file "^2.0.1" require-directory "^2.1.1" @@ -11518,6 +11436,19 @@ yargs@^15.3.1, yargs@^15.4.0: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + zlibjs@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/zlibjs/-/zlibjs-0.3.1.tgz#50197edb28a1c42ca659cc8b4e6a9ddd6d444554"