Merge pull request #2532 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to 0b4a3a0437
This commit is contained in:
commit
d668b85dcd
300 changed files with 3056 additions and 1530 deletions
|
@ -24,4 +24,4 @@ RAILS_ENV=development ./bin/rails db:setup
|
||||||
RAILS_ENV=development ./bin/rails assets:precompile
|
RAILS_ENV=development ./bin/rails assets:precompile
|
||||||
|
|
||||||
# Precompile assets for test
|
# Precompile assets for test
|
||||||
RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile
|
RAILS_ENV=test ./bin/rails assets:precompile
|
||||||
|
|
23
.eslintrc.js
23
.eslintrc.js
|
@ -1,4 +1,7 @@
|
||||||
module.exports = {
|
// @ts-check
|
||||||
|
const { defineConfig } = require('eslint-define-config');
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
root: true,
|
root: true,
|
||||||
|
|
||||||
extends: [
|
extends: [
|
||||||
|
@ -117,7 +120,6 @@ module.exports = {
|
||||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||||
'react/jsx-wrap-multilines': 'error',
|
'react/jsx-wrap-multilines': 'error',
|
||||||
'react/no-deprecated': 'off',
|
'react/no-deprecated': 'off',
|
||||||
'react/no-unknown-property': 'off',
|
|
||||||
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
||||||
'react/self-closing-comp': 'error',
|
'react/self-closing-comp': 'error',
|
||||||
|
|
||||||
|
@ -193,6 +195,7 @@ module.exports = {
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
devDependencies: [
|
devDependencies: [
|
||||||
|
'.eslintrc.js',
|
||||||
'config/webpack/**',
|
'config/webpack/**',
|
||||||
'app/javascript/mastodon/performance.js',
|
'app/javascript/mastodon/performance.js',
|
||||||
'app/javascript/mastodon/test_setup.js',
|
'app/javascript/mastodon/test_setup.js',
|
||||||
|
@ -297,7 +300,6 @@ module.exports = {
|
||||||
'formatjs/no-id': 'off', // IDs are used for translation keys
|
'formatjs/no-id': 'off', // IDs are used for translation keys
|
||||||
'formatjs/no-invalid-icu': 'error',
|
'formatjs/no-invalid-icu': 'error',
|
||||||
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
||||||
'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx
|
|
||||||
'formatjs/no-multiple-whitespaces': 'error',
|
'formatjs/no-multiple-whitespaces': 'error',
|
||||||
'formatjs/no-offset': 'error',
|
'formatjs/no-offset': 'error',
|
||||||
'formatjs/no-useless-message': 'error',
|
'formatjs/no-useless-message': 'error',
|
||||||
|
@ -316,6 +318,7 @@ module.exports = {
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
|
'.eslintrc.js',
|
||||||
'*.config.js',
|
'*.config.js',
|
||||||
'.*rc.js',
|
'.*rc.js',
|
||||||
'ide-helper.js',
|
'ide-helper.js',
|
||||||
|
@ -366,7 +369,7 @@ module.exports = {
|
||||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||||
'@typescript-eslint/consistent-type-exports': 'error',
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
"@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}],
|
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
||||||
|
|
||||||
'jsdoc/require-jsdoc': 'off',
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
|
||||||
|
@ -389,14 +392,6 @@ module.exports = {
|
||||||
env: {
|
env: {
|
||||||
jest: true,
|
jest: true,
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'streaming/**/*',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'import/no-commonjs': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
});
|
||||||
|
|
1
.github/renovate.json5
vendored
1
.github/renovate.json5
vendored
|
@ -50,7 +50,6 @@
|
||||||
matchManagers: ['bundler'],
|
matchManagers: ['bundler'],
|
||||||
matchPackageNames: [
|
matchPackageNames: [
|
||||||
'rack', // Needs to be synced with Rails version
|
'rack', // Needs to be synced with Rails version
|
||||||
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
|
|
||||||
'strong_migrations', // Requires manual upgrade
|
'strong_migrations', // Requires manual upgrade
|
||||||
'sidekiq', // Requires manual upgrade
|
'sidekiq', // Requires manual upgrade
|
||||||
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
|
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
|
||||||
|
|
3
.github/workflows/build-container-image.yml
vendored
3
.github/workflows/build-container-image.yml
vendored
|
@ -21,6 +21,8 @@ on:
|
||||||
type: string
|
type: string
|
||||||
labels:
|
labels:
|
||||||
type: string
|
type: string
|
||||||
|
file_to_build:
|
||||||
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-image:
|
||||||
|
@ -86,6 +88,7 @@ jobs:
|
||||||
- uses: docker/build-push-action@v5
|
- uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ${{ inputs.file_to_build }}
|
||||||
build-args: |
|
build-args: |
|
||||||
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
|
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
|
||||||
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
|
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
|
||||||
|
|
23
.github/workflows/build-nightly.yml
vendored
23
.github/workflows/build-nightly.yml
vendored
|
@ -25,6 +25,7 @@ jobs:
|
||||||
needs: compute-suffix
|
needs: compute-suffix
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
|
file_to_build: Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
cache: false
|
cache: false
|
||||||
|
@ -40,3 +41,25 @@ jobs:
|
||||||
type=raw,value=nightly
|
type=raw,value=nightly
|
||||||
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
build-image-streaming:
|
||||||
|
needs: compute-suffix
|
||||||
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
|
with:
|
||||||
|
file_to_build: streaming/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
use_native_arm64_builder: true
|
||||||
|
cache: false
|
||||||
|
push_to_images: |
|
||||||
|
tootsuite/mastodon-streaming
|
||||||
|
ghcr.io/mastodon/mastodon-streaming
|
||||||
|
version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.description=Nightly build image used for testing purposes
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
tags: |
|
||||||
|
type=raw,value=edge
|
||||||
|
type=raw,value=nightly
|
||||||
|
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
||||||
|
secrets: inherit
|
||||||
|
|
17
.github/workflows/build-push-pr.yml
vendored
17
.github/workflows/build-push-pr.yml
vendored
|
@ -29,6 +29,7 @@ jobs:
|
||||||
needs: compute-suffix
|
needs: compute-suffix
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
|
file_to_build: Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
|
@ -39,3 +40,19 @@ jobs:
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
build-image-streaming:
|
||||||
|
needs: compute-suffix
|
||||||
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
|
with:
|
||||||
|
file_to_build: streaming/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
use_native_arm64_builder: true
|
||||||
|
push_to_images: |
|
||||||
|
ghcr.io/mastodon/mastodon-streaming
|
||||||
|
version_metadata: ${{ needs.compute-suffix.outputs.metadata }}
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
tags: |
|
||||||
|
type=ref,event=pr
|
||||||
|
secrets: inherit
|
||||||
|
|
22
.github/workflows/build-releases.yml
vendored
22
.github/workflows/build-releases.yml
vendored
|
@ -12,6 +12,7 @@ jobs:
|
||||||
build-image:
|
build-image:
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
|
file_to_build: Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
|
@ -26,3 +27,24 @@ jobs:
|
||||||
type=pep440,pattern={{raw}}
|
type=pep440,pattern={{raw}}
|
||||||
type=pep440,pattern=v{{major}}.{{minor}}
|
type=pep440,pattern=v{{major}}.{{minor}}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
build-image-streaming:
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v4.3.')
|
||||||
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
|
with:
|
||||||
|
file_to_build: streaming/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
use_native_arm64_builder: true
|
||||||
|
push_to_images: |
|
||||||
|
tootsuite/mastodon-streaming
|
||||||
|
ghcr.io/mastodon/mastodon-streaming
|
||||||
|
# Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages
|
||||||
|
cache: false
|
||||||
|
# Only tag with latest when ran against the latest stable branch
|
||||||
|
# This needs to be updated after each minor version release
|
||||||
|
flavor: |
|
||||||
|
latest=${{ startsWith(github.ref, 'refs/tags/v4.3.') }}
|
||||||
|
tags: |
|
||||||
|
type=pep440,pattern={{raw}}
|
||||||
|
type=pep440,pattern=v{{major}}.{{minor}}
|
||||||
|
secrets: inherit
|
||||||
|
|
14
.github/workflows/test-image-build.yml
vendored
14
.github/workflows/test-image-build.yml
vendored
|
@ -7,6 +7,7 @@ on:
|
||||||
- .github/workflows/build-releases.yml
|
- .github/workflows/build-releases.yml
|
||||||
- .github/workflows/test-image-build.yml
|
- .github/workflows/test-image-build.yml
|
||||||
- Dockerfile
|
- Dockerfile
|
||||||
|
- streaming/Dockerfile
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
@ -18,4 +19,17 @@ jobs:
|
||||||
|
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
|
file_to_build: Dockerfile
|
||||||
platforms: linux/amd64 # Testing only on native platform so it is performant
|
platforms: linux/amd64 # Testing only on native platform so it is performant
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
build-image-streaming:
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-streaming
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
|
with:
|
||||||
|
file_to_build: streaming/Dockerfile
|
||||||
|
platforms: linux/amd64 # Testing only on native platform so it is performant
|
||||||
|
cache: true
|
||||||
|
|
|
@ -26,9 +26,7 @@ Lint/NonLocalExitFromIterator:
|
||||||
|
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 144
|
Max: 130
|
||||||
Exclude:
|
|
||||||
- 'app/serializers/initial_state_serializer.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: CountBlocks, Max.
|
# Configuration parameters: CountBlocks, Max.
|
||||||
Metrics/BlockNesting:
|
Metrics/BlockNesting:
|
||||||
|
@ -109,25 +107,11 @@ Rails/ApplicationController:
|
||||||
# Include: app/models/**/*.rb
|
# Include: app/models/**/*.rb
|
||||||
Rails/HasAndBelongsToMany:
|
Rails/HasAndBelongsToMany:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account_associations.rb'
|
- 'app/models/concerns/account/associations.rb'
|
||||||
- 'app/models/preview_card.rb'
|
- 'app/models/preview_card.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
|
||||||
# Include: app/models/**/*.rb
|
|
||||||
Rails/HasManyOrHasOneDependent:
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/concerns/account_counters.rb'
|
|
||||||
- 'app/models/conversation.rb'
|
|
||||||
- 'app/models/custom_emoji.rb'
|
|
||||||
- 'app/models/custom_emoji_category.rb'
|
|
||||||
- 'app/models/domain_block.rb'
|
|
||||||
- 'app/models/invite.rb'
|
|
||||||
- 'app/models/status.rb'
|
|
||||||
- 'app/models/user.rb'
|
|
||||||
- 'app/models/web/push_subscription.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
# Configuration parameters: Include.
|
||||||
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
||||||
Rails/LexicallyScopedActionFilter:
|
Rails/LexicallyScopedActionFilter:
|
||||||
|
@ -174,7 +158,7 @@ Rails/SkipsModelValidations:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/invites_controller.rb'
|
- 'app/controllers/admin/invites_controller.rb'
|
||||||
- 'app/controllers/concerns/session_tracking_concern.rb'
|
- 'app/controllers/concerns/session_tracking_concern.rb'
|
||||||
- 'app/models/concerns/account_merging.rb'
|
- 'app/models/concerns/account/merging.rb'
|
||||||
- 'app/models/concerns/expireable.rb'
|
- 'app/models/concerns/expireable.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/trends/links.rb'
|
- 'app/models/trends/links.rb'
|
||||||
|
@ -254,7 +238,7 @@ Rails/WhereExists:
|
||||||
- 'app/lib/feed_manager.rb'
|
- 'app/lib/feed_manager.rb'
|
||||||
- 'app/lib/status_cache_hydrator.rb'
|
- 'app/lib/status_cache_hydrator.rb'
|
||||||
- 'app/lib/suspicious_sign_in_detector.rb'
|
- 'app/lib/suspicious_sign_in_detector.rb'
|
||||||
- 'app/models/concerns/account_interactions.rb'
|
- 'app/models/concerns/account/interactions.rb'
|
||||||
- 'app/models/featured_tag.rb'
|
- 'app/models/featured_tag.rb'
|
||||||
- 'app/models/poll.rb'
|
- 'app/models/poll.rb'
|
||||||
- 'app/models/session_activation.rb'
|
- 'app/models/session_activation.rb'
|
||||||
|
@ -309,7 +293,7 @@ Style/FetchEnvVar:
|
||||||
- 'config/initializers/devise.rb'
|
- 'config/initializers/devise.rb'
|
||||||
- 'config/initializers/paperclip.rb'
|
- 'config/initializers/paperclip.rb'
|
||||||
- 'config/initializers/vapid.rb'
|
- 'config/initializers/vapid.rb'
|
||||||
- 'lib/mastodon/premailer_webpack_strategy.rb'
|
- 'lib/premailer_webpack_strategy.rb'
|
||||||
- 'lib/mastodon/redis_config.rb'
|
- 'lib/mastodon/redis_config.rb'
|
||||||
- 'lib/tasks/repo.rake'
|
- 'lib/tasks/repo.rake'
|
||||||
- 'spec/features/profile_spec.rb'
|
- 'spec/features/profile_spec.rb'
|
||||||
|
@ -344,8 +328,8 @@ Style/GuardClause:
|
||||||
- 'app/lib/request_pool.rb'
|
- 'app/lib/request_pool.rb'
|
||||||
- 'app/lib/webfinger.rb'
|
- 'app/lib/webfinger.rb'
|
||||||
- 'app/lib/webfinger_resource.rb'
|
- 'app/lib/webfinger_resource.rb'
|
||||||
- 'app/models/concerns/account_counters.rb'
|
- 'app/models/concerns/account/counters.rb'
|
||||||
- 'app/models/concerns/ldap_authenticable.rb'
|
- 'app/models/concerns/user/ldap_authenticable.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
- 'app/models/user.rb'
|
- 'app/models/user.rb'
|
||||||
- 'app/services/fan_out_on_write_service.rb'
|
- 'app/services/fan_out_on_write_service.rb'
|
||||||
|
@ -359,8 +343,8 @@ Style/GuardClause:
|
||||||
- 'config/initializers/devise.rb'
|
- 'config/initializers/devise.rb'
|
||||||
- 'db/migrate/20170901141119_truncate_preview_cards.rb'
|
- 'db/migrate/20170901141119_truncate_preview_cards.rb'
|
||||||
- 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb'
|
- 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb'
|
||||||
- 'lib/devise/two_factor_ldap_authenticatable.rb'
|
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
|
||||||
- 'lib/devise/two_factor_pam_authenticatable.rb'
|
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
|
||||||
- 'lib/mastodon/cli/accounts.rb'
|
- 'lib/mastodon/cli/accounts.rb'
|
||||||
- 'lib/mastodon/cli/maintenance.rb'
|
- 'lib/mastodon/cli/maintenance.rb'
|
||||||
- 'lib/mastodon/cli/media.rb'
|
- 'lib/mastodon/cli/media.rb'
|
||||||
|
@ -374,8 +358,8 @@ Style/HashAsLastArrayItem:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/statuses_controller.rb'
|
- 'app/controllers/admin/statuses_controller.rb'
|
||||||
- 'app/controllers/api/v1/statuses_controller.rb'
|
- 'app/controllers/api/v1/statuses_controller.rb'
|
||||||
- 'app/models/concerns/account_counters.rb'
|
- 'app/models/concerns/account/counters.rb'
|
||||||
- 'app/models/concerns/status_threading_concern.rb'
|
- 'app/models/concerns/status/threading_concern.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/services/batched_remove_status_service.rb'
|
- 'app/services/batched_remove_status_service.rb'
|
||||||
- 'app/services/notify_service.rb'
|
- 'app/services/notify_service.rb'
|
||||||
|
@ -488,15 +472,15 @@ Style/RedundantReturn:
|
||||||
# AllowedMethods: present?, blank?, presence, try, try!
|
# AllowedMethods: present?, blank?, presence, try, try!
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account_finder_concern.rb'
|
- 'app/models/concerns/account/finder_concern.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
# SupportedStyles: only_raise, only_fail, semantic
|
# SupportedStyles: only_raise, only_fail, semantic
|
||||||
Style/SignalException:
|
Style/SignalException:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/devise/two_factor_ldap_authenticatable.rb'
|
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
|
||||||
- 'lib/devise/two_factor_pam_authenticatable.rb'
|
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
Style/SingleArgumentDig:
|
Style/SingleArgumentDig:
|
||||||
|
|
321
Dockerfile
321
Dockerfile
|
@ -1,112 +1,259 @@
|
||||||
# syntax=docker/dockerfile:1.4
|
# syntax=docker/dockerfile:1.4
|
||||||
# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim
|
|
||||||
ARG NODE_VERSION="20.9-bookworm-slim"
|
|
||||||
|
|
||||||
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby
|
# Please see https://docs.docker.com/engine/reference/builder for information about
|
||||||
FROM node:${NODE_VERSION} as build
|
# the extended buildx capabilities used in this file.
|
||||||
|
# Make sure multiarch TARGETPLATFORM is available for interpolation
|
||||||
|
# See: https://docs.docker.com/build/building/multi-platform/
|
||||||
|
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
||||||
|
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
||||||
|
|
||||||
COPY --link --from=ruby /opt/ruby /opt/ruby
|
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"]
|
||||||
|
ARG RUBY_VERSION="3.2.2"
|
||||||
|
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||||
|
ARG NODE_MAJOR_VERSION="20"
|
||||||
|
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
||||||
|
ARG DEBIAN_VERSION="bookworm"
|
||||||
|
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
||||||
|
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
|
||||||
|
# Ruby image to use for base image based on combined variables (ex: 3.2.2-slim-bookworm)
|
||||||
|
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND="noninteractive" \
|
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
||||||
PATH="${PATH}:/opt/ruby/bin"
|
# Example: v4.2.0-nightly.2023.11.09+something
|
||||||
|
# Overwrite existance of 'alpha.0' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"]
|
||||||
|
ARG MASTODON_VERSION_PRERELEASE=""
|
||||||
|
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="something"]
|
||||||
|
ARG MASTODON_VERSION_METADATA=""
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
# Allow Ruby on Rails to serve static files
|
||||||
|
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
|
||||||
|
ARG RAILS_SERVE_STATIC_FILES="true"
|
||||||
|
# Allow to use YJIT compiler
|
||||||
|
# See: https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md
|
||||||
|
ARG RUBY_YJIT_ENABLE="1"
|
||||||
|
# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
|
||||||
|
ARG TZ="Etc/UTC"
|
||||||
|
# Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234]
|
||||||
|
ARG UID="991"
|
||||||
|
# Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234]
|
||||||
|
ARG GID="991"
|
||||||
|
|
||||||
|
# Apply Mastodon build options based on options above
|
||||||
|
ENV \
|
||||||
|
# Apply Mastodon version information
|
||||||
|
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
||||||
|
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
|
||||||
|
# Apply Mastodon static files and YJIT options
|
||||||
|
RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
|
||||||
|
RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
|
||||||
|
# Apply timezone
|
||||||
|
TZ=${TZ}
|
||||||
|
|
||||||
|
ENV \
|
||||||
|
# Configure the IP to bind Mastodon to when serving traffic
|
||||||
|
BIND="0.0.0.0" \
|
||||||
|
# Use production settings for Yarn, Node and related nodejs based tools
|
||||||
|
NODE_ENV="production" \
|
||||||
|
# Use production settings for Ruby on Rails
|
||||||
|
RAILS_ENV="production" \
|
||||||
|
# Add Ruby and Mastodon installation to the PATH
|
||||||
|
DEBIAN_FRONTEND="noninteractive" \
|
||||||
|
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
|
||||||
|
# Optimize jemalloc 5.x performance
|
||||||
|
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0"
|
||||||
|
|
||||||
|
# Set default shell used for running commands
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
RUN echo "Target platform is $TARGETPLATFORM"
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Remove automatic apt cache Docker cleanup scripts
|
||||||
|
rm -f /etc/apt/apt.conf.d/docker-clean; \
|
||||||
|
# Sets timezone
|
||||||
|
echo "${TZ}" > /etc/localtime; \
|
||||||
|
# Creates mastodon user/group and sets home directory
|
||||||
|
groupadd -g "${GID}" mastodon; \
|
||||||
|
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
|
||||||
|
# Creates /mastodon symlink to /opt/mastodon
|
||||||
|
ln -s /opt/mastodon /mastodon;
|
||||||
|
|
||||||
|
# Set /opt/mastodon as working directory
|
||||||
WORKDIR /opt/mastodon
|
WORKDIR /opt/mastodon
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
# hadolint ignore=DL3008,DL3005
|
||||||
RUN apt-get update && \
|
RUN \
|
||||||
apt-get -yq dist-upgrade && \
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
apt-get install -y --no-install-recommends build-essential \
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
git \
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
libicu-dev \
|
# Apt update & upgrade to check for security updates to Debian image
|
||||||
libidn-dev \
|
apt-get update; \
|
||||||
libpq-dev \
|
apt-get dist-upgrade -yq; \
|
||||||
libjemalloc-dev \
|
# Install jemalloc, curl and other necessary components
|
||||||
zlib1g-dev \
|
apt-get install -y --no-install-recommends \
|
||||||
libgdbm-dev \
|
ca-certificates \
|
||||||
libgmp-dev \
|
curl \
|
||||||
libssl-dev \
|
ffmpeg \
|
||||||
libyaml-dev \
|
file \
|
||||||
ca-certificates \
|
imagemagick \
|
||||||
libreadline8 \
|
libjemalloc2 \
|
||||||
python3 \
|
patchelf \
|
||||||
shared-mime-info && \
|
procps \
|
||||||
bundle config set --local deployment 'true' && \
|
tini \
|
||||||
bundle config set --local without 'development test' && \
|
tzdata \
|
||||||
bundle config set silence_root_warning true && \
|
; \
|
||||||
corepack enable
|
# Patch Ruby to use jemalloc
|
||||||
|
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
|
||||||
|
# Discard patchelf after use
|
||||||
|
apt-get purge -y \
|
||||||
|
patchelf \
|
||||||
|
;
|
||||||
|
|
||||||
COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
# Create temporary build layer from base image
|
||||||
|
FROM ruby as build
|
||||||
|
|
||||||
|
# Copy Node package configuration files into working directory
|
||||||
|
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||||
|
COPY .yarn /opt/mastodon/.yarn
|
||||||
|
|
||||||
|
COPY --from=node /usr/local/bin /usr/local/bin
|
||||||
|
COPY --from=node /usr/local/lib /usr/local/lib
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
# hadolint ignore=DL3008
|
||||||
|
RUN \
|
||||||
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
|
# Install build tools and bundler dependencies from APT
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
git \
|
||||||
|
libgdbm-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libidn-dev \
|
||||||
|
libpq-dev \
|
||||||
|
libssl-dev \
|
||||||
|
make \
|
||||||
|
shared-mime-info \
|
||||||
|
zlib1g-dev \
|
||||||
|
;
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Configure Corepack
|
||||||
|
rm /usr/local/bin/yarn*; \
|
||||||
|
corepack enable; \
|
||||||
|
corepack prepare --activate;
|
||||||
|
|
||||||
|
# Create temporary bundler specific build layer from build layer
|
||||||
|
FROM build as bundler
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
# Copy Gemfile config into working directory
|
||||||
|
COPY Gemfile* /opt/mastodon/
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Mount Ruby Gem caches
|
||||||
|
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
|
||||||
|
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
|
||||||
|
bundle config set --global frozen "true"; \
|
||||||
|
# Configure bundle to not cache downloaded Gems
|
||||||
|
bundle config set --global cache_all "false"; \
|
||||||
|
# Configure bundle to only process production Gems
|
||||||
|
bundle config set --local without "development test"; \
|
||||||
|
# Configure bundle to not warn about root user
|
||||||
|
bundle config set silence_root_warning "true"; \
|
||||||
|
# Download and install required Gems
|
||||||
|
bundle install -j"$(nproc)";
|
||||||
|
|
||||||
|
# Create temporary node specific build layer from build layer
|
||||||
|
FROM build as yarn
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
# Copy Node package configuration files into working directory
|
||||||
|
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||||
COPY streaming/package.json /opt/mastodon/streaming/
|
COPY streaming/package.json /opt/mastodon/streaming/
|
||||||
COPY .yarn /opt/mastodon/.yarn
|
COPY .yarn /opt/mastodon/.yarn
|
||||||
|
|
||||||
RUN bundle install -j"$(nproc)"
|
# hadolint ignore=DL3008
|
||||||
|
RUN \
|
||||||
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
||||||
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
||||||
|
# Install Node packages
|
||||||
|
yarn workspaces focus --production @mastodon/mastodon;
|
||||||
|
|
||||||
RUN yarn workspaces focus --all --production && \
|
# Create temporary assets build layer from build layer
|
||||||
yarn cache clean
|
FROM build as precompiler
|
||||||
|
|
||||||
FROM node:${NODE_VERSION}
|
# Copy Mastodon sources into precompiler layer
|
||||||
|
COPY . /opt/mastodon/
|
||||||
|
|
||||||
# Use those args to specify your own version flags & suffixes
|
# Copy bundler and node packages from build layer to container
|
||||||
ARG MASTODON_VERSION_PRERELEASE=""
|
COPY --from=yarn /opt/mastodon /opt/mastodon/
|
||||||
ARG MASTODON_VERSION_METADATA=""
|
COPY --from=bundler /opt/mastodon /opt/mastodon/
|
||||||
|
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
||||||
|
|
||||||
ARG UID="991"
|
ARG TARGETPLATFORM
|
||||||
ARG GID="991"
|
|
||||||
|
|
||||||
COPY --link --from=ruby /opt/ruby /opt/ruby
|
RUN \
|
||||||
|
# Use Ruby on Rails to create Mastodon assets
|
||||||
|
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \
|
||||||
|
# Cleanup temporary files
|
||||||
|
rm -fr /opt/mastodon/tmp;
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
# Prep final Mastodon Ruby layer
|
||||||
|
FROM ruby as mastodon
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND="noninteractive" \
|
ARG TARGETPLATFORM
|
||||||
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
|
|
||||||
|
|
||||||
# Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use
|
# hadolint ignore=DL3008
|
||||||
# hadolint ignore=DL3008,DL3009
|
RUN \
|
||||||
RUN apt-get update && \
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
echo "Etc/UTC" > /etc/localtime && \
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
groupadd -g "${GID}" mastodon && \
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \
|
# Mount Corepack and Yarn caches from Docker buildx caches
|
||||||
apt-get -y --no-install-recommends install whois \
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
||||||
wget \
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
||||||
procps \
|
# Apt update install non-dev versions of necessary components
|
||||||
libssl3 \
|
apt-get install -y --no-install-recommends \
|
||||||
libpq5 \
|
libssl3 \
|
||||||
imagemagick \
|
libpq5 \
|
||||||
ffmpeg \
|
libicu72 \
|
||||||
libjemalloc2 \
|
libidn12 \
|
||||||
libicu72 \
|
libreadline8 \
|
||||||
libidn12 \
|
libyaml-0-2 \
|
||||||
libyaml-0-2 \
|
;
|
||||||
file \
|
|
||||||
ca-certificates \
|
|
||||||
tzdata \
|
|
||||||
libreadline8 \
|
|
||||||
tini && \
|
|
||||||
ln -s /opt/mastodon /mastodon && \
|
|
||||||
corepack enable
|
|
||||||
|
|
||||||
# Note: no, cleaning here since Debian does this automatically
|
# Copy Mastodon sources into final layer
|
||||||
# See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem
|
COPY . /opt/mastodon/
|
||||||
|
|
||||||
COPY --chown=mastodon:mastodon . /opt/mastodon
|
# Copy compiled assets to layer
|
||||||
COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon
|
COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs
|
||||||
|
COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets
|
||||||
|
# Copy bundler components to layer
|
||||||
|
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
||||||
|
|
||||||
ENV RAILS_ENV="production" \
|
RUN \
|
||||||
NODE_ENV="production" \
|
# Precompile bootsnap code for faster Rails startup
|
||||||
RAILS_SERVE_STATIC_FILES="true" \
|
bundle exec bootsnap precompile --gemfile app/ lib/;
|
||||||
BIND="0.0.0.0" \
|
|
||||||
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
|
||||||
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}"
|
|
||||||
|
|
||||||
# Set the run user
|
RUN \
|
||||||
|
# Pre-create and chown system volume to Mastodon user
|
||||||
|
mkdir -p /opt/mastodon/public/system; \
|
||||||
|
chown mastodon:mastodon /opt/mastodon/public/system; \
|
||||||
|
# Set Mastodon user as owner of tmp folder
|
||||||
|
chown -R mastodon:mastodon /opt/mastodon/tmp;
|
||||||
|
|
||||||
|
# Set the running user for resulting container
|
||||||
USER mastodon
|
USER mastodon
|
||||||
WORKDIR /opt/mastodon
|
# Expose default Puma ports
|
||||||
|
EXPOSE 3000
|
||||||
# Precompile assets
|
# Set container tini as default entry point
|
||||||
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
|
|
||||||
# Set the work dir and the container entry point
|
|
||||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
|
||||||
EXPOSE 3000 4000
|
|
3
Gemfile
3
Gemfile
|
@ -5,7 +5,7 @@ ruby '>= 3.0.0'
|
||||||
|
|
||||||
gem 'puma', '~> 6.3'
|
gem 'puma', '~> 6.3'
|
||||||
gem 'rails', '~> 7.1.1'
|
gem 'rails', '~> 7.1.1'
|
||||||
gem 'sprockets', '~> 3.7.2'
|
gem 'propshaft'
|
||||||
gem 'thor', '~> 1.2'
|
gem 'thor', '~> 1.2'
|
||||||
gem 'rack', '~> 2.2.7'
|
gem 'rack', '~> 2.2.7'
|
||||||
|
|
||||||
|
@ -89,7 +89,6 @@ gem 'sidekiq-unique-jobs', '~> 7.1'
|
||||||
gem 'sidekiq-bulk', '~> 0.2.0'
|
gem 'sidekiq-bulk', '~> 0.2.0'
|
||||||
gem 'simple-navigation', '~> 4.4'
|
gem 'simple-navigation', '~> 4.4'
|
||||||
gem 'simple_form', '~> 5.2'
|
gem 'simple_form', '~> 5.2'
|
||||||
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
|
|
||||||
gem 'stoplight', '~> 3.0.1'
|
gem 'stoplight', '~> 3.0.1'
|
||||||
gem 'strong_migrations', '1.6.4'
|
gem 'strong_migrations', '1.6.4'
|
||||||
gem 'tty-prompt', '~> 0.23', require: false
|
gem 'tty-prompt', '~> 0.23', require: false
|
||||||
|
|
46
Gemfile.lock
46
Gemfile.lock
|
@ -156,7 +156,7 @@ GEM
|
||||||
nokogiri (~> 1, >= 1.10.8)
|
nokogiri (~> 1, >= 1.10.8)
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
bcp47_spec (0.2.1)
|
bcp47_spec (0.2.1)
|
||||||
bcrypt (3.1.19)
|
bcrypt (3.1.20)
|
||||||
better_errors (2.10.1)
|
better_errors (2.10.1)
|
||||||
erubi (>= 1.0.0)
|
erubi (>= 1.0.0)
|
||||||
rack (>= 0.9.0)
|
rack (>= 0.9.0)
|
||||||
|
@ -175,7 +175,7 @@ GEM
|
||||||
blurhash (0.1.7)
|
blurhash (0.1.7)
|
||||||
bootsnap (1.17.0)
|
bootsnap (1.17.0)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
brakeman (6.0.1)
|
brakeman (6.1.0)
|
||||||
browser (5.3.1)
|
browser (5.3.1)
|
||||||
brpoplpush-redis_script (0.1.3)
|
brpoplpush-redis_script (0.1.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
|
@ -197,7 +197,7 @@ GEM
|
||||||
activesupport
|
activesupport
|
||||||
cbor (0.5.9.6)
|
cbor (0.5.9.6)
|
||||||
charlock_holmes (0.7.7)
|
charlock_holmes (0.7.7)
|
||||||
chewy (7.3.4)
|
chewy (7.3.5)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
elasticsearch (>= 7.12.0, < 7.14.0)
|
elasticsearch (>= 7.12.0, < 7.14.0)
|
||||||
elasticsearch-dsl
|
elasticsearch-dsl
|
||||||
|
@ -245,7 +245,7 @@ GEM
|
||||||
docile (1.4.0)
|
docile (1.4.0)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
doorkeeper (5.6.7)
|
doorkeeper (5.6.8)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
dotenv (2.8.1)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.8.1)
|
dotenv-rails (2.8.1)
|
||||||
|
@ -377,11 +377,11 @@ GEM
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
idn-ruby (0.1.5)
|
idn-ruby (0.1.5)
|
||||||
io-console (0.6.0)
|
io-console (0.6.0)
|
||||||
irb (1.9.1)
|
irb (1.10.1)
|
||||||
rdoc
|
rdoc
|
||||||
reline (>= 0.3.8)
|
reline (>= 0.3.8)
|
||||||
jmespath (1.6.2)
|
jmespath (1.6.2)
|
||||||
json (2.6.3)
|
json (2.7.0)
|
||||||
json-canonicalization (1.0.0)
|
json-canonicalization (1.0.0)
|
||||||
json-jwt (1.15.3)
|
json-jwt (1.15.3)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
|
@ -484,7 +484,8 @@ GEM
|
||||||
nokogiri (1.15.5)
|
nokogiri (1.15.5)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.16.1)
|
oj (3.16.2)
|
||||||
|
bigdecimal (~> 3.1)
|
||||||
omniauth (2.1.1)
|
omniauth (2.1.1)
|
||||||
hashie (>= 3.4.6)
|
hashie (>= 3.4.6)
|
||||||
rack (>= 2.2.3)
|
rack (>= 2.2.3)
|
||||||
|
@ -522,7 +523,7 @@ GEM
|
||||||
pastel (0.8.0)
|
pastel (0.8.0)
|
||||||
tty-color (~> 0.5)
|
tty-color (~> 0.5)
|
||||||
pg (1.5.4)
|
pg (1.5.4)
|
||||||
pghero (3.3.4)
|
pghero (3.4.0)
|
||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
premailer (1.21.0)
|
premailer (1.21.0)
|
||||||
|
@ -534,6 +535,11 @@ GEM
|
||||||
net-smtp
|
net-smtp
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
premailer (~> 1.7, >= 1.7.9)
|
||||||
private_address_check (0.5.0)
|
private_address_check (0.5.0)
|
||||||
|
propshaft (0.8.0)
|
||||||
|
actionpack (>= 7.0.0)
|
||||||
|
activesupport (>= 7.0.0)
|
||||||
|
rack
|
||||||
|
railties (>= 7.0.0)
|
||||||
psych (5.1.1.1)
|
psych (5.1.1.1)
|
||||||
stringio
|
stringio
|
||||||
public_suffix (5.0.4)
|
public_suffix (5.0.4)
|
||||||
|
@ -608,7 +614,7 @@ GEM
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.6.1)
|
rdf-normalize (0.6.1)
|
||||||
rdf (~> 3.2)
|
rdf (~> 3.2)
|
||||||
rdoc (6.6.0)
|
rdoc (6.6.1)
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
redcarpet (3.6.0)
|
redcarpet (3.6.0)
|
||||||
redis (4.8.1)
|
redis (4.8.1)
|
||||||
|
@ -617,7 +623,7 @@ GEM
|
||||||
redlock (1.3.2)
|
redlock (1.3.2)
|
||||||
redis (>= 3.0.0, < 6.0)
|
redis (>= 3.0.0, < 6.0)
|
||||||
regexp_parser (2.8.2)
|
regexp_parser (2.8.2)
|
||||||
reline (0.4.0)
|
reline (0.4.1)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
request_store (1.5.1)
|
request_store (1.5.1)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
|
@ -656,7 +662,7 @@ GEM
|
||||||
rspec-mocks (~> 3.0)
|
rspec-mocks (~> 3.0)
|
||||||
sidekiq (>= 5, < 8)
|
sidekiq (>= 5, < 8)
|
||||||
rspec-support (3.12.1)
|
rspec-support (3.12.1)
|
||||||
rubocop (1.57.2)
|
rubocop (1.58.0)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
|
@ -664,7 +670,7 @@ GEM
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rexml (>= 3.2.5, < 4.0)
|
||||||
rubocop-ast (>= 1.28.1, < 2.0)
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
rubocop-ast (1.30.0)
|
rubocop-ast (1.30.0)
|
||||||
|
@ -702,7 +708,7 @@ GEM
|
||||||
scenic (1.7.0)
|
scenic (1.7.0)
|
||||||
activerecord (>= 4.0.0)
|
activerecord (>= 4.0.0)
|
||||||
railties (>= 4.0.0)
|
railties (>= 4.0.0)
|
||||||
selenium-webdriver (4.15.0)
|
selenium-webdriver (4.16.0)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (>= 1.2.2, < 3.0)
|
rubyzip (>= 1.2.2, < 3.0)
|
||||||
websocket (~> 1.0)
|
websocket (~> 1.0)
|
||||||
|
@ -736,18 +742,11 @@ GEM
|
||||||
simplecov-lcov (0.8.0)
|
simplecov-lcov (0.8.0)
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
smart_properties (1.17.0)
|
smart_properties (1.17.0)
|
||||||
sprockets (3.7.2)
|
|
||||||
concurrent-ruby (~> 1.0)
|
|
||||||
rack (> 1, < 3)
|
|
||||||
sprockets-rails (3.4.2)
|
|
||||||
actionpack (>= 5.2)
|
|
||||||
activesupport (>= 5.2)
|
|
||||||
sprockets (>= 3.0.0)
|
|
||||||
stackprof (0.2.25)
|
stackprof (0.2.25)
|
||||||
statsd-ruby (1.5.0)
|
statsd-ruby (1.5.0)
|
||||||
stoplight (3.0.2)
|
stoplight (3.0.2)
|
||||||
redlock (~> 1.0)
|
redlock (~> 1.0)
|
||||||
stringio (3.0.9)
|
stringio (3.1.0)
|
||||||
strong_migrations (1.6.4)
|
strong_migrations (1.6.4)
|
||||||
activerecord (>= 5.2)
|
activerecord (>= 5.2)
|
||||||
swd (1.3.0)
|
swd (1.3.0)
|
||||||
|
@ -755,7 +754,7 @@ GEM
|
||||||
attr_required (>= 0.0.5)
|
attr_required (>= 0.0.5)
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
sysexits (1.2.0)
|
sysexits (1.2.0)
|
||||||
temple (0.10.2)
|
temple (0.10.3)
|
||||||
terminal-table (3.0.2)
|
terminal-table (3.0.2)
|
||||||
unicode-display_width (>= 1.1.1, < 3)
|
unicode-display_width (>= 1.1.1, < 3)
|
||||||
terrapin (0.6.0)
|
terrapin (0.6.0)
|
||||||
|
@ -911,6 +910,7 @@ DEPENDENCIES
|
||||||
posix-spawn
|
posix-spawn
|
||||||
premailer-rails
|
premailer-rails
|
||||||
private_address_check (~> 0.5)
|
private_address_check (~> 0.5)
|
||||||
|
propshaft
|
||||||
public_suffix (~> 5.0)
|
public_suffix (~> 5.0)
|
||||||
puma (~> 6.3)
|
puma (~> 6.3)
|
||||||
pundit (~> 2.3)
|
pundit (~> 2.3)
|
||||||
|
@ -949,8 +949,6 @@ DEPENDENCIES
|
||||||
simple_form (~> 5.2)
|
simple_form (~> 5.2)
|
||||||
simplecov (~> 0.22)
|
simplecov (~> 0.22)
|
||||||
simplecov-lcov (~> 0.8)
|
simplecov-lcov (~> 0.8)
|
||||||
sprockets (~> 3.7.2)
|
|
||||||
sprockets-rails (~> 3.4)
|
|
||||||
stackprof
|
stackprof
|
||||||
stoplight (~> 3.0.1)
|
stoplight (~> 3.0.1)
|
||||||
strong_migrations (= 1.6.4)
|
strong_migrations (= 1.6.4)
|
||||||
|
|
6
Vagrantfile
vendored
6
Vagrantfile
vendored
|
@ -10,7 +10,11 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||||
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||||
|
|
||||||
# Add repo for NodeJS
|
# Add repo for NodeJS
|
||||||
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
|
sudo mkdir -p /etc/apt/keyrings
|
||||||
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
||||||
|
NODE_MAJOR=20
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
# Add firewall rule to redirect 80 to PORT and save
|
# Add firewall rule to redirect 80 to PORT and save
|
||||||
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class AccountsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def only_media_scope
|
def only_media_scope
|
||||||
Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id)
|
Status.joins(:media_attachments).merge(@account.media_attachments).group(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def no_replies_scope
|
def no_replies_scope
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Admin
|
||||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||||
@warnings = @account.strikes.custom.latest
|
@warnings = @account.strikes.custom.latest
|
||||||
|
|
||||||
render template: 'admin/accounts/show'
|
render 'admin/accounts/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Admin
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :audit_log, :index?
|
authorize :audit_log, :index?
|
||||||
@auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username)
|
@auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'csv'
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ExportDomainAllowsController < BaseController
|
class ExportDomainAllowsController < BaseController
|
||||||
include AdminExportControllerConcern
|
include Admin::ExportControllerConcern
|
||||||
|
|
||||||
before_action :set_dummy_import!, only: [:new]
|
before_action :set_dummy_import!, only: [:new]
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'csv'
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ExportDomainBlocksController < BaseController
|
class ExportDomainBlocksController < BaseController
|
||||||
include AdminExportControllerConcern
|
include Admin::ExportControllerConcern
|
||||||
|
|
||||||
before_action :set_dummy_import!, only: [:new]
|
before_action :set_dummy_import!, only: [:new]
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Admin
|
||||||
@relay.enable!
|
@relay.enable!
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
else
|
else
|
||||||
render action: :new
|
render :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ module Admin
|
||||||
@form = Admin::StatusBatchAction.new
|
@form = Admin::StatusBatchAction.new
|
||||||
@statuses = @report.statuses.with_includes
|
@statuses = @report.statuses.with_includes
|
||||||
|
|
||||||
render template: 'admin/reports/show'
|
render 'admin/reports/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ class Api::BaseController < ApplicationController
|
||||||
DEFAULT_STATUSES_LIMIT = 20
|
DEFAULT_STATUSES_LIMIT = 20
|
||||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||||
|
|
||||||
include RateLimitHeaders
|
include Api::RateLimitHeaders
|
||||||
include AccessTokenTrackingConcern
|
include Api::AccessTokenTrackingConcern
|
||||||
include ApiCachingConcern
|
include Api::CachingConcern
|
||||||
include Api::ContentSecurityPolicy
|
include Api::ContentSecurityPolicy
|
||||||
|
|
||||||
skip_before_action :require_functional!, unless: :limited_federation_mode?
|
skip_before_action :require_functional!, unless: :limited_federation_mode?
|
||||||
|
@ -64,7 +64,7 @@ class Api::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_unauthorized_render_options(error: nil)
|
def doorkeeper_unauthorized_render_options(error: nil)
|
||||||
{ json: { error: (error.try(:description) || 'Not authorized') } }
|
{ json: { error: error.try(:description) || 'Not authorized' } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_forbidden_render_options(*)
|
def doorkeeper_forbidden_render_options(*)
|
||||||
|
@ -105,7 +105,7 @@ class Api::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended?
|
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.unavailable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_user!
|
def require_user!
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_results?
|
def hide_results?
|
||||||
@account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
@account.unavailable? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_accounts
|
def default_accounts
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_results?
|
def hide_results?
|
||||||
@account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
@account.unavailable? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_accounts
|
def default_accounts
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_statuses
|
def load_statuses
|
||||||
@account.suspended? ? [] : cached_account_statuses
|
@account.unavailable? ? [] : cached_account_statuses
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_account_statuses
|
def cached_account_statuses
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def mute
|
def mute
|
||||||
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0))
|
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: params[:duration].to_i)
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,11 @@ class Api::V2::SearchController < Api::BaseController
|
||||||
before_action -> { authorize_if_got_token! :read, :'read:search' }
|
before_action -> { authorize_if_got_token! :read, :'read:search' }
|
||||||
before_action :validate_search_params!
|
before_action :validate_search_params!
|
||||||
|
|
||||||
|
with_options unless: :user_signed_in? do
|
||||||
|
before_action :query_pagination_error, if: :pagination_requested?
|
||||||
|
before_action :remote_resolve_error, if: :remote_resolve_requested?
|
||||||
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@search = Search.new(search_results)
|
@search = Search.new(search_results)
|
||||||
render json: @search, serializer: REST::SearchSerializer
|
render json: @search, serializer: REST::SearchSerializer
|
||||||
|
@ -21,12 +26,22 @@ class Api::V2::SearchController < Api::BaseController
|
||||||
|
|
||||||
def validate_search_params!
|
def validate_search_params!
|
||||||
params.require(:q)
|
params.require(:q)
|
||||||
|
end
|
||||||
|
|
||||||
return if user_signed_in?
|
def query_pagination_error
|
||||||
|
render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401
|
||||||
|
end
|
||||||
|
|
||||||
return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present?
|
def remote_resolve_error
|
||||||
|
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401
|
||||||
|
end
|
||||||
|
|
||||||
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve)
|
def remote_resolve_requested?
|
||||||
|
truthy_param?(:resolve)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_requested?
|
||||||
|
params[:offset].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_results
|
def search_results
|
||||||
|
@ -34,7 +49,15 @@ class Api::V2::SearchController < Api::BaseController
|
||||||
params[:q],
|
params[:q],
|
||||||
current_account,
|
current_account,
|
||||||
limit_param(RESULTS_LIMIT),
|
limit_param(RESULTS_LIMIT),
|
||||||
search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed), following: truthy_param?(:following))
|
combined_search_params
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def combined_search_params
|
||||||
|
search_params.merge(
|
||||||
|
resolve: truthy_param?(:resolve),
|
||||||
|
exclude_unreviewed: truthy_param?(:exclude_unreviewed),
|
||||||
|
following: truthy_param?(:following)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
include CaptchaConcern
|
include Auth::CaptchaConcern
|
||||||
|
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class Auth::RegistrationsController < Devise::RegistrationsController
|
class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
include RegistrationHelper
|
include RegistrationHelper
|
||||||
include RegistrationSpamConcern
|
include Auth::RegistrationSpamConcern
|
||||||
|
|
||||||
layout :determine_layout
|
layout :determine_layout
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.suspended?
|
forbidden if current_account.unavailable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_rules
|
def set_rules
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Auth::SessionsController < Devise::SessionsController
|
||||||
prepend_before_action :set_pack
|
prepend_before_action :set_pack
|
||||||
prepend_before_action :check_suspicious!, only: [:create]
|
prepend_before_action :check_suspicious!, only: [:create]
|
||||||
|
|
||||||
include TwoFactorAuthenticationConcern
|
include Auth::TwoFactorAuthenticationConcern
|
||||||
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ module AccountOwnedConcern
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
if @account.suspended_permanently?
|
if @account.permanently_unavailable?
|
||||||
permanent_suspension_response
|
permanent_unavailability_response
|
||||||
elsif @account.suspended? && !skip_temporary_suspension_response?
|
elsif @account.suspended? && !skip_temporary_suspension_response?
|
||||||
temporary_suspension_response
|
temporary_suspension_response
|
||||||
end
|
end
|
||||||
|
@ -45,7 +45,7 @@ module AccountOwnedConcern
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def permanent_suspension_response
|
def permanent_unavailability_response
|
||||||
expires_in(3.minutes, public: true)
|
expires_in(3.minutes, public: true)
|
||||||
gone
|
gone
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AdminExportControllerConcern
|
module Admin::ExportControllerConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
private
|
private
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module AccessTokenTrackingConcern
|
module Api::AccessTokenTrackingConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze
|
ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ApiCachingConcern
|
module Api::CachingConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def cache_if_unauthenticated!
|
def cache_if_unauthenticated!
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module RateLimitHeaders
|
module Api::RateLimitHeaders
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module CaptchaConcern
|
module Auth::CaptchaConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
include Hcaptcha::Adapters::ViewMethods
|
include Hcaptcha::Adapters::ViewMethods
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module RegistrationSpamConcern
|
module Auth::RegistrationSpamConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def set_registration_form_time
|
def set_registration_form_time
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module TwoFactorAuthenticationConcern
|
module Auth::TwoFactorAuthenticationConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -43,7 +43,7 @@ module ChallengableConcern
|
||||||
|
|
||||||
def render_challenge
|
def render_challenge
|
||||||
@body_classes = 'lighter'
|
@body_classes = 'lighter'
|
||||||
render template: 'auth/challenges/new', layout: 'auth'
|
render 'auth/challenges/new', layout: 'auth'
|
||||||
end
|
end
|
||||||
|
|
||||||
def challenge_passed?
|
def challenge_passed?
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ExportControllerConcern
|
module Settings::ExportControllerConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
|
@ -11,7 +11,7 @@ class Disputes::AppealsController < Disputes::BaseController
|
||||||
redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg')
|
redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg')
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
@appeal = e.record
|
@appeal = e.record
|
||||||
render template: 'disputes/strikes/show'
|
render 'disputes/strikes/show'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -26,7 +26,7 @@ class FiltersController < ApplicationController
|
||||||
if @filter.save
|
if @filter.save
|
||||||
redirect_to filters_path
|
redirect_to filters_path
|
||||||
else
|
else
|
||||||
render action: :new
|
render :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class FiltersController < ApplicationController
|
||||||
if @filter.update(resource_params)
|
if @filter.update(resource_params)
|
||||||
redirect_to filters_path
|
redirect_to filters_path
|
||||||
else
|
else
|
||||||
render action: :edit
|
render :edit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.suspended?
|
forbidden if current_account.unavailable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
|
|
|
@ -23,6 +23,6 @@ class Settings::BaseController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.suspended?
|
forbidden if current_account.unavailable?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Settings::DeletesController < Settings::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.suspended?
|
forbidden if current_account.unavailable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def challenge_passed?
|
def challenge_passed?
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BlockedAccountsController < BaseController
|
class BlockedAccountsController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BlockedDomainsController < BaseController
|
class BlockedDomainsController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BookmarksController < BaseController
|
class BookmarksController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class FollowingAccountsController < BaseController
|
class FollowingAccountsController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class ListsController < BaseController
|
class ListsController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class MutedAccountsController < BaseController
|
class MutedAccountsController < BaseController
|
||||||
include ExportControllerConcern
|
include Settings::ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|
|
@ -15,7 +15,7 @@ class StatusesCleanupController < ApplicationController
|
||||||
if @policy.update(resource_params)
|
if @policy.update(resource_params)
|
||||||
redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg')
|
redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg')
|
||||||
else
|
else
|
||||||
render action: :show
|
render :show
|
||||||
end
|
end
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
|
|
@ -42,7 +42,7 @@ module WellKnown
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
gone if @account.suspended_permanently?
|
gone if @account.permanently_unavailable?
|
||||||
end
|
end
|
||||||
|
|
||||||
def gone
|
def gone
|
||||||
|
|
12
app/helpers/admin/account_actions_helper.rb
Normal file
12
app/helpers/admin/account_actions_helper.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin::AccountActionsHelper
|
||||||
|
def account_action_type_label(type)
|
||||||
|
safe_join(
|
||||||
|
[
|
||||||
|
I18n.t("simple_form.labels.admin_account_action.types.#{type}"),
|
||||||
|
content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
19
app/helpers/admin/accounts_helper.rb
Normal file
19
app/helpers/admin/accounts_helper.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin::AccountsHelper
|
||||||
|
def admin_accounts_moderation_options
|
||||||
|
[
|
||||||
|
[t('admin.accounts.moderation.active'), 'active'],
|
||||||
|
[t('admin.accounts.moderation.silenced'), 'silenced'],
|
||||||
|
[t('admin.accounts.moderation.disabled'), 'disabled'],
|
||||||
|
[t('admin.accounts.moderation.suspended'), 'suspended'],
|
||||||
|
[safe_join([t('admin.accounts.moderation.pending'), "(#{pending_user_count_label})"], ' '), 'pending'],
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def pending_user_count_label
|
||||||
|
number_with_delimiter User.pending.count
|
||||||
|
end
|
||||||
|
end
|
12
app/helpers/admin/ip_blocks_helper.rb
Normal file
12
app/helpers/admin/ip_blocks_helper.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin::IpBlocksHelper
|
||||||
|
def ip_blocks_severity_label(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'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
24
app/helpers/admin/roles_helper.rb
Normal file
24
app/helpers/admin/roles_helper.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
module RolesHelper
|
||||||
|
def privilege_label(privilege)
|
||||||
|
safe_join(
|
||||||
|
[
|
||||||
|
t("admin.roles.privileges.#{privilege}"),
|
||||||
|
content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable_permissions?(permissions)
|
||||||
|
permissions.filter { |privilege| role_flag_value(privilege).zero? }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def role_flag_value(privilege)
|
||||||
|
UserRole::FLAGS[privilege] & current_user.role.computed_permissions
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
15
app/helpers/admin/settings/discovery_helper.rb
Normal file
15
app/helpers/admin/settings/discovery_helper.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin::Settings::DiscoveryHelper
|
||||||
|
def discovery_warning_hint_text
|
||||||
|
authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def discovery_hint_text
|
||||||
|
t('admin.settings.security.authorized_fetch_hint')
|
||||||
|
end
|
||||||
|
|
||||||
|
def discovery_recommended_value
|
||||||
|
authorized_fetch_overridden? ? :overridden : nil
|
||||||
|
end
|
||||||
|
end
|
12
app/helpers/filters_helper.rb
Normal file
12
app/helpers/filters_helper.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module FiltersHelper
|
||||||
|
def filter_action_label(action)
|
||||||
|
safe_join(
|
||||||
|
[
|
||||||
|
t("simple_form.labels.filters.actions.#{action}"),
|
||||||
|
content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,9 +1,16 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-call,
|
||||||
|
@typescript-eslint/no-unsafe-return,
|
||||||
|
@typescript-eslint/no-unsafe-assignment,
|
||||||
|
@typescript-eslint/no-unsafe-member-access
|
||||||
|
-- the settings store is not yet typed */
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState, useEffect } from 'react';
|
||||||
|
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { changeSetting } from 'flavours/glitch/actions/settings';
|
||||||
import { bannerSettings } from 'flavours/glitch/settings';
|
import { bannerSettings } from 'flavours/glitch/settings';
|
||||||
|
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
|
||||||
|
|
||||||
import { IconButton } from './icon_button';
|
import { IconButton } from './icon_button';
|
||||||
|
|
||||||
|
@ -19,13 +26,25 @@ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
|
||||||
id,
|
id,
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const [visible, setVisible] = useState(!bannerSettings.get(id));
|
const dismissed = useAppSelector((state) =>
|
||||||
|
state.settings.getIn(['dismissed_banners', id], false),
|
||||||
|
);
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(!bannerSettings.get(id) && !dismissed);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleDismiss = useCallback(() => {
|
const handleDismiss = useCallback(() => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
bannerSettings.set(id, true);
|
bannerSettings.set(id, true);
|
||||||
}, [id]);
|
dispatch(changeSetting(['dismissed_banners', id], true));
|
||||||
|
}, [id, dispatch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible && !dismissed) {
|
||||||
|
dispatch(changeSetting(['dismissed_banners', id], true));
|
||||||
|
}
|
||||||
|
}, [id, dispatch, visible, dismissed]);
|
||||||
|
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -294,9 +294,9 @@ class LoginForm extends React.PureComponent {
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
autocomplete='off'
|
autoComplete='off'
|
||||||
autocapitalize='off'
|
autoCapitalize='off'
|
||||||
spellcheck='false'
|
spellCheck='false'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
|
<Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
|
||||||
|
|
|
@ -59,7 +59,7 @@ class ConfirmationModal extends PureComponent {
|
||||||
{ onDoNotAsk && (
|
{ onDoNotAsk && (
|
||||||
<div className='confirmation-modal__do_not_ask_again'>
|
<div className='confirmation-modal__do_not_ask_again'>
|
||||||
<input type='checkbox' id='confirmation-modal__do_not_ask_again-checkbox' ref={this.setDoNotAskRef} />
|
<input type='checkbox' id='confirmation-modal__do_not_ask_again-checkbox' ref={this.setDoNotAskRef} />
|
||||||
<label for='confirmation-modal__do_not_ask_again-checkbox'>
|
<label htmlFor='confirmation-modal__do_not_ask_again-checkbox'>
|
||||||
<FormattedMessage id='confirmation_modal.do_not_ask_again' defaultMessage='Do not ask for confirmation again' />
|
<FormattedMessage id='confirmation_modal.do_not_ask_again' defaultMessage='Do not ask for confirmation again' />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,7 +66,7 @@ class NavigationPanel extends Component {
|
||||||
return (
|
return (
|
||||||
<div className='navigation-panel'>
|
<div className='navigation-panel'>
|
||||||
{banner &&
|
{banner &&
|
||||||
<div class='navigation-panel__banner'>
|
<div className='navigation-panel__banner'>
|
||||||
{banner}
|
{banner}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,7 +592,6 @@ class Video extends PureComponent {
|
||||||
aria-label={alt}
|
aria-label={alt}
|
||||||
title={alt}
|
title={alt}
|
||||||
lang={lang}
|
lang={lang}
|
||||||
volume={volume}
|
|
||||||
onClick={this.togglePlay}
|
onClick={this.togglePlay}
|
||||||
onKeyDown={this.handleVideoKeyDown}
|
onKeyDown={this.handleVideoKeyDown}
|
||||||
onPlay={this.handlePlay}
|
onPlay={this.handlePlay}
|
||||||
|
|
|
@ -110,6 +110,15 @@ const initialState = ImmutableMap({
|
||||||
body: '',
|
body: '',
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
dismissed_banners: ImmutableMap({
|
||||||
|
'public_timeline': false,
|
||||||
|
'community_timeline': false,
|
||||||
|
'home.explore_prompt': false,
|
||||||
|
'explore/links': false,
|
||||||
|
'explore/statuses': false,
|
||||||
|
'explore/tags': false,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultColumns = fromJS([
|
const defaultColumns = fromJS([
|
||||||
|
|
|
@ -1083,22 +1083,16 @@ $ui-header-height: 55px;
|
||||||
&__description {
|
&__description {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
h6 {
|
h6 {
|
||||||
color: $highlight-text-color;
|
color: $highlight-text-color;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import api from 'mastodon/api';
|
import api from 'mastodon/api';
|
||||||
import Hashtag from 'mastodon/components/hashtag';
|
import { Hashtag } from 'mastodon/components/hashtag';
|
||||||
|
|
||||||
export default class Trends extends PureComponent {
|
export default class Trends extends PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-call,
|
||||||
|
@typescript-eslint/no-unsafe-return,
|
||||||
|
@typescript-eslint/no-unsafe-assignment,
|
||||||
|
@typescript-eslint/no-unsafe-member-access
|
||||||
|
-- the settings store is not yet typed */
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState, useEffect } from 'react';
|
||||||
|
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
|
import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
|
||||||
|
|
||||||
|
import { changeSetting } from 'mastodon/actions/settings';
|
||||||
import { bannerSettings } from 'mastodon/settings';
|
import { bannerSettings } from 'mastodon/settings';
|
||||||
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
|
|
||||||
import { IconButton } from './icon_button';
|
import { IconButton } from './icon_button';
|
||||||
|
|
||||||
|
@ -21,13 +28,25 @@ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
|
||||||
id,
|
id,
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const [visible, setVisible] = useState(!bannerSettings.get(id));
|
const dismissed = useAppSelector((state) =>
|
||||||
|
state.settings.getIn(['dismissed_banners', id], false),
|
||||||
|
);
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(!bannerSettings.get(id) && !dismissed);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const handleDismiss = useCallback(() => {
|
const handleDismiss = useCallback(() => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
bannerSettings.set(id, true);
|
bannerSettings.set(id, true);
|
||||||
}, [id]);
|
dispatch(changeSetting(['dismissed_banners', id], true));
|
||||||
|
}, [id, dispatch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!visible && !dismissed) {
|
||||||
|
dispatch(changeSetting(['dismissed_banners', id], true));
|
||||||
|
}
|
||||||
|
}, [id, dispatch, visible, dismissed]);
|
||||||
|
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
// @ts-check
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Component } from 'react';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
|
|
||||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
|
||||||
|
|
||||||
import { ShortNumber } from 'mastodon/components/short_number';
|
|
||||||
import { Skeleton } from 'mastodon/components/skeleton';
|
|
||||||
|
|
||||||
class SilentErrorBoundary extends Component {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
children: PropTypes.node,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
error: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidCatch() {
|
|
||||||
this.setState({ error: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.props.children;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to render counter of how much people are talking about hashtag
|
|
||||||
* @type {(displayNumber: JSX.Element, pluralReady: number) => JSX.Element}
|
|
||||||
*/
|
|
||||||
export const accountsCountRenderer = (displayNumber, pluralReady) => (
|
|
||||||
<FormattedMessage
|
|
||||||
id='trends.counter_by_accounts'
|
|
||||||
defaultMessage='{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}'
|
|
||||||
values={{
|
|
||||||
count: pluralReady,
|
|
||||||
counter: <strong>{displayNumber}</strong>,
|
|
||||||
days: 2,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
export const ImmutableHashtag = ({ hashtag }) => (
|
|
||||||
<Hashtag
|
|
||||||
name={hashtag.get('name')}
|
|
||||||
to={`/tags/${hashtag.get('name')}`}
|
|
||||||
people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1}
|
|
||||||
// @ts-expect-error
|
|
||||||
history={hashtag.get('history').reverse().map((day) => day.get('uses')).toArray()}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
ImmutableHashtag.propTypes = {
|
|
||||||
hashtag: ImmutablePropTypes.map.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
const Hashtag = ({ name, to, people, uses, history, className, description, withGraph }) => (
|
|
||||||
<div className={classNames('trends__item', className)}>
|
|
||||||
<div className='trends__item__name'>
|
|
||||||
<Link to={to}>
|
|
||||||
{name ? <>#<span>{name}</span></> : <Skeleton width={50} />}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{description ? (
|
|
||||||
<span>{description}</span>
|
|
||||||
) : (
|
|
||||||
typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{typeof uses !== 'undefined' && (
|
|
||||||
<div className='trends__item__current'>
|
|
||||||
<ShortNumber value={uses} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{withGraph && (
|
|
||||||
<div className='trends__item__sparkline'>
|
|
||||||
<SilentErrorBoundary>
|
|
||||||
<Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
|
|
||||||
<SparklinesCurve style={{ fill: 'none' }} />
|
|
||||||
</Sparklines>
|
|
||||||
</SilentErrorBoundary>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
Hashtag.propTypes = {
|
|
||||||
name: PropTypes.string,
|
|
||||||
to: PropTypes.string,
|
|
||||||
people: PropTypes.number,
|
|
||||||
description: PropTypes.node,
|
|
||||||
uses: PropTypes.number,
|
|
||||||
history: PropTypes.arrayOf(PropTypes.number),
|
|
||||||
className: PropTypes.string,
|
|
||||||
withGraph: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
Hashtag.defaultProps = {
|
|
||||||
withGraph: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Hashtag;
|
|
145
app/javascript/mastodon/components/hashtag.tsx
Normal file
145
app/javascript/mastodon/components/hashtag.tsx
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
import type { JSX } from 'react';
|
||||||
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import type Immutable from 'immutable';
|
||||||
|
|
||||||
|
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||||
|
|
||||||
|
import { ShortNumber } from 'mastodon/components/short_number';
|
||||||
|
import { Skeleton } from 'mastodon/components/skeleton';
|
||||||
|
|
||||||
|
interface SilentErrorBoundaryProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SilentErrorBoundary extends Component<SilentErrorBoundaryProps> {
|
||||||
|
state = {
|
||||||
|
error: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidCatch() {
|
||||||
|
this.setState({ error: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to render counter of how much people are talking about hashtag
|
||||||
|
* @param displayNumber Counter number to display
|
||||||
|
* @param pluralReady Whether the count is plural
|
||||||
|
* @returns Formatted counter of how much people are talking about hashtag
|
||||||
|
*/
|
||||||
|
export const accountsCountRenderer = (
|
||||||
|
displayNumber: JSX.Element,
|
||||||
|
pluralReady: number,
|
||||||
|
) => (
|
||||||
|
<FormattedMessage
|
||||||
|
id='trends.counter_by_accounts'
|
||||||
|
defaultMessage='{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {# days}}'
|
||||||
|
values={{
|
||||||
|
count: pluralReady,
|
||||||
|
counter: <strong>{displayNumber}</strong>,
|
||||||
|
days: 2,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
interface ImmutableHashtagProps {
|
||||||
|
hashtag: Immutable.Map<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImmutableHashtag = ({ hashtag }: ImmutableHashtagProps) => (
|
||||||
|
<Hashtag
|
||||||
|
name={hashtag.get('name') as string}
|
||||||
|
to={`/tags/${hashtag.get('name') as string}`}
|
||||||
|
people={
|
||||||
|
(hashtag.getIn(['history', 0, 'accounts']) as number) * 1 +
|
||||||
|
(hashtag.getIn(['history', 1, 'accounts']) as number) * 1
|
||||||
|
}
|
||||||
|
history={(
|
||||||
|
hashtag.get('history') as Immutable.Collection.Indexed<
|
||||||
|
Immutable.Map<string, number>
|
||||||
|
>
|
||||||
|
)
|
||||||
|
.reverse()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
.map((day) => day.get('uses')!)
|
||||||
|
.toArray()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface HashtagProps {
|
||||||
|
className?: string;
|
||||||
|
description?: React.ReactNode;
|
||||||
|
history?: number[];
|
||||||
|
name: string;
|
||||||
|
people: number;
|
||||||
|
to: string;
|
||||||
|
uses?: number;
|
||||||
|
withGraph?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Hashtag: React.FC<HashtagProps> = ({
|
||||||
|
name,
|
||||||
|
to,
|
||||||
|
people,
|
||||||
|
uses,
|
||||||
|
history,
|
||||||
|
className,
|
||||||
|
description,
|
||||||
|
withGraph = true,
|
||||||
|
}) => (
|
||||||
|
<div className={classNames('trends__item', className)}>
|
||||||
|
<div className='trends__item__name'>
|
||||||
|
<Link to={to}>
|
||||||
|
{name ? (
|
||||||
|
<>
|
||||||
|
#<span>{name}</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Skeleton width={50} />
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{description ? (
|
||||||
|
<span>{description}</span>
|
||||||
|
) : typeof people !== 'undefined' ? (
|
||||||
|
<ShortNumber value={people} renderer={accountsCountRenderer} />
|
||||||
|
) : (
|
||||||
|
<Skeleton width={100} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{typeof uses !== 'undefined' && (
|
||||||
|
<div className='trends__item__current'>
|
||||||
|
<ShortNumber value={uses} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{withGraph && (
|
||||||
|
<div className='trends__item__sparkline'>
|
||||||
|
<SilentErrorBoundary>
|
||||||
|
<Sparklines
|
||||||
|
width={50}
|
||||||
|
height={28}
|
||||||
|
data={history ? history : Array.from(Array(7)).map(() => 0)}
|
||||||
|
>
|
||||||
|
<SparklinesCurve style={{ fill: 'none' }} />
|
||||||
|
</Sparklines>
|
||||||
|
</SilentErrorBoundary>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
|
@ -5,7 +5,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import Hashtag from 'mastodon/components/hashtag';
|
import { Hashtag } from 'mastodon/components/hashtag';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
lastStatusAt: { id: 'account.featured_tags.last_status_at', defaultMessage: 'Last post on {date}' },
|
lastStatusAt: { id: 'account.featured_tags.last_status_at', defaultMessage: 'Last post on {date}' },
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { debounce } from 'lodash';
|
||||||
|
|
||||||
import { expandFollowedHashtags, fetchFollowedHashtags } from 'mastodon/actions/tags';
|
import { expandFollowedHashtags, fetchFollowedHashtags } from 'mastodon/actions/tags';
|
||||||
import ColumnHeader from 'mastodon/components/column_header';
|
import ColumnHeader from 'mastodon/components/column_header';
|
||||||
import Hashtag from 'mastodon/components/hashtag';
|
import { Hashtag } from 'mastodon/components/hashtag';
|
||||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||||
import Column from 'mastodon/features/ui/components/column';
|
import Column from 'mastodon/features/ui/components/column';
|
||||||
|
|
||||||
|
|
|
@ -298,9 +298,9 @@ class LoginForm extends React.PureComponent {
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
autocomplete='off'
|
autoComplete='off'
|
||||||
autocapitalize='off'
|
autoCapitalize='off'
|
||||||
spellcheck='false'
|
spellCheck='false'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
|
<Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
|
||||||
|
|
|
@ -82,7 +82,7 @@ class NavigationPanel extends Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{banner &&
|
{banner &&
|
||||||
<div class='navigation-panel__banner'>
|
<div className='navigation-panel__banner'>
|
||||||
{banner}
|
{banner}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -612,7 +612,6 @@ class Video extends PureComponent {
|
||||||
aria-label={alt}
|
aria-label={alt}
|
||||||
title={alt}
|
title={alt}
|
||||||
lang={lang}
|
lang={lang}
|
||||||
volume={volume}
|
|
||||||
onClick={this.togglePlay}
|
onClick={this.togglePlay}
|
||||||
onKeyDown={this.handleVideoKeyDown}
|
onKeyDown={this.handleVideoKeyDown}
|
||||||
onPlay={this.handlePlay}
|
onPlay={this.handlePlay}
|
||||||
|
|
|
@ -499,6 +499,7 @@
|
||||||
"report_notification.open": "Ubrir informe",
|
"report_notification.open": "Ubrir informe",
|
||||||
"search.placeholder": "Buscar",
|
"search.placeholder": "Buscar",
|
||||||
"search.search_or_paste": "Buscar u apegar URL",
|
"search.search_or_paste": "Buscar u apegar URL",
|
||||||
|
"search_popout.full_text_search_logged_out_message": "Nomás disponible iniciando la sesión.",
|
||||||
"search_results.all": "Totz",
|
"search_results.all": "Totz",
|
||||||
"search_results.hashtags": "Etiquetas",
|
"search_results.hashtags": "Etiquetas",
|
||||||
"search_results.nothing_found": "No se podió trobar cosa pa estes termins de busqueda",
|
"search_results.nothing_found": "No se podió trobar cosa pa estes termins de busqueda",
|
||||||
|
|
|
@ -482,6 +482,7 @@
|
||||||
"onboarding.follows.lead": "La teva línia de temps inici només està a les teves mans. Com més gent segueixis, més activa i interessant serà. Aquests perfils poden ser un bon punt d'inici—sempre pots acabar deixant de seguir-los!:",
|
"onboarding.follows.lead": "La teva línia de temps inici només està a les teves mans. Com més gent segueixis, més activa i interessant serà. Aquests perfils poden ser un bon punt d'inici—sempre pots acabar deixant de seguir-los!:",
|
||||||
"onboarding.follows.title": "Personalitza la pantalla d'inci",
|
"onboarding.follows.title": "Personalitza la pantalla d'inci",
|
||||||
"onboarding.profile.discoverable": "Fes el meu perfil descobrible",
|
"onboarding.profile.discoverable": "Fes el meu perfil descobrible",
|
||||||
|
"onboarding.profile.discoverable_hint": "En acceptar d'ésser descobert a Mastodon els teus missatges poden aparèixer dins les tendències i els resultats de cerques, i el teu perfil es pot suggerir a qui tingui interessos semblants als teus.",
|
||||||
"onboarding.profile.display_name": "Nom que es mostrarà",
|
"onboarding.profile.display_name": "Nom que es mostrarà",
|
||||||
"onboarding.profile.display_name_hint": "El teu nom complet o el teu malnom…",
|
"onboarding.profile.display_name_hint": "El teu nom complet o el teu malnom…",
|
||||||
"onboarding.profile.lead": "Sempre ho pots completar més endavant a la configuració, on hi ha encara més opcions disponibles.",
|
"onboarding.profile.lead": "Sempre ho pots completar més endavant a la configuració, on hi ha encara més opcions disponibles.",
|
||||||
|
|
|
@ -606,7 +606,7 @@
|
||||||
"search.quick_action.status_search": "Publicaciones que coinciden con {x}",
|
"search.quick_action.status_search": "Publicaciones que coinciden con {x}",
|
||||||
"search.search_or_paste": "Buscar o pegar URL",
|
"search.search_or_paste": "Buscar o pegar URL",
|
||||||
"search_popout.full_text_search_disabled_message": "No disponible en {domain}.",
|
"search_popout.full_text_search_disabled_message": "No disponible en {domain}.",
|
||||||
"search_popout.full_text_search_logged_out_message": "Solo disponible si inicias sesión.",
|
"search_popout.full_text_search_logged_out_message": "Sólo disponible al iniciar sesión.",
|
||||||
"search_popout.language_code": "Código de idioma ISO",
|
"search_popout.language_code": "Código de idioma ISO",
|
||||||
"search_popout.options": "Opciones de búsqueda",
|
"search_popout.options": "Opciones de búsqueda",
|
||||||
"search_popout.quick_actions": "Acciones rápidas",
|
"search_popout.quick_actions": "Acciones rápidas",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"about.blocks": "کارسازهای نظارت شده",
|
"about.blocks": "کارسازهای نظارت شده",
|
||||||
"about.contact": "تماس:",
|
"about.contact": "تماس:",
|
||||||
"about.disclaimer": "ماستودون نرمافزار آزاد و یک شرکت غیر انتفاعی آلمانی با مسئولیت محدود است.",
|
"about.disclaimer": "ماستودون نرمافزار آزاد و نشان تجاری یک شرکت غیر انتفاعی با مسئولیت محدود آلمانی است.",
|
||||||
"about.domain_blocks.no_reason_available": "دلیلی موجود نیست",
|
"about.domain_blocks.no_reason_available": "دلیلی موجود نیست",
|
||||||
"about.domain_blocks.preamble": "ماستودون عموماً میگذارد محتوا را از از هر کارساز دیگری در دنیای شبکههای اجتماعی غیرمتمرکز دیده و با آنان برهمکنش داشته باشید. اینها استثناهایی هستند که روی این کارساز خاص وضع شدهاند.",
|
"about.domain_blocks.preamble": "ماستودون عموماً میگذارد محتوا را از از هر کارساز دیگری در دنیای شبکههای اجتماعی غیرمتمرکز دیده و با آنان برهمکنش داشته باشید. اینها استثناهایی هستند که روی این کارساز خاص وضع شدهاند.",
|
||||||
"about.domain_blocks.silenced.explanation": "عموماً نمایهها و محتوا از این کارساز را نمیبینید، مگر این که به طور خاص دنبالشان گشته یا با پی گیری، داوطلب دیدنشان شوید.",
|
"about.domain_blocks.silenced.explanation": "عموماً نمایهها و محتوا از این کارساز را نمیبینید، مگر این که به طور خاص دنبالشان گشته یا با پی گیری، داوطلب دیدنشان شوید.",
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
"account.blocked": "مسدود",
|
"account.blocked": "مسدود",
|
||||||
"account.browse_more_on_origin_server": "مرور بیشتر روی نمایهٔ اصلی",
|
"account.browse_more_on_origin_server": "مرور بیشتر روی نمایهٔ اصلی",
|
||||||
"account.cancel_follow_request": "رد کردن درخواست پیگیری",
|
"account.cancel_follow_request": "رد کردن درخواست پیگیری",
|
||||||
|
"account.copy": "رونوشت از پیوند به نمایه",
|
||||||
"account.direct": "اشارهٔ خصوصی به @{name}",
|
"account.direct": "اشارهٔ خصوصی به @{name}",
|
||||||
"account.disable_notifications": "آگاه کردن من هنگام فرستههای @{name} را متوقّف کن",
|
"account.disable_notifications": "آگاه کردن من هنگام فرستههای @{name} را متوقّف کن",
|
||||||
"account.domain_blocked": "دامنه مسدود شد",
|
"account.domain_blocked": "دامنه مسدود شد",
|
||||||
|
@ -191,6 +192,7 @@
|
||||||
"conversation.mark_as_read": "علامتگذاری به عنوان خوانده شده",
|
"conversation.mark_as_read": "علامتگذاری به عنوان خوانده شده",
|
||||||
"conversation.open": "دیدن گفتگو",
|
"conversation.open": "دیدن گفتگو",
|
||||||
"conversation.with": "با {names}",
|
"conversation.with": "با {names}",
|
||||||
|
"copy_icon_button.copied": "در بریدهدان رونوشت شد",
|
||||||
"copypaste.copied": "رونوشت شد",
|
"copypaste.copied": "رونوشت شد",
|
||||||
"copypaste.copy_to_clipboard": "رونوشت به تختهگیره",
|
"copypaste.copy_to_clipboard": "رونوشت به تختهگیره",
|
||||||
"directory.federated": "از کارسازهای شناختهشده",
|
"directory.federated": "از کارسازهای شناختهشده",
|
||||||
|
@ -486,6 +488,8 @@
|
||||||
"onboarding.profile.note_hint": "میتوانید افراد دیگر را @نامبردن یا #برچسب بزنید…",
|
"onboarding.profile.note_hint": "میتوانید افراد دیگر را @نامبردن یا #برچسب بزنید…",
|
||||||
"onboarding.profile.save_and_continue": "ذخیره کن و ادامه بده",
|
"onboarding.profile.save_and_continue": "ذخیره کن و ادامه بده",
|
||||||
"onboarding.profile.title": "تنظیم نمایه",
|
"onboarding.profile.title": "تنظیم نمایه",
|
||||||
|
"onboarding.profile.upload_avatar": "بازگذاری تصویر نمایه",
|
||||||
|
"onboarding.profile.upload_header": "بارگذاری تصویر سردر نمایه",
|
||||||
"onboarding.share.lead": "بگذارید افراد بدانند چگونه میتوانند در ماستادون بیابندتان!",
|
"onboarding.share.lead": "بگذارید افراد بدانند چگونه میتوانند در ماستادون بیابندتان!",
|
||||||
"onboarding.share.message": "من {username} روی #ماستودون هستم! مرا در {url} پیبگیرید",
|
"onboarding.share.message": "من {username} روی #ماستودون هستم! مرا در {url} پیبگیرید",
|
||||||
"onboarding.share.next_steps": "گامهای ممکن بعدی:",
|
"onboarding.share.next_steps": "گامهای ممکن بعدی:",
|
||||||
|
@ -600,6 +604,7 @@
|
||||||
"search.quick_action.status_search": "فرستههای جور با {x}",
|
"search.quick_action.status_search": "فرستههای جور با {x}",
|
||||||
"search.search_or_paste": "جستوجو یا جایگذاری نشانی",
|
"search.search_or_paste": "جستوجو یا جایگذاری نشانی",
|
||||||
"search_popout.full_text_search_disabled_message": "روی {domain} موجود نیست.",
|
"search_popout.full_text_search_disabled_message": "روی {domain} موجود نیست.",
|
||||||
|
"search_popout.full_text_search_logged_out_message": "تنها زمانی که وارد شدهاید دردسترس است.",
|
||||||
"search_popout.language_code": "کد زبان ایزو",
|
"search_popout.language_code": "کد زبان ایزو",
|
||||||
"search_popout.options": "گزینههای جستوجو",
|
"search_popout.options": "گزینههای جستوجو",
|
||||||
"search_popout.quick_actions": "کنشهای سریع",
|
"search_popout.quick_actions": "کنشهای سریع",
|
||||||
|
|
1
app/javascript/mastodon/locales/fil.json
Normal file
1
app/javascript/mastodon/locales/fil.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -13,7 +13,7 @@
|
||||||
"about.rules": "Kiszolgáló szabályai",
|
"about.rules": "Kiszolgáló szabályai",
|
||||||
"account.account_note_header": "Feljegyzés",
|
"account.account_note_header": "Feljegyzés",
|
||||||
"account.add_or_remove_from_list": "Hozzáadás vagy eltávolítás a listákról",
|
"account.add_or_remove_from_list": "Hozzáadás vagy eltávolítás a listákról",
|
||||||
"account.badges.bot": "Bot",
|
"account.badges.bot": "Automatizált",
|
||||||
"account.badges.group": "Csoport",
|
"account.badges.group": "Csoport",
|
||||||
"account.block": "@{name} letiltása",
|
"account.block": "@{name} letiltása",
|
||||||
"account.block_domain": "Domain blokkolása: {domain}",
|
"account.block_domain": "Domain blokkolása: {domain}",
|
||||||
|
@ -63,8 +63,8 @@
|
||||||
"account.share": "@{name} profiljának megosztása",
|
"account.share": "@{name} profiljának megosztása",
|
||||||
"account.show_reblogs": "@{name} megtolásainak mutatása",
|
"account.show_reblogs": "@{name} megtolásainak mutatása",
|
||||||
"account.statuses_counter": "{count, plural, one {{counter} Bejegyzés} other {{counter} Bejegyzés}}",
|
"account.statuses_counter": "{count, plural, one {{counter} Bejegyzés} other {{counter} Bejegyzés}}",
|
||||||
"account.unblock": "@{name} tiltásának feloldása",
|
"account.unblock": "@{name} letiltásának feloldása",
|
||||||
"account.unblock_domain": "{domain} domain tiltás feloldása",
|
"account.unblock_domain": "{domain} domain tiltásának feloldása",
|
||||||
"account.unblock_short": "Tiltás feloldása",
|
"account.unblock_short": "Tiltás feloldása",
|
||||||
"account.unendorse": "Ne jelenjen meg a profilodon",
|
"account.unendorse": "Ne jelenjen meg a profilodon",
|
||||||
"account.unfollow": "Követés megszüntetése",
|
"account.unfollow": "Követés megszüntetése",
|
||||||
|
@ -138,21 +138,21 @@
|
||||||
"compose.language.search": "Nyelv keresése...",
|
"compose.language.search": "Nyelv keresése...",
|
||||||
"compose.published.body": "A bejegyzés publikálásra került.",
|
"compose.published.body": "A bejegyzés publikálásra került.",
|
||||||
"compose.published.open": "Megnyitás",
|
"compose.published.open": "Megnyitás",
|
||||||
"compose.saved.body": "A bejegyzés mentésre került.",
|
"compose.saved.body": "A bejegyzés mentve.",
|
||||||
"compose_form.direct_message_warning_learn_more": "Tudj meg többet",
|
"compose_form.direct_message_warning_learn_more": "Tudj meg többet",
|
||||||
"compose_form.encryption_warning": "A bejegyzések Mastodonon nem használnak végpontok közötti titkosítást. Ne ossz meg semmilyen érzékeny információt Mastodonon.",
|
"compose_form.encryption_warning": "A bejegyzések a Mastodonon nem használnak végpontok közti titkosítást. Ne ossz meg semmilyen érzékeny információt a Mastodonon.",
|
||||||
"compose_form.hashtag_warning": "Ez a bejegyzésed nem fog megjelenni semmilyen hashtag alatt, mivel nem nyilvános. Csak a nyilvános bejegyzések kereshetők hashtaggel.",
|
"compose_form.hashtag_warning": "Ez a bejegyzésed nem fog megjelenni semmilyen hashtag alatt, mivel nem nyilvános. Csak a nyilvános bejegyzések kereshetők hashtaggel.",
|
||||||
"compose_form.lock_disclaimer": "A fiókod nincs {locked}. Bárki követni tud, hogy megtekintse a kizárólag követőknek szánt bejegyzéseket.",
|
"compose_form.lock_disclaimer": "A fiókod nincs {locked}. Bárki követni tud, hogy megtekintse a kizárólag követőknek szánt bejegyzéseket.",
|
||||||
"compose_form.lock_disclaimer.lock": "lezárva",
|
"compose_form.lock_disclaimer.lock": "zárolva",
|
||||||
"compose_form.placeholder": "Mi jár a fejedben?",
|
"compose_form.placeholder": "Mi jár a fejedben?",
|
||||||
"compose_form.poll.add_option": "Lehetőség hozzáadása",
|
"compose_form.poll.add_option": "Lehetőség hozzáadása",
|
||||||
"compose_form.poll.duration": "Szavazás időtartama",
|
"compose_form.poll.duration": "Szavazás időtartama",
|
||||||
"compose_form.poll.option_placeholder": "{number}. lehetőség",
|
"compose_form.poll.option_placeholder": "{number}. lehetőség",
|
||||||
"compose_form.poll.remove_option": "Lehetőség törlése",
|
"compose_form.poll.remove_option": "Lehetőség eltávolítása",
|
||||||
"compose_form.poll.switch_to_multiple": "Szavazás megváltoztatása több választásosra",
|
"compose_form.poll.switch_to_multiple": "Szavazás megváltoztatása több választásosra",
|
||||||
"compose_form.poll.switch_to_single": "Szavazás megváltoztatása egyetlen választásosra",
|
"compose_form.poll.switch_to_single": "Szavazás megváltoztatása egyetlen választásosra",
|
||||||
"compose_form.publish": "Közzététel",
|
"compose_form.publish": "Közzététel",
|
||||||
"compose_form.publish_form": "Közzététel",
|
"compose_form.publish_form": "Új bejegyzés",
|
||||||
"compose_form.publish_loud": "{publish}!",
|
"compose_form.publish_loud": "{publish}!",
|
||||||
"compose_form.save_changes": "Módosítások mentése",
|
"compose_form.save_changes": "Módosítások mentése",
|
||||||
"compose_form.sensitive.hide": "{count, plural, one {Média kényesnek jelölése} other {Média kényesnek jelölése}}",
|
"compose_form.sensitive.hide": "{count, plural, one {Média kényesnek jelölése} other {Média kényesnek jelölése}}",
|
||||||
|
@ -195,13 +195,13 @@
|
||||||
"copy_icon_button.copied": "A szöveg a vágólapra másolva",
|
"copy_icon_button.copied": "A szöveg a vágólapra másolva",
|
||||||
"copypaste.copied": "Másolva",
|
"copypaste.copied": "Másolva",
|
||||||
"copypaste.copy_to_clipboard": "Másolás vágólapra",
|
"copypaste.copy_to_clipboard": "Másolás vágólapra",
|
||||||
"directory.federated": "Az ismert fediverzumból",
|
"directory.federated": "Az ismert födiverzumból",
|
||||||
"directory.local": "Csak {domain} tartományból",
|
"directory.local": "Csak {domain} tartományból",
|
||||||
"directory.new_arrivals": "Új csatlakozók",
|
"directory.new_arrivals": "Új csatlakozók",
|
||||||
"directory.recently_active": "Nemrég aktív",
|
"directory.recently_active": "Nemrég aktív",
|
||||||
"disabled_account_banner.account_settings": "Fiókbeállítások",
|
"disabled_account_banner.account_settings": "Fiókbeállítások",
|
||||||
"disabled_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva.",
|
"disabled_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva.",
|
||||||
"dismissable_banner.community_timeline": "Ezek a legfrissebb nyilvános bejegyzések, amelyeket {domain} tartományban levő kiszolgáló fiókjait használó emberek tettek közzé.",
|
"dismissable_banner.community_timeline": "Ezek a legfrissebb nyilvános bejegyzések, amelyeket a(z) {domain} kiszolgáló fiókjait használó emberek tették közzé.",
|
||||||
"dismissable_banner.dismiss": "Elvetés",
|
"dismissable_banner.dismiss": "Elvetés",
|
||||||
"dismissable_banner.explore_links": "Jelenleg ezekről a hírekről beszélgetnek az ezen és a központosítás nélküli hálózat többi kiszolgálóján lévő emberek.",
|
"dismissable_banner.explore_links": "Jelenleg ezekről a hírekről beszélgetnek az ezen és a központosítás nélküli hálózat többi kiszolgálóján lévő emberek.",
|
||||||
"dismissable_banner.explore_statuses": "Ezek jelenleg népszerűvé váló bejegyzések a háló különböző szegleteiből. Az újabb vagy több megtolással rendelkező bejegyzéseket, illetve a kedvencnek jelöléssel rendelkezőeket rangsoroljuk előrébb.",
|
"dismissable_banner.explore_statuses": "Ezek jelenleg népszerűvé váló bejegyzések a háló különböző szegleteiből. Az újabb vagy több megtolással rendelkező bejegyzéseket, illetve a kedvencnek jelöléssel rendelkezőeket rangsoroljuk előrébb.",
|
||||||
|
@ -216,14 +216,14 @@
|
||||||
"emoji_button.food": "Étel és Ital",
|
"emoji_button.food": "Étel és Ital",
|
||||||
"emoji_button.label": "Emodzsi beszúrása",
|
"emoji_button.label": "Emodzsi beszúrása",
|
||||||
"emoji_button.nature": "Természet",
|
"emoji_button.nature": "Természet",
|
||||||
"emoji_button.not_found": "Nincsenek emodzsik!! (╯°□°)╯︵ ┻━┻",
|
"emoji_button.not_found": "Nem találhatók emodzsik",
|
||||||
"emoji_button.objects": "Tárgyak",
|
"emoji_button.objects": "Tárgyak",
|
||||||
"emoji_button.people": "Emberek",
|
"emoji_button.people": "Emberek",
|
||||||
"emoji_button.recent": "Gyakran használt",
|
"emoji_button.recent": "Gyakran használt",
|
||||||
"emoji_button.search": "Keresés...",
|
"emoji_button.search": "Keresés...",
|
||||||
"emoji_button.search_results": "Keresési találatok",
|
"emoji_button.search_results": "Keresési találatok",
|
||||||
"emoji_button.symbols": "Szimbólumok",
|
"emoji_button.symbols": "Szimbólumok",
|
||||||
"emoji_button.travel": "Utazás és Helyek",
|
"emoji_button.travel": "Utazás és helyek",
|
||||||
"empty_column.account_hides_collections": "Ez a felhasználó úgy döntött, hogy nem teszi elérhetővé ezt az információt.",
|
"empty_column.account_hides_collections": "Ez a felhasználó úgy döntött, hogy nem teszi elérhetővé ezt az információt.",
|
||||||
"empty_column.account_suspended": "Fiók felfüggesztve",
|
"empty_column.account_suspended": "Fiók felfüggesztve",
|
||||||
"empty_column.account_timeline": "Itt nincs bejegyzés!",
|
"empty_column.account_timeline": "Itt nincs bejegyzés!",
|
||||||
|
@ -245,7 +245,7 @@
|
||||||
"empty_column.mutes": "Még egy felhasználót sem némítottál le.",
|
"empty_column.mutes": "Még egy felhasználót sem némítottál le.",
|
||||||
"empty_column.notifications": "Jelenleg még nincsenek értesítéseid. Ha mások kapcsolatba lépnek veled, ezek itt lesznek láthatóak.",
|
"empty_column.notifications": "Jelenleg még nincsenek értesítéseid. Ha mások kapcsolatba lépnek veled, ezek itt lesznek láthatóak.",
|
||||||
"empty_column.public": "Jelenleg itt nincs semmi! Írj valamit nyilvánosan vagy kövess más kiszolgálón levő felhasználókat, hogy megtöltsd.",
|
"empty_column.public": "Jelenleg itt nincs semmi! Írj valamit nyilvánosan vagy kövess más kiszolgálón 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": "Egy kód- vagy böngészőkompatibilitási hiba miatt ez az oldal nem jeleníthető meg helyesen.",
|
||||||
"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ő kiegészítő vagy egy automatikus fordító okozza.",
|
"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ő kiegészítő 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": "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.",
|
"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.",
|
||||||
|
@ -278,13 +278,13 @@
|
||||||
"firehose.remote": "Egyéb kiszolgálók",
|
"firehose.remote": "Egyéb kiszolgálók",
|
||||||
"follow_request.authorize": "Hitelesítés",
|
"follow_request.authorize": "Hitelesítés",
|
||||||
"follow_request.reject": "Elutasítás",
|
"follow_request.reject": "Elutasítás",
|
||||||
"follow_requests.unlocked_explanation": "Bár a fiókod nincs zárolva, a(z) {domain} csapata úgy gondolta, hogy talán kézzel szeretnéd ellenőrizni a fiók követési kéréseit.",
|
"follow_requests.unlocked_explanation": "Bár a fiókod nincs zárolva, a(z) {domain} csapata úgy gondolta, hogy talán kézzel szeretnéd ellenőrizni ezen fiókok követési kéréseit.",
|
||||||
"followed_tags": "Követett hashtagek",
|
"followed_tags": "Követett hashtagek",
|
||||||
"footer.about": "Névjegy",
|
"footer.about": "Névjegy",
|
||||||
"footer.directory": "Profiltár",
|
"footer.directory": "Profiltár",
|
||||||
"footer.get_app": "Alkalmazás beszerzése",
|
"footer.get_app": "Alkalmazás beszerzése",
|
||||||
"footer.invite": "Emberek meghívása",
|
"footer.invite": "Emberek meghívása",
|
||||||
"footer.keyboard_shortcuts": "Billentyűparancsok",
|
"footer.keyboard_shortcuts": "Gyorsbillentyűk",
|
||||||
"footer.privacy_policy": "Adatvédelmi szabályzat",
|
"footer.privacy_policy": "Adatvédelmi szabályzat",
|
||||||
"footer.source_code": "Forráskód megtekintése",
|
"footer.source_code": "Forráskód megtekintése",
|
||||||
"footer.status": "Állapot",
|
"footer.status": "Állapot",
|
||||||
|
@ -347,13 +347,13 @@
|
||||||
"keyboard_shortcuts.favourite": "Bejegyzés kedvencnek jelölése",
|
"keyboard_shortcuts.favourite": "Bejegyzés kedvencnek jelölése",
|
||||||
"keyboard_shortcuts.favourites": "Kedvencek lista megnyitása",
|
"keyboard_shortcuts.favourites": "Kedvencek lista megnyitása",
|
||||||
"keyboard_shortcuts.federated": "Föderációs idővonal megnyitása",
|
"keyboard_shortcuts.federated": "Föderációs idővonal megnyitása",
|
||||||
"keyboard_shortcuts.heading": "Billentyűparancsok",
|
"keyboard_shortcuts.heading": "Gyorsbillentyűk",
|
||||||
"keyboard_shortcuts.home": "Saját idővonal megnyitása",
|
"keyboard_shortcuts.home": "Saját idővonal megnyitása",
|
||||||
"keyboard_shortcuts.hotkey": "Gyorsbillentyű",
|
"keyboard_shortcuts.hotkey": "Gyorsbillentyű",
|
||||||
"keyboard_shortcuts.legend": "jelmagyarázat megjelenítése",
|
"keyboard_shortcuts.legend": "jelmagyarázat megjelenítése",
|
||||||
"keyboard_shortcuts.local": "helyi idővonal megnyitása",
|
"keyboard_shortcuts.local": "Helyi idővonal megnyitása",
|
||||||
"keyboard_shortcuts.mention": "Szerző megemlítése",
|
"keyboard_shortcuts.mention": "Szerző megemlítése",
|
||||||
"keyboard_shortcuts.muted": "némított felhasználók listájának megnyitása",
|
"keyboard_shortcuts.muted": "Némított felhasználók listájának megnyitása",
|
||||||
"keyboard_shortcuts.my_profile": "Saját profil megnyitása",
|
"keyboard_shortcuts.my_profile": "Saját profil megnyitása",
|
||||||
"keyboard_shortcuts.notifications": "Értesítések oszlop megnyitása",
|
"keyboard_shortcuts.notifications": "Értesítések oszlop megnyitása",
|
||||||
"keyboard_shortcuts.open_media": "Média megnyitása",
|
"keyboard_shortcuts.open_media": "Média megnyitása",
|
||||||
|
@ -389,7 +389,7 @@
|
||||||
"lists.replies_policy.list": "A lista tagjai",
|
"lists.replies_policy.list": "A lista tagjai",
|
||||||
"lists.replies_policy.none": "Senki",
|
"lists.replies_policy.none": "Senki",
|
||||||
"lists.replies_policy.title": "Nekik mutassuk a válaszokat:",
|
"lists.replies_policy.title": "Nekik mutassuk a válaszokat:",
|
||||||
"lists.search": "Keresés a követett személyek között",
|
"lists.search": "Keresés a követett emberek között",
|
||||||
"lists.subheading": "Saját listák",
|
"lists.subheading": "Saját listák",
|
||||||
"load_pending": "{count, plural, one {# új elem} other {# új elem}}",
|
"load_pending": "{count, plural, one {# új elem} other {# új elem}}",
|
||||||
"loading_indicator.label": "Betöltés…",
|
"loading_indicator.label": "Betöltés…",
|
||||||
|
@ -399,7 +399,7 @@
|
||||||
"mute_modal.hide_notifications": "Rejtsük el a felhasználótól származó értesítéseket?",
|
"mute_modal.hide_notifications": "Rejtsük el a felhasználótól származó értesítéseket?",
|
||||||
"mute_modal.indefinite": "Határozatlan",
|
"mute_modal.indefinite": "Határozatlan",
|
||||||
"navigation_bar.about": "Névjegy",
|
"navigation_bar.about": "Névjegy",
|
||||||
"navigation_bar.advanced_interface": "Haladó webes felület engedélyezése",
|
"navigation_bar.advanced_interface": "Megnyitás a speciális webes felületben",
|
||||||
"navigation_bar.blocks": "Letiltott felhasználók",
|
"navigation_bar.blocks": "Letiltott felhasználók",
|
||||||
"navigation_bar.bookmarks": "Könyvjelzők",
|
"navigation_bar.bookmarks": "Könyvjelzők",
|
||||||
"navigation_bar.community_timeline": "Helyi idővonal",
|
"navigation_bar.community_timeline": "Helyi idővonal",
|
||||||
|
@ -411,9 +411,9 @@
|
||||||
"navigation_bar.explore": "Felfedezés",
|
"navigation_bar.explore": "Felfedezés",
|
||||||
"navigation_bar.favourites": "Kedvencek",
|
"navigation_bar.favourites": "Kedvencek",
|
||||||
"navigation_bar.filters": "Némított szavak",
|
"navigation_bar.filters": "Némított szavak",
|
||||||
"navigation_bar.follow_requests": "Követési kérelmek",
|
"navigation_bar.follow_requests": "Követési kérések",
|
||||||
"navigation_bar.followed_tags": "Követett hashtagek",
|
"navigation_bar.followed_tags": "Követett hashtagek",
|
||||||
"navigation_bar.follows_and_followers": "Követettek és követők",
|
"navigation_bar.follows_and_followers": "Követések és követők",
|
||||||
"navigation_bar.lists": "Listák",
|
"navigation_bar.lists": "Listák",
|
||||||
"navigation_bar.logout": "Kijelentkezés",
|
"navigation_bar.logout": "Kijelentkezés",
|
||||||
"navigation_bar.mutes": "Némított felhasználók",
|
"navigation_bar.mutes": "Némított felhasználók",
|
||||||
|
@ -449,7 +449,7 @@
|
||||||
"notifications.column_settings.follow_request": "Új követési kérelmek:",
|
"notifications.column_settings.follow_request": "Új követési kérelmek:",
|
||||||
"notifications.column_settings.mention": "Megemlítések:",
|
"notifications.column_settings.mention": "Megemlítések:",
|
||||||
"notifications.column_settings.poll": "Szavazási eredmények:",
|
"notifications.column_settings.poll": "Szavazási eredmények:",
|
||||||
"notifications.column_settings.push": "Push értesítések",
|
"notifications.column_settings.push": "Leküldéses értesítések",
|
||||||
"notifications.column_settings.reblog": "Megtolások:",
|
"notifications.column_settings.reblog": "Megtolások:",
|
||||||
"notifications.column_settings.show": "Megjelenítés az oszlopban",
|
"notifications.column_settings.show": "Megjelenítés az oszlopban",
|
||||||
"notifications.column_settings.sound": "Hang lejátszása",
|
"notifications.column_settings.sound": "Hang lejátszása",
|
||||||
|
@ -480,7 +480,7 @@
|
||||||
"onboarding.compose.template": "Üdvözlet, #Mastodon!",
|
"onboarding.compose.template": "Üdvözlet, #Mastodon!",
|
||||||
"onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.",
|
"onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.",
|
||||||
"onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:",
|
"onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:",
|
||||||
"onboarding.follows.title": "Népszerű a Mastodonon",
|
"onboarding.follows.title": "Szabd személyre a kezdőlapodat",
|
||||||
"onboarding.profile.discoverable": "Saját profil beállítása felfedezhetőként",
|
"onboarding.profile.discoverable": "Saját profil beállítása felfedezhetőként",
|
||||||
"onboarding.profile.discoverable_hint": "A Mastodonon a felfedezhetőség választása esetén a saját bejegyzéseid megjelenhetnek a keresési eredmények és a felkapott tartalmak között, valamint a profilod a hozzád hasonló érdeklődési körrel rendelkező embereknél is ajánlásra kerülhet.",
|
"onboarding.profile.discoverable_hint": "A Mastodonon a felfedezhetőség választása esetén a saját bejegyzéseid megjelenhetnek a keresési eredmények és a felkapott tartalmak között, valamint a profilod a hozzád hasonló érdeklődési körrel rendelkező embereknél is ajánlásra kerülhet.",
|
||||||
"onboarding.profile.display_name": "Megjelenített név",
|
"onboarding.profile.display_name": "Megjelenített név",
|
||||||
|
@ -499,14 +499,14 @@
|
||||||
"onboarding.start.lead": "Az új Mastodon-fiók használatra kész. Így hozhatod ki belőle a legtöbbet:",
|
"onboarding.start.lead": "Az új Mastodon-fiók használatra kész. Így hozhatod ki belőle a legtöbbet:",
|
||||||
"onboarding.start.skip": "Szeretnél előreugrani?",
|
"onboarding.start.skip": "Szeretnél előreugrani?",
|
||||||
"onboarding.start.title": "Ez sikerült!",
|
"onboarding.start.title": "Ez sikerült!",
|
||||||
"onboarding.steps.follow_people.body": "Te állítod össze a saját hírfolyamodat. Töltsd meg érdekes emberekkel.",
|
"onboarding.steps.follow_people.body": "A Mastodon az érdekes emberek követéséről szól.",
|
||||||
"onboarding.steps.follow_people.title": "{count, plural, one {egy ember} other {# ember}} követése",
|
"onboarding.steps.follow_people.title": "{count, plural, one {egy ember} other {# ember}} követése",
|
||||||
"onboarding.steps.publish_status.body": "Üdvözöljük a világot.",
|
"onboarding.steps.publish_status.body": "Üdvözöljük a világot.",
|
||||||
"onboarding.steps.publish_status.title": "Az első bejegyzés létrehozása",
|
"onboarding.steps.publish_status.title": "Az első bejegyzés létrehozása",
|
||||||
"onboarding.steps.setup_profile.body": "Mások nagyobb valószínűséggel lépnek kapcsolatba veled egy kitöltött profil esetén.",
|
"onboarding.steps.setup_profile.body": "Mások nagyobb valószínűséggel lépnek kapcsolatba veled egy kitöltött profil esetén.",
|
||||||
"onboarding.steps.setup_profile.title": "Profilod testreszabása",
|
"onboarding.steps.setup_profile.title": "Profilod testreszabása",
|
||||||
"onboarding.steps.share_profile.body": "Tudasd az ismerőseiddel, hogyan találhatnak meg a Mastodonon!",
|
"onboarding.steps.share_profile.body": "Tudasd az ismerőseiddel, hogyan találhatnak meg a Mastodonon",
|
||||||
"onboarding.steps.share_profile.title": "Profilod megosztása",
|
"onboarding.steps.share_profile.title": "Oszd meg a Mastodon profilodat",
|
||||||
"onboarding.tips.2fa": "<strong>Tudtad?</strong> A fiókod biztonságossá teheted, ha a fiók beállításaiban beállítod a kétlépcsős hitelesítést. Bármilyen választott TOTP alkalmazással működik, nincs szükség telefonszámra!",
|
"onboarding.tips.2fa": "<strong>Tudtad?</strong> A fiókod biztonságossá teheted, ha a fiók beállításaiban beállítod a kétlépcsős hitelesítést. Bármilyen választott TOTP alkalmazással működik, nincs szükség telefonszámra!",
|
||||||
"onboarding.tips.accounts_from_other_servers": "<strong>Tudtad?</strong> Mivel a Mastodon decentralizált, egyes profilok, amelyekkel találkozol, más kiszolgálókon lesznek tárolva. És mégis zökkenőmentesen kommunikálhatsz velük! A kiszolgáló a felhasználónevük második felében található!",
|
"onboarding.tips.accounts_from_other_servers": "<strong>Tudtad?</strong> Mivel a Mastodon decentralizált, egyes profilok, amelyekkel találkozol, más kiszolgálókon lesznek tárolva. És mégis zökkenőmentesen kommunikálhatsz velük! A kiszolgáló a felhasználónevük második felében található!",
|
||||||
"onboarding.tips.migration": "<strong>Tudtad?</strong> Ha úgy érzed, hogy a {domain} már nem jó kiszolgáló a számodra, átköltözhetsz egy másik Mastodon kiszolgálóra anélkül, hogy elveszítenéd a követőidet. Akár saját kiszolgálót is üzemeltethetsz!",
|
"onboarding.tips.migration": "<strong>Tudtad?</strong> Ha úgy érzed, hogy a {domain} már nem jó kiszolgáló a számodra, átköltözhetsz egy másik Mastodon kiszolgálóra anélkül, hogy elveszítenéd a követőidet. Akár saját kiszolgálót is üzemeltethetsz!",
|
||||||
|
|
|
@ -302,8 +302,8 @@
|
||||||
"hashtag.counter_by_accounts": "{count, plural, other {{counter} 명의 참여자}}",
|
"hashtag.counter_by_accounts": "{count, plural, other {{counter} 명의 참여자}}",
|
||||||
"hashtag.counter_by_uses": "{count, plural, other {{counter} 개의 게시물}}",
|
"hashtag.counter_by_uses": "{count, plural, other {{counter} 개의 게시물}}",
|
||||||
"hashtag.counter_by_uses_today": "오늘 {count, plural, other {{counter} 개의 게시물}}",
|
"hashtag.counter_by_uses_today": "오늘 {count, plural, other {{counter} 개의 게시물}}",
|
||||||
"hashtag.follow": "해시태그 팔로우",
|
"hashtag.follow": "팔로우",
|
||||||
"hashtag.unfollow": "해시태그 팔로우 해제",
|
"hashtag.unfollow": "팔로우 해제",
|
||||||
"hashtags.and_other": "…그리고 {count, plural,other {#개 더}}",
|
"hashtags.and_other": "…그리고 {count, plural,other {#개 더}}",
|
||||||
"home.actions.go_to_explore": "무엇이 유행인지 보기",
|
"home.actions.go_to_explore": "무엇이 유행인지 보기",
|
||||||
"home.actions.go_to_suggestions": "팔로우할 사람 찾기",
|
"home.actions.go_to_suggestions": "팔로우할 사람 찾기",
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"account.follows.empty": "Šis (-i) naudotojas (-a) dar nieko neseka.",
|
"account.follows.empty": "Šis (-i) naudotojas (-a) dar nieko neseka.",
|
||||||
"account.follows_you": "Seka tave",
|
"account.follows_you": "Seka tave",
|
||||||
"account.go_to_profile": "Eiti į profilį",
|
"account.go_to_profile": "Eiti į profilį",
|
||||||
"account.hide_reblogs": "Slėpti \"boosts\" iš @{name}",
|
"account.hide_reblogs": "Slėpti pakėlimus iš @{name}",
|
||||||
"account.in_memoriam": "Atminimui.",
|
"account.in_memoriam": "Atminimui.",
|
||||||
"account.joined_short": "Prisijungė",
|
"account.joined_short": "Prisijungė",
|
||||||
"account.languages": "Keisti prenumeruojamas kalbas",
|
"account.languages": "Keisti prenumeruojamas kalbas",
|
||||||
|
@ -49,19 +49,19 @@
|
||||||
"account.media": "Medija",
|
"account.media": "Medija",
|
||||||
"account.mention": "Paminėti @{name}",
|
"account.mention": "Paminėti @{name}",
|
||||||
"account.moved_to": "{name} nurodė, kad dabar jų nauja paskyra yra:",
|
"account.moved_to": "{name} nurodė, kad dabar jų nauja paskyra yra:",
|
||||||
"account.mute": "Užtildyti @{name}",
|
"account.mute": "Nutildyti @{name}",
|
||||||
"account.mute_notifications_short": "Nutildyti pranešimus",
|
"account.mute_notifications_short": "Nutildyti pranešimus",
|
||||||
"account.mute_short": "Nutildyti",
|
"account.mute_short": "Nutildyti",
|
||||||
"account.muted": "Užtildytas",
|
"account.muted": "Nutildytas",
|
||||||
"account.no_bio": "Nėra pateikto aprašymo.",
|
"account.no_bio": "Nėra pateikto aprašymo.",
|
||||||
"account.open_original_page": "Atidaryti originalinį tinklalapį",
|
"account.open_original_page": "Atidaryti originalinį puslapį",
|
||||||
"account.posts": "Įrašai",
|
"account.posts": "Įrašai",
|
||||||
"account.posts_with_replies": "Įrašai ir atsakymai",
|
"account.posts_with_replies": "Įrašai ir atsakymai",
|
||||||
"account.report": "Pranešti @{name}",
|
"account.report": "Pranešti @{name}",
|
||||||
"account.requested": "Laukiama patvirtinimo. Spausk, kad atšaukti sekimo užklausą.",
|
"account.requested": "Laukiama patvirtinimo. Spausk, kad atšaukti sekimo užklausą",
|
||||||
"account.requested_follow": "{name} paprašė tave sekti",
|
"account.requested_follow": "{name} paprašė tave sekti",
|
||||||
"account.share": "Bendrinti @{name} profilį",
|
"account.share": "Bendrinti @{name} profilį",
|
||||||
"account.show_reblogs": "Rodyti \"boosts\" iš @{name}",
|
"account.show_reblogs": "Rodyti pakėlimus iš @{name}",
|
||||||
"account.statuses_counter": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
|
"account.statuses_counter": "{count, plural, one {{counter} įrašas} few {{counter} įrašai} many {{counter} įrašo} other {{counter} įrašų}}",
|
||||||
"account.unblock": "Atblokuoti @{name}",
|
"account.unblock": "Atblokuoti @{name}",
|
||||||
"account.unblock_domain": "Atblokuoti domeną {domain}",
|
"account.unblock_domain": "Atblokuoti domeną {domain}",
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
"account.unmute_short": "Atitildyti",
|
"account.unmute_short": "Atitildyti",
|
||||||
"account_note.placeholder": "Spausk norėdamas (-a) pridėti pastabą",
|
"account_note.placeholder": "Spausk norėdamas (-a) pridėti pastabą",
|
||||||
"admin.dashboard.daily_retention": "Vartotojų išbuvimo rodiklis pagal dieną po registracijos",
|
"admin.dashboard.daily_retention": "Vartotojų išbuvimo rodiklis pagal dieną po registracijos",
|
||||||
"admin.dashboard.monthly_retention": "Vartotojų išbuvimo rodiklis pagal mėnesį po registracijos",
|
"admin.dashboard.monthly_retention": "Naudotojų išlaikymo rodiklis pagal mėnesį po registracijos",
|
||||||
"admin.dashboard.retention.average": "Vidurkis",
|
"admin.dashboard.retention.average": "Vidurkis",
|
||||||
"admin.dashboard.retention.cohort": "Registravimo mėnuo",
|
"admin.dashboard.retention.cohort": "Registravimo mėnuo",
|
||||||
"admin.dashboard.retention.cohort_size": "Nauji naudotojai",
|
"admin.dashboard.retention.cohort_size": "Nauji naudotojai",
|
||||||
|
@ -117,9 +117,9 @@
|
||||||
"column.favourites": "Mėgstamiausi",
|
"column.favourites": "Mėgstamiausi",
|
||||||
"column.firehose": "Tiesioginiai padavimai",
|
"column.firehose": "Tiesioginiai padavimai",
|
||||||
"column.follow_requests": "Sekti prašymus",
|
"column.follow_requests": "Sekti prašymus",
|
||||||
"column.home": "Pradžia",
|
"column.home": "Pagrindinis",
|
||||||
"column.lists": "Sąrašai",
|
"column.lists": "Sąrašai",
|
||||||
"column.mutes": "Užtildyti naudotojai",
|
"column.mutes": "Nutildyti naudotojai",
|
||||||
"column.notifications": "Pranešimai",
|
"column.notifications": "Pranešimai",
|
||||||
"column.pins": "Prisegti įrašai",
|
"column.pins": "Prisegti įrašai",
|
||||||
"column.public": "Federacinė laiko skalė",
|
"column.public": "Federacinė laiko skalė",
|
||||||
|
@ -141,13 +141,13 @@
|
||||||
"compose.saved.body": "Įrašas išsaugotas.",
|
"compose.saved.body": "Įrašas išsaugotas.",
|
||||||
"compose_form.direct_message_warning_learn_more": "Sužinoti daugiau",
|
"compose_form.direct_message_warning_learn_more": "Sužinoti daugiau",
|
||||||
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
|
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
|
||||||
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
|
"compose_form.hashtag_warning": "Šis įrašas nebus įtraukta į jokį saitažodį, nes ji nėra vieša. Tik viešų įrašų galima ieškoti pagal saitažodį.",
|
||||||
"compose_form.lock_disclaimer": "Jūsų paskyra nėra {locked}. Kiekvienas gali jus sekti ir peržiūrėti tik sekėjams skirtus įrašus.",
|
"compose_form.lock_disclaimer": "Tavo paskyra nėra {locked}. Bet kas gali sekti tave ir peržiūrėti tik sekėjams skirtus įrašus.",
|
||||||
"compose_form.lock_disclaimer.lock": "užrakinta",
|
"compose_form.lock_disclaimer.lock": "užrakinta",
|
||||||
"compose_form.placeholder": "Kas tavo mintyse?",
|
"compose_form.placeholder": "Kas tavo mintyse?",
|
||||||
"compose_form.poll.add_option": "Pridėti pasirinkimą",
|
"compose_form.poll.add_option": "Pridėti pasirinkimą",
|
||||||
"compose_form.poll.duration": "Apklausos trukmė",
|
"compose_form.poll.duration": "Apklausos trukmė",
|
||||||
"compose_form.poll.option_placeholder": "Pasirinkimas {number}",
|
"compose_form.poll.option_placeholder": "{number} pasirinkimas",
|
||||||
"compose_form.poll.remove_option": "Pašalinti šį pasirinkimą",
|
"compose_form.poll.remove_option": "Pašalinti šį pasirinkimą",
|
||||||
"compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų galima pasirinkti kelis pasirinkimus",
|
"compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų galima pasirinkti kelis pasirinkimus",
|
||||||
"compose_form.poll.switch_to_single": "Pakeisti apklausą, kad būtų galima pasirinkti vieną variantą",
|
"compose_form.poll.switch_to_single": "Pakeisti apklausą, kad būtų galima pasirinkti vieną variantą",
|
||||||
|
@ -180,29 +180,71 @@
|
||||||
"confirmations.logout.message": "Ar tikrai nori atsijungti?",
|
"confirmations.logout.message": "Ar tikrai nori atsijungti?",
|
||||||
"confirmations.mute.confirm": "Nutildyti",
|
"confirmations.mute.confirm": "Nutildyti",
|
||||||
"confirmations.mute.explanation": "Tai paslėps jų įrašus ir įrašus, kuriuose jie menėmi, tačiau jie vis tiek galės matyti tavo įrašus ir sekti.",
|
"confirmations.mute.explanation": "Tai paslėps jų įrašus ir įrašus, kuriuose jie menėmi, tačiau jie vis tiek galės matyti tavo įrašus ir sekti.",
|
||||||
|
"confirmations.mute.message": "Ar tikrai norite nutildyti {name}?",
|
||||||
|
"confirmations.redraft.confirm": "Ištrinti ir perrašyti",
|
||||||
"confirmations.reply.confirm": "Atsakyti",
|
"confirmations.reply.confirm": "Atsakyti",
|
||||||
"confirmations.reply.message": "Atsakant dabar, bus perrašyta metu kuriama žinutė. Ar tikrai nori tęsti?",
|
"confirmations.reply.message": "Atsakant dabar, bus perrašyta metu kuriama žinutė. Ar tikrai nori tęsti?",
|
||||||
"confirmations.unfollow.confirm": "Nebesekti",
|
"confirmations.unfollow.confirm": "Nebesekti",
|
||||||
|
"confirmations.unfollow.message": "Ar tikrai norite atsisakyti sekimo {name}?",
|
||||||
|
"conversation.delete": "Ištrinti pokalbį",
|
||||||
"conversation.mark_as_read": "Žymėti kaip skaitytą",
|
"conversation.mark_as_read": "Žymėti kaip skaitytą",
|
||||||
"conversation.open": "Peržiūrėti pokalbį",
|
"conversation.open": "Peržiūrėti pokalbį",
|
||||||
"conversation.with": "Su {names}",
|
"conversation.with": "Su {names}",
|
||||||
"copy_icon_button.copied": "Nukopijuota į iškarpinę",
|
"copy_icon_button.copied": "Nukopijuota į iškarpinę",
|
||||||
"copypaste.copied": "Nukopijuota",
|
"copypaste.copied": "Nukopijuota",
|
||||||
"copypaste.copy_to_clipboard": "Kopijuoti į iškarpinę",
|
"copypaste.copy_to_clipboard": "Kopijuoti į iškarpinę",
|
||||||
|
"directory.local": "Iš {domain} tik",
|
||||||
|
"directory.new_arrivals": "Naujos prekės",
|
||||||
|
"directory.recently_active": "Neseniai aktyvus",
|
||||||
"disabled_account_banner.account_settings": "Paskyros nustatymai",
|
"disabled_account_banner.account_settings": "Paskyros nustatymai",
|
||||||
|
"disabled_account_banner.text": "Jūsų paskyra {disabledAccount} šiuo metu yra išjungta.",
|
||||||
|
"dismissable_banner.dismiss": "Atmesti",
|
||||||
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||||
|
"dismissable_banner.explore_statuses": "Tai įrašai iš viso socialinio tinklo, kurie šiandien sulaukia vis daugiau dėmesio. Naujesni įrašai, turintys daugiau boosts ir mėgstamiausių įrašų, yra vertinami aukščiau.",
|
||||||
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
"embed.instructions": "Embed this status on your website by copying the code below.",
|
||||||
"embed.preview": "Štai kaip tai atrodys:",
|
"embed.preview": "Štai kaip tai atrodys:",
|
||||||
|
"emoji_button.activity": "Veikla",
|
||||||
|
"emoji_button.clear": "Išvalyti",
|
||||||
|
"emoji_button.custom": "Pasirinktinis",
|
||||||
|
"emoji_button.flags": "Vėliavos",
|
||||||
|
"emoji_button.food": "Maistas ir Gėrimai",
|
||||||
|
"emoji_button.label": "Įterpti veidelius",
|
||||||
|
"emoji_button.nature": "Gamta",
|
||||||
|
"emoji_button.not_found": "Nerasta jokių tinkamų jaustukų",
|
||||||
"emoji_button.objects": "Objektai",
|
"emoji_button.objects": "Objektai",
|
||||||
|
"emoji_button.people": "Žmonės",
|
||||||
|
"emoji_button.recent": "Dažniausiai naudojama",
|
||||||
"emoji_button.search": "Paieška...",
|
"emoji_button.search": "Paieška...",
|
||||||
|
"emoji_button.search_results": "Paieškos rezultatai",
|
||||||
|
"emoji_button.symbols": "Simboliai",
|
||||||
|
"emoji_button.travel": "Kelionės ir Vietos",
|
||||||
"empty_column.account_hides_collections": "Šis naudotojas (-a) pasirinko nepadaryti šią informaciją prieinamą",
|
"empty_column.account_hides_collections": "Šis naudotojas (-a) pasirinko nepadaryti šią informaciją prieinamą",
|
||||||
|
"empty_column.account_suspended": "Paskyra sustabdyta",
|
||||||
"empty_column.account_timeline": "No toots here!",
|
"empty_column.account_timeline": "No toots here!",
|
||||||
|
"empty_column.account_unavailable": "Profilis neprieinamas",
|
||||||
|
"empty_column.blocks": "Dar neužblokavote nė vieno naudotojo.",
|
||||||
"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": "You don't have any bookmarked toots yet. When you bookmark one, it will show up here.",
|
||||||
|
"empty_column.community": "Vietinė laiko juosta yra tuščia. Parašykite ką nors viešai, kad pradėtumėte veikti!",
|
||||||
|
"empty_column.direct": "Dar neturite jokių privačių paminėjimų. Kai išsiųsite arba gausite tokį pranešimą, jis bus rodomas čia.",
|
||||||
"empty_column.domain_blocks": "There are no hidden domains yet.",
|
"empty_column.domain_blocks": "There are no hidden domains yet.",
|
||||||
|
"empty_column.favourited_statuses": "Dar neturite mėgstamiausių įrašų. Kai vieną iš jų pamėgsite, jis bus rodomas čia.",
|
||||||
|
"empty_column.follow_requests": "Dar neturite jokių sekimo užklausų. Kai gausite tokį prašymą, jis bus rodomas čia.",
|
||||||
|
"empty_column.followed_tags": "Dar nesekėte jokių grotažymių. Kai tai padarysite, jie bus rodomi čia.",
|
||||||
"empty_column.hashtag": "Nėra nieko šiame saitažodyje kol kas.",
|
"empty_column.hashtag": "Nėra nieko šiame saitažodyje kol kas.",
|
||||||
"empty_column.home": "Your home timeline is empty! Follow more people to fill it up. {suggestions}",
|
"empty_column.home": "Your home timeline is empty! Follow more people to fill it up. {suggestions}",
|
||||||
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
|
"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": "Dar neturite jokių sąrašų. Kai jį sukursite, jis bus rodomas čia.",
|
||||||
|
"empty_column.mutes": "Dar nesate nutildę nė vieno naudotojo.",
|
||||||
|
"empty_column.notifications": "Dar neturite jokių pranešimų. Kai kiti žmonės su jumis bendraus, matysite tai čia.",
|
||||||
|
"empty_column.public": "Čia nieko nėra! Parašykite ką nors viešai arba rankiniu būdu sekite naudotojus iš kitų serverių, kad jį užpildytumėte",
|
||||||
|
"error.unexpected_crash.explanation": "Dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos šis puslapis negalėjo būti rodomas teisingai.",
|
||||||
|
"error.unexpected_crash.explanation_addons": "Šį puslapį nepavyko teisingai parodyti. Šią klaidą greičiausiai sukėlė naršyklės priedas arba automatinio vertimo įrankiai.",
|
||||||
|
"error.unexpected_crash.next_steps": "Pabandykite atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsite naudotis \"Mastodon\" naudodami kitą naršyklę arba vietinę programėlę.",
|
||||||
|
"error.unexpected_crash.next_steps_addons": "Pabandykite juos išjungti ir atnaujinti puslapį. Jei tai nepadeda, galbūt vis dar galėsite naudotis \"Mastodon\" naudodami kitą naršyklę arba vietinę programėlę.",
|
||||||
|
"errors.unexpected_crash.report_issue": "Pranešti apie triktį",
|
||||||
|
"explore.search_results": "Paieškos rezultatai",
|
||||||
|
"explore.suggested_follows": "Žmonės",
|
||||||
"explore.title": "Naršyti",
|
"explore.title": "Naršyti",
|
||||||
"explore.trending_links": "Naujienos",
|
"explore.trending_links": "Naujienos",
|
||||||
"explore.trending_statuses": "Įrašai",
|
"explore.trending_statuses": "Įrašai",
|
||||||
|
@ -304,7 +346,13 @@
|
||||||
"moved_to_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu yra išjungta, nes persikėlei į {movedToAccount}.",
|
"moved_to_account_banner.text": "Tavo paskyra {disabledAccount} šiuo metu yra išjungta, nes persikėlei į {movedToAccount}.",
|
||||||
"mute_modal.duration": "Trukmė",
|
"mute_modal.duration": "Trukmė",
|
||||||
"mute_modal.hide_notifications": "Slėpti šio naudotojo pranešimus?",
|
"mute_modal.hide_notifications": "Slėpti šio naudotojo pranešimus?",
|
||||||
|
"mute_modal.indefinite": "Neribotas",
|
||||||
|
"navigation_bar.about": "Apie",
|
||||||
|
"navigation_bar.advanced_interface": "Atidarykite išplėstinę žiniatinklio sąsają",
|
||||||
|
"navigation_bar.blocks": "Užblokuoti naudotojai",
|
||||||
|
"navigation_bar.bookmarks": "Žymės",
|
||||||
"navigation_bar.compose": "Compose new toot",
|
"navigation_bar.compose": "Compose new toot",
|
||||||
|
"navigation_bar.direct": "Privatūs paminėjimai",
|
||||||
"navigation_bar.discover": "Atrasti",
|
"navigation_bar.discover": "Atrasti",
|
||||||
"navigation_bar.domain_blocks": "Hidden domains",
|
"navigation_bar.domain_blocks": "Hidden domains",
|
||||||
"navigation_bar.edit_profile": "Redaguoti profilį",
|
"navigation_bar.edit_profile": "Redaguoti profilį",
|
||||||
|
@ -372,6 +420,7 @@
|
||||||
"notifications.permission_required": "Darbalaukio pranešimai nepasiekiami, nes nesuteiktas reikiamas leidimas.",
|
"notifications.permission_required": "Darbalaukio pranešimai nepasiekiami, nes nesuteiktas reikiamas leidimas.",
|
||||||
"notifications_permission_banner.enable": "Įjungti darbalaukio pranešimus",
|
"notifications_permission_banner.enable": "Įjungti darbalaukio pranešimus",
|
||||||
"notifications_permission_banner.how_to_control": "Jei norite gauti pranešimus, kai \"Mastodon\" nėra atidarytas, įjunkite darbalaukio pranešimus. Įjungę darbalaukio pranešimus, galite tiksliai valdyti, kokių tipų sąveikos generuoja darbalaukio pranešimus, naudodamiesi pirmiau esančiu mygtuku {icon}.",
|
"notifications_permission_banner.how_to_control": "Jei norite gauti pranešimus, kai \"Mastodon\" nėra atidarytas, įjunkite darbalaukio pranešimus. Įjungę darbalaukio pranešimus, galite tiksliai valdyti, kokių tipų sąveikos generuoja darbalaukio pranešimus, naudodamiesi pirmiau esančiu mygtuku {icon}.",
|
||||||
|
"notifications_permission_banner.title": "Niekada nieko nepraleiskite",
|
||||||
"onboarding.action.back": "Gražinkite mane atgal",
|
"onboarding.action.back": "Gražinkite mane atgal",
|
||||||
"onboarding.actions.back": "Gražinkite mane atgal",
|
"onboarding.actions.back": "Gražinkite mane atgal",
|
||||||
"onboarding.actions.go_to_explore": "See what's trending",
|
"onboarding.actions.go_to_explore": "See what's trending",
|
||||||
|
@ -394,8 +443,10 @@
|
||||||
"onboarding.share.lead": "Praneškite žmonėms, kaip jus rasti \"Mastodon\"!",
|
"onboarding.share.lead": "Praneškite žmonėms, kaip jus rasti \"Mastodon\"!",
|
||||||
"onboarding.share.message": "Aš {username} #Mastodon! Ateik sekti manęs adresu {url}",
|
"onboarding.share.message": "Aš {username} #Mastodon! Ateik sekti manęs adresu {url}",
|
||||||
"onboarding.share.next_steps": "Galimi kiti žingsniai:",
|
"onboarding.share.next_steps": "Galimi kiti žingsniai:",
|
||||||
|
"onboarding.share.title": "Bendrinkite savo profilį",
|
||||||
"onboarding.start.lead": "Dabar esi Mastodon dalis – unikalios decentralizuotos socialinės žiniasklaidos platformos, kurioje tu, o ne algoritmas, pats nustatai savo patirtį. Pradėkime tavo kelionę šioje naujoje socialinėje erdvėje:",
|
"onboarding.start.lead": "Dabar esi Mastodon dalis – unikalios decentralizuotos socialinės žiniasklaidos platformos, kurioje tu, o ne algoritmas, pats nustatai savo patirtį. Pradėkime tavo kelionę šioje naujoje socialinėje erdvėje:",
|
||||||
"onboarding.start.skip": "Want to skip right ahead?",
|
"onboarding.start.skip": "Want to skip right ahead?",
|
||||||
|
"onboarding.start.title": "Jums pavyko!",
|
||||||
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
|
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
|
||||||
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
|
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
|
||||||
"onboarding.steps.publish_status.body": "Say hello to the world.",
|
"onboarding.steps.publish_status.body": "Say hello to the world.",
|
||||||
|
@ -404,23 +455,46 @@
|
||||||
"onboarding.steps.setup_profile.title": "Customize your profile",
|
"onboarding.steps.setup_profile.title": "Customize your profile",
|
||||||
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
|
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
|
||||||
"onboarding.steps.share_profile.title": "Share your profile",
|
"onboarding.steps.share_profile.title": "Share your profile",
|
||||||
|
"picture_in_picture.restore": "Padėkite jį atgal",
|
||||||
|
"poll.closed": "Uždaryti",
|
||||||
|
"poll.refresh": "Atnaujinti",
|
||||||
|
"poll.reveal": "Peržiūrėti rezultatus",
|
||||||
"poll.vote": "Balsuoti",
|
"poll.vote": "Balsuoti",
|
||||||
"poll.voted": "Tu balsavai už šį atsakymą",
|
"poll.voted": "Tu balsavai už šį atsakymą",
|
||||||
"poll.votes": "{votes, plural, one {# balsas} few {# balsai} many {# balso} other {# balsų}}",
|
"poll.votes": "{votes, plural, one {# balsas} few {# balsai} many {# balso} other {# balsų}}",
|
||||||
|
"poll_button.add_poll": "Pridėti apklausą",
|
||||||
|
"poll_button.remove_poll": "Šalinti apklausą",
|
||||||
"privacy.change": "Adjust status privacy",
|
"privacy.change": "Adjust status privacy",
|
||||||
"privacy.direct.long": "Post to mentioned users only",
|
"privacy.direct.long": "Post to mentioned users only",
|
||||||
"privacy.direct.short": "Direct",
|
"privacy.direct.short": "Direct",
|
||||||
"privacy.private.long": "Post to followers only",
|
"privacy.private.long": "Post to followers only",
|
||||||
"privacy.private.short": "Followers-only",
|
"privacy.private.short": "Followers-only",
|
||||||
|
"privacy.public.long": "Visiems matomas",
|
||||||
|
"privacy.public.short": "Viešas",
|
||||||
"privacy.unlisted.long": "Matomas visiems, bet atsisakyta atradimo funkcijų",
|
"privacy.unlisted.long": "Matomas visiems, bet atsisakyta atradimo funkcijų",
|
||||||
"privacy.unlisted.short": "Neįtrauktas į sąrašą",
|
"privacy.unlisted.short": "Neįtrauktas į sąrašą",
|
||||||
"privacy_policy.last_updated": "Paskutinį kartą atnaujinta {date}",
|
"privacy_policy.last_updated": "Paskutinį kartą atnaujinta {date}",
|
||||||
|
"privacy_policy.title": "Privatumo politika",
|
||||||
"recommended": "Rekomenduojama",
|
"recommended": "Rekomenduojama",
|
||||||
|
"refresh": "Atnaujinti",
|
||||||
|
"regeneration_indicator.label": "Kraunasi…",
|
||||||
|
"relative_time.full.just_now": "ką tik",
|
||||||
"relative_time.hours": "{number} val.",
|
"relative_time.hours": "{number} val.",
|
||||||
"relative_time.just_now": "dabar",
|
"relative_time.just_now": "dabar",
|
||||||
"relative_time.minutes": "{number} min.",
|
"relative_time.minutes": "{number} min.",
|
||||||
"relative_time.seconds": "{number} sek.",
|
"relative_time.seconds": "{number} sek.",
|
||||||
"relative_time.today": "šiandien",
|
"relative_time.today": "šiandien",
|
||||||
|
"reply_indicator.cancel": "Atšaukti",
|
||||||
|
"report.block": "Blokuoti",
|
||||||
|
"report.categories.legal": "Legalus",
|
||||||
|
"report.categories.other": "Kita",
|
||||||
|
"report.categories.spam": "Šlamštas",
|
||||||
|
"report.categories.violation": "Turinys pažeidžia vieną ar daugiau serverio taisyklių",
|
||||||
|
"report.category.subtitle": "Pasirinkite tinkamiausią variantą",
|
||||||
|
"report.category.title_account": "profilis",
|
||||||
|
"report.category.title_status": "įrašas",
|
||||||
|
"report.close": "Atlikta",
|
||||||
|
"report.comment.title": "Ar yra dar kas nors, ką, jūsų manymu, turėtume žinoti?",
|
||||||
"report.mute_explanation": "Jų įrašų nematysi. Jie vis tiek gali tave sekti ir matyti įrašus, bet nežinos, kad jie nutildyti.",
|
"report.mute_explanation": "Jų įrašų nematysi. Jie vis tiek gali tave sekti ir matyti įrašus, bet nežinos, kad jie nutildyti.",
|
||||||
"report.next": "Tęsti",
|
"report.next": "Tęsti",
|
||||||
"report.placeholder": "Papildomi komentarai",
|
"report.placeholder": "Papildomi komentarai",
|
||||||
|
@ -454,6 +528,8 @@
|
||||||
"search_results.hashtags": "Saitažodžiai",
|
"search_results.hashtags": "Saitažodžiai",
|
||||||
"search_results.nothing_found": "Nepavyko rasti nieko pagal šiuos paieškos terminus.",
|
"search_results.nothing_found": "Nepavyko rasti nieko pagal šiuos paieškos terminus.",
|
||||||
"search_results.statuses": "Toots",
|
"search_results.statuses": "Toots",
|
||||||
|
"server_banner.about_active_users": "Žmonės, kurie naudojosi šiuo serveriu per pastarąsias 30 dienų (mėnesio aktyvūs naudotojai)",
|
||||||
|
"server_banner.active_users": "aktyvūs naudotojai",
|
||||||
"sign_in_banner.sign_in": "Prisijungimas",
|
"sign_in_banner.sign_in": "Prisijungimas",
|
||||||
"sign_in_banner.text": "Prisijunk, kad galėtum sekti profilius arba saitažodžius, mėgsti, bendrinti ir atsakyti į įrašus. Taip pat gali bendrauti iš savo paskyros kitame serveryje.",
|
"sign_in_banner.text": "Prisijunk, kad galėtum sekti profilius arba saitažodžius, mėgsti, bendrinti ir atsakyti į įrašus. Taip pat gali bendrauti iš savo paskyros kitame serveryje.",
|
||||||
"status.admin_status": "Open this status in the moderation interface",
|
"status.admin_status": "Open this status in the moderation interface",
|
||||||
|
|
1
app/javascript/mastodon/locales/ne.json
Normal file
1
app/javascript/mastodon/locales/ne.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
1
app/javascript/mastodon/locales/ry.json
Normal file
1
app/javascript/mastodon/locales/ry.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -14,6 +14,7 @@
|
||||||
"account.badges.group": "Grupu",
|
"account.badges.group": "Grupu",
|
||||||
"account.block": "Bloca @{name}",
|
"account.block": "Bloca @{name}",
|
||||||
"account.block_domain": "Bloca su domìniu {domain}",
|
"account.block_domain": "Bloca su domìniu {domain}",
|
||||||
|
"account.block_short": "Bloca",
|
||||||
"account.blocked": "Blocadu",
|
"account.blocked": "Blocadu",
|
||||||
"account.browse_more_on_origin_server": "Esplora de prus in su profilu originale",
|
"account.browse_more_on_origin_server": "Esplora de prus in su profilu originale",
|
||||||
"account.cancel_follow_request": "Withdraw follow request",
|
"account.cancel_follow_request": "Withdraw follow request",
|
||||||
|
@ -31,17 +32,20 @@
|
||||||
"account.follows.empty": "Custa persone non sighit ancora a nemos.",
|
"account.follows.empty": "Custa persone non sighit ancora a nemos.",
|
||||||
"account.follows_you": "Ti sighit",
|
"account.follows_you": "Ti sighit",
|
||||||
"account.hide_reblogs": "Cua is cumpartziduras de @{name}",
|
"account.hide_reblogs": "Cua is cumpartziduras de @{name}",
|
||||||
|
"account.in_memoriam": "In memoriam.",
|
||||||
"account.joined_short": "At aderidu",
|
"account.joined_short": "At aderidu",
|
||||||
"account.link_verified_on": "Sa propiedade de custu ligòngiu est istada controllada su {date}",
|
"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.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.media": "Cuntenutu multimediale",
|
||||||
"account.mention": "Mèntova a @{name}",
|
"account.mention": "Mèntova a @{name}",
|
||||||
"account.mute": "Pone a @{name} a sa muda",
|
"account.mute": "Pone a @{name} a sa muda",
|
||||||
|
"account.mute_short": "A sa muda",
|
||||||
"account.muted": "A sa muda",
|
"account.muted": "A sa muda",
|
||||||
"account.posts": "Publicatziones",
|
"account.posts": "Publicatziones",
|
||||||
"account.posts_with_replies": "Publicatziones e rispostas",
|
"account.posts_with_replies": "Publicatziones e rispostas",
|
||||||
"account.report": "Signala @{name}",
|
"account.report": "Signala @{name}",
|
||||||
"account.requested": "Abetende s'aprovatzione. Incarca pro annullare sa rechesta de sighidura",
|
"account.requested": "Abetende s'aprovatzione. Incarca pro annullare sa rechesta de sighidura",
|
||||||
|
"account.requested_follow": "{name} at dimandadu de ti sighire",
|
||||||
"account.share": "Cumpartzi su profilu de @{name}",
|
"account.share": "Cumpartzi su profilu de @{name}",
|
||||||
"account.show_reblogs": "Ammustra is cumpartziduras de @{name}",
|
"account.show_reblogs": "Ammustra is cumpartziduras de @{name}",
|
||||||
"account.statuses_counter": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}}",
|
"account.statuses_counter": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}}",
|
||||||
|
@ -106,6 +110,7 @@
|
||||||
"compose_form.publish": "Pùblica",
|
"compose_form.publish": "Pùblica",
|
||||||
"compose_form.publish_form": "Publish",
|
"compose_form.publish_form": "Publish",
|
||||||
"compose_form.publish_loud": "{publish}!",
|
"compose_form.publish_loud": "{publish}!",
|
||||||
|
"compose_form.save_changes": "Sarva is modìficas",
|
||||||
"compose_form.sensitive.hide": "{count, plural, one {Marca elementu multimediale comente a sensìbile} other {Marca elementos multimediales comente sensìbiles}}",
|
"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.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.sensitive.unmarked": "{count, plural, one {Elementu multimediale non marcadu comente a sensìbile} other {Elementos multimediales non marcados comente a sensìbiles}}",
|
||||||
|
@ -122,6 +127,7 @@
|
||||||
"confirmations.delete_list.message": "Seguru chi boles cantzellare custa lista in manera permanente?",
|
"confirmations.delete_list.message": "Seguru chi boles cantzellare custa lista in manera permanente?",
|
||||||
"confirmations.domain_block.confirm": "Bloca totu su domìniu",
|
"confirmations.domain_block.confirm": "Bloca totu su domìniu",
|
||||||
"confirmations.domain_block.message": "Boles de seguru, ma a beru a beru, blocare {domain}? 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.domain_block.message": "Boles de seguru, ma a beru a beru, blocare {domain}? 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.edit.confirm": "Modìfica",
|
||||||
"confirmations.logout.confirm": "Essi·nche",
|
"confirmations.logout.confirm": "Essi·nche",
|
||||||
"confirmations.logout.message": "Seguru chi boles essire?",
|
"confirmations.logout.message": "Seguru chi boles essire?",
|
||||||
"confirmations.mute.confirm": "A sa muda",
|
"confirmations.mute.confirm": "A sa muda",
|
||||||
|
@ -140,6 +146,7 @@
|
||||||
"directory.local": "Isceti dae {domain}",
|
"directory.local": "Isceti dae {domain}",
|
||||||
"directory.new_arrivals": "Arribos noos",
|
"directory.new_arrivals": "Arribos noos",
|
||||||
"directory.recently_active": "Cun atividade dae pagu",
|
"directory.recently_active": "Cun atividade dae pagu",
|
||||||
|
"disabled_account_banner.account_settings": "Cunfiguratziones de su contu",
|
||||||
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||||
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||||
"embed.instructions": "Inserta custa publicatzione in su situ web tuo copiende su còdighe de suta.",
|
"embed.instructions": "Inserta custa publicatzione in su situ web tuo copiende su còdighe de suta.",
|
||||||
|
@ -180,13 +187,19 @@
|
||||||
"errors.unexpected_crash.copy_stacktrace": "Còpia stacktrace in punta de billete",
|
"errors.unexpected_crash.copy_stacktrace": "Còpia stacktrace in punta de billete",
|
||||||
"errors.unexpected_crash.report_issue": "Sinnala unu problema",
|
"errors.unexpected_crash.report_issue": "Sinnala unu problema",
|
||||||
"explore.search_results": "Resurtados de sa chirca",
|
"explore.search_results": "Resurtados de sa chirca",
|
||||||
|
"explore.suggested_follows": "Gente",
|
||||||
|
"explore.trending_statuses": "Publicatziones",
|
||||||
|
"explore.trending_tags": "Etichetas",
|
||||||
"filter_modal.select_filter.expired": "iscadidu",
|
"filter_modal.select_filter.expired": "iscadidu",
|
||||||
|
"firehose.all": "Totus",
|
||||||
"follow_request.authorize": "Autoriza",
|
"follow_request.authorize": "Autoriza",
|
||||||
"follow_request.reject": "Refuda",
|
"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.",
|
"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.",
|
||||||
"footer.about": "Informatziones",
|
"footer.about": "Informatziones",
|
||||||
"footer.invite": "Invita gente",
|
"footer.invite": "Invita gente",
|
||||||
|
"footer.keyboard_shortcuts": "Incurtzaduras de tecladu",
|
||||||
"footer.privacy_policy": "Polìtica de riservadesa",
|
"footer.privacy_policy": "Polìtica de riservadesa",
|
||||||
|
"footer.status": "Istadu",
|
||||||
"generic.saved": "Sarvadu",
|
"generic.saved": "Sarvadu",
|
||||||
"getting_started.heading": "Comente cumintzare",
|
"getting_started.heading": "Comente cumintzare",
|
||||||
"hashtag.column_header.tag_mode.all": "e {additional}",
|
"hashtag.column_header.tag_mode.all": "e {additional}",
|
||||||
|
@ -263,6 +276,7 @@
|
||||||
"lists.search": "Chirca intre sa gente chi ses sighende",
|
"lists.search": "Chirca intre sa gente chi ses sighende",
|
||||||
"lists.subheading": "Is listas tuas",
|
"lists.subheading": "Is listas tuas",
|
||||||
"load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}",
|
"load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}",
|
||||||
|
"loading_indicator.label": "Carrighende…",
|
||||||
"media_gallery.toggle_visible": "Cua {number, plural, one {immàgine} other {immàgines}}",
|
"media_gallery.toggle_visible": "Cua {number, plural, one {immàgine} other {immàgines}}",
|
||||||
"mute_modal.duration": "Durada",
|
"mute_modal.duration": "Durada",
|
||||||
"mute_modal.hide_notifications": "Boles cuare is notìficas de custa persone?",
|
"mute_modal.hide_notifications": "Boles cuare is notìficas de custa persone?",
|
||||||
|
@ -288,6 +302,7 @@
|
||||||
"navigation_bar.search": "Chirca",
|
"navigation_bar.search": "Chirca",
|
||||||
"navigation_bar.security": "Seguresa",
|
"navigation_bar.security": "Seguresa",
|
||||||
"not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.",
|
"not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.",
|
||||||
|
"notification.favourite": "{name} at marcadu comente a preferidu s'istadu tuo",
|
||||||
"notification.follow": "{name} ti sighit",
|
"notification.follow": "{name} ti sighit",
|
||||||
"notification.follow_request": "{name} at dimandadu de ti sighire",
|
"notification.follow_request": "{name} at dimandadu de ti sighire",
|
||||||
"notification.mention": "{name} t'at mentovadu",
|
"notification.mention": "{name} t'at mentovadu",
|
||||||
|
@ -328,6 +343,8 @@
|
||||||
"onboarding.actions.go_to_home": "Go to your home feed",
|
"onboarding.actions.go_to_home": "Go to your home feed",
|
||||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||||
"onboarding.follows.title": "Popular on Mastodon",
|
"onboarding.follows.title": "Popular on Mastodon",
|
||||||
|
"onboarding.profile.display_name": "Nòmine visìbile",
|
||||||
|
"onboarding.profile.note": "Biografia",
|
||||||
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
|
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
|
||||||
"onboarding.start.skip": "Want to skip right ahead?",
|
"onboarding.start.skip": "Want to skip right ahead?",
|
||||||
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
|
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
|
||||||
|
@ -344,6 +361,7 @@
|
||||||
"poll.total_votes": "{count, plural, one {# votu} other {# votos}}",
|
"poll.total_votes": "{count, plural, one {# votu} other {# votos}}",
|
||||||
"poll.vote": "Vota",
|
"poll.vote": "Vota",
|
||||||
"poll.voted": "As votadu custa risposta",
|
"poll.voted": "As votadu custa risposta",
|
||||||
|
"poll.votes": "{votes, plural, one {# votu} other {# votos}}",
|
||||||
"poll_button.add_poll": "Agiunghe unu sondàgiu",
|
"poll_button.add_poll": "Agiunghe unu sondàgiu",
|
||||||
"poll_button.remove_poll": "Cantzella su sondàgiu",
|
"poll_button.remove_poll": "Cantzella su sondàgiu",
|
||||||
"privacy.change": "Modìfica s'istadu de riservadesa",
|
"privacy.change": "Modìfica s'istadu de riservadesa",
|
||||||
|
@ -353,25 +371,41 @@
|
||||||
"privacy.private.short": "Followers-only",
|
"privacy.private.short": "Followers-only",
|
||||||
"privacy.public.short": "Pùblicu",
|
"privacy.public.short": "Pùblicu",
|
||||||
"privacy.unlisted.short": "Esclùidu de sa lista",
|
"privacy.unlisted.short": "Esclùidu de sa lista",
|
||||||
|
"recommended": "Cussigiadu",
|
||||||
"refresh": "Atualiza",
|
"refresh": "Atualiza",
|
||||||
"regeneration_indicator.label": "Carrighende…",
|
"regeneration_indicator.label": "Carrighende…",
|
||||||
"regeneration_indicator.sublabel": "Preparende sa lìnia de tempus printzipale tua.",
|
"regeneration_indicator.sublabel": "Preparende sa lìnia de tempus printzipale tua.",
|
||||||
"relative_time.days": "{number} dies a oe",
|
"relative_time.days": "{number} dies a oe",
|
||||||
|
"relative_time.full.just_now": "immoe etotu",
|
||||||
"relative_time.hours": "{number} oras a immoe",
|
"relative_time.hours": "{number} oras a immoe",
|
||||||
"relative_time.just_now": "immoe",
|
"relative_time.just_now": "immoe",
|
||||||
"relative_time.minutes": "{number} minutos a immoe",
|
"relative_time.minutes": "{number} minutos a immoe",
|
||||||
"relative_time.seconds": "{number} segundos a immoe",
|
"relative_time.seconds": "{number} segundos a immoe",
|
||||||
"relative_time.today": "oe",
|
"relative_time.today": "oe",
|
||||||
"reply_indicator.cancel": "Annulla",
|
"reply_indicator.cancel": "Annulla",
|
||||||
|
"report.block": "Bloca",
|
||||||
|
"report.categories.other": "Àteru",
|
||||||
|
"report.category.title_account": "profilu",
|
||||||
|
"report.category.title_status": "publicatzione",
|
||||||
|
"report.close": "Fatu",
|
||||||
"report.forward": "Torra a imbiare a {target}",
|
"report.forward": "Torra a imbiare a {target}",
|
||||||
"report.forward_hint": "Custu contu est de un'àteru serbidore. Ddi 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.mute": "A sa muda",
|
||||||
|
"report.next": "Imbeniente",
|
||||||
"report.placeholder": "Cummentos additzionales",
|
"report.placeholder": "Cummentos additzionales",
|
||||||
"report.submit": "Imbia",
|
"report.submit": "Imbia",
|
||||||
"report.target": "Informende de {target}",
|
"report.target": "Informende de {target}",
|
||||||
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
|
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
|
||||||
|
"report_notification.categories.other": "Àteru",
|
||||||
"search.placeholder": "Chirca",
|
"search.placeholder": "Chirca",
|
||||||
|
"search_popout.user": "utente",
|
||||||
|
"search_results.accounts": "Profilos",
|
||||||
|
"search_results.all": "Totus",
|
||||||
"search_results.hashtags": "Etichetas",
|
"search_results.hashtags": "Etichetas",
|
||||||
"search_results.statuses": "Publicatziones",
|
"search_results.statuses": "Publicatziones",
|
||||||
|
"server_banner.administered_by": "Amministradu dae:",
|
||||||
|
"server_banner.learn_more": "Àteras informatziones",
|
||||||
|
"server_banner.server_stats": "Istatìsticas de su serbidore:",
|
||||||
"sign_in_banner.sign_in": "Sign in",
|
"sign_in_banner.sign_in": "Sign in",
|
||||||
"status.admin_account": "Aberi s'interfache de moderatzione pro @{name}",
|
"status.admin_account": "Aberi s'interfache de moderatzione pro @{name}",
|
||||||
"status.admin_status": "Aberi custa publicatzione in s'interfache de moderatzione",
|
"status.admin_status": "Aberi custa publicatzione in s'interfache de moderatzione",
|
||||||
|
@ -382,6 +416,7 @@
|
||||||
"status.copy": "Còpia su ligòngiu a sa publicatzione tua",
|
"status.copy": "Còpia su ligòngiu a sa publicatzione tua",
|
||||||
"status.delete": "Cantzella",
|
"status.delete": "Cantzella",
|
||||||
"status.detailed_status": "Visualizatzione de detàlliu de arresonada",
|
"status.detailed_status": "Visualizatzione de detàlliu de arresonada",
|
||||||
|
"status.edit": "Modìfica",
|
||||||
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
|
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
|
||||||
"status.embed": "Afissa",
|
"status.embed": "Afissa",
|
||||||
"status.filtered": "Filtradu",
|
"status.filtered": "Filtradu",
|
||||||
|
@ -413,6 +448,7 @@
|
||||||
"status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}",
|
"status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}",
|
||||||
"status.unmute_conversation": "Torra a ativare s'arresonada",
|
"status.unmute_conversation": "Torra a ativare s'arresonada",
|
||||||
"status.unpin": "Boga dae pitzu de su profilu",
|
"status.unpin": "Boga dae pitzu de su profilu",
|
||||||
|
"subscribed_languages.save": "Sarva is modìficas",
|
||||||
"tabs_bar.home": "Printzipale",
|
"tabs_bar.home": "Printzipale",
|
||||||
"tabs_bar.notifications": "Notìficas",
|
"tabs_bar.notifications": "Notìficas",
|
||||||
"time_remaining.days": "{number, plural, one {abarrat # die} other {abarrant # dies}}",
|
"time_remaining.days": "{number, plural, one {abarrat # die} other {abarrant # dies}}",
|
||||||
|
|
|
@ -391,6 +391,7 @@
|
||||||
"lists.search": "Vyhľadávaj medzi užívateľmi, ktorých sleduješ",
|
"lists.search": "Vyhľadávaj medzi užívateľmi, ktorých sleduješ",
|
||||||
"lists.subheading": "Tvoje zoznamy",
|
"lists.subheading": "Tvoje zoznamy",
|
||||||
"load_pending": "{count, plural, one {# nová položka} other {# nových položiek}}",
|
"load_pending": "{count, plural, one {# nová položka} other {# nových položiek}}",
|
||||||
|
"loading_indicator.label": "Načítam…",
|
||||||
"media_gallery.toggle_visible": "Zapni/Vypni viditeľnosť",
|
"media_gallery.toggle_visible": "Zapni/Vypni viditeľnosť",
|
||||||
"moved_to_account_banner.text": "Vaše konto {disabledAccount} je momentálne zablokované, pretože ste sa presunuli na {movedToAccount}.",
|
"moved_to_account_banner.text": "Vaše konto {disabledAccount} je momentálne zablokované, pretože ste sa presunuli na {movedToAccount}.",
|
||||||
"mute_modal.duration": "Trvanie",
|
"mute_modal.duration": "Trvanie",
|
||||||
|
@ -480,6 +481,14 @@
|
||||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||||
"onboarding.follows.title": "Popular on Mastodon",
|
"onboarding.follows.title": "Popular on Mastodon",
|
||||||
"onboarding.profile.discoverable": "Urob môj profil objaviteľný",
|
"onboarding.profile.discoverable": "Urob môj profil objaviteľný",
|
||||||
|
"onboarding.profile.display_name": "Zobrazované meno",
|
||||||
|
"onboarding.profile.display_name_hint": "Tvoje plné meno, alebo tvoje zábavné meno…",
|
||||||
|
"onboarding.profile.lead": "Toto môžeš vždy dokončiť neskôr v nastaveniach, kde je dostupných ešte viac volieb na prispôsobenie.",
|
||||||
|
"onboarding.profile.note": "O tebe",
|
||||||
|
"onboarding.profile.note_hint": "Môžeš @spomenúť iných ľudí, alebo #haštagy…",
|
||||||
|
"onboarding.profile.save_and_continue": "Ulož a pokračuj",
|
||||||
|
"onboarding.profile.upload_avatar": "Nahraj profilový obrázok",
|
||||||
|
"onboarding.profile.upload_header": "Nahraj profilové záhlavie",
|
||||||
"onboarding.share.lead": "Daj ľudom vedieť, ako ťa môžu na Mastodone nájsť!",
|
"onboarding.share.lead": "Daj ľudom vedieť, ako ťa môžu na Mastodone nájsť!",
|
||||||
"onboarding.share.message": "Na Mastodone som {username}. Príď ma nasledovať na {url}",
|
"onboarding.share.message": "Na Mastodone som {username}. Príď ma nasledovať na {url}",
|
||||||
"onboarding.share.next_steps": "Ďalšie možné kroky:",
|
"onboarding.share.next_steps": "Ďalšie možné kroky:",
|
||||||
|
@ -594,6 +603,7 @@
|
||||||
"search.quick_action.status_search": "Príspevky zodpovedajúce {x}",
|
"search.quick_action.status_search": "Príspevky zodpovedajúce {x}",
|
||||||
"search.search_or_paste": "Hľadaj, alebo vlož URL adresu",
|
"search.search_or_paste": "Hľadaj, alebo vlož URL adresu",
|
||||||
"search_popout.full_text_search_disabled_message": "Nie je k dispozícii v doméne {domain}.",
|
"search_popout.full_text_search_disabled_message": "Nie je k dispozícii v doméne {domain}.",
|
||||||
|
"search_popout.full_text_search_logged_out_message": "Dostupné iba keď si prihlásený/á.",
|
||||||
"search_popout.language_code": "ISO kód jazyka",
|
"search_popout.language_code": "ISO kód jazyka",
|
||||||
"search_popout.options": "Možnosti vyhľadávania",
|
"search_popout.options": "Možnosti vyhľadávania",
|
||||||
"search_popout.quick_actions": "Rýchle akcie",
|
"search_popout.quick_actions": "Rýchle akcie",
|
||||||
|
|
|
@ -606,6 +606,7 @@
|
||||||
"search.quick_action.status_search": "Postime me përputhje me {x}",
|
"search.quick_action.status_search": "Postime me përputhje me {x}",
|
||||||
"search.search_or_paste": "Kërkoni, ose hidhni një URL",
|
"search.search_or_paste": "Kërkoni, ose hidhni një URL",
|
||||||
"search_popout.full_text_search_disabled_message": "Jo i passhëm në {domain}.",
|
"search_popout.full_text_search_disabled_message": "Jo i passhëm në {domain}.",
|
||||||
|
"search_popout.full_text_search_logged_out_message": "E përdorshme vetëm kur keni bërë hyrjen në llogari.",
|
||||||
"search_popout.language_code": "Kod ISO gjuhe",
|
"search_popout.language_code": "Kod ISO gjuhe",
|
||||||
"search_popout.options": "Mundësi kërkimi",
|
"search_popout.options": "Mundësi kërkimi",
|
||||||
"search_popout.quick_actions": "Veprime të shpejta",
|
"search_popout.quick_actions": "Veprime të shpejta",
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
"account.report": "รายงาน @{name}",
|
"account.report": "รายงาน @{name}",
|
||||||
"account.requested": "กำลังรอการอนุมัติ คลิกเพื่อยกเลิกคำขอติดตาม",
|
"account.requested": "กำลังรอการอนุมัติ คลิกเพื่อยกเลิกคำขอติดตาม",
|
||||||
"account.requested_follow": "{name} ได้ขอติดตามคุณ",
|
"account.requested_follow": "{name} ได้ขอติดตามคุณ",
|
||||||
"account.share": "แบ่งปันโปรไฟล์ของ @{name}",
|
"account.share": "แชร์โปรไฟล์ของ @{name}",
|
||||||
"account.show_reblogs": "แสดงการดันจาก @{name}",
|
"account.show_reblogs": "แสดงการดันจาก @{name}",
|
||||||
"account.statuses_counter": "{count, plural, other {{counter} โพสต์}}",
|
"account.statuses_counter": "{count, plural, other {{counter} โพสต์}}",
|
||||||
"account.unblock": "เลิกปิดกั้น @{name}",
|
"account.unblock": "เลิกปิดกั้น @{name}",
|
||||||
|
@ -319,7 +319,7 @@
|
||||||
"home.show_announcements": "แสดงประกาศ",
|
"home.show_announcements": "แสดงประกาศ",
|
||||||
"interaction_modal.description.favourite": "ด้วยบัญชีใน Mastodon คุณสามารถชื่นชอบโพสต์นี้เพื่อแจ้งให้ผู้สร้างทราบว่าคุณชื่นชมโพสต์และบันทึกโพสต์ไว้สำหรับภายหลัง",
|
"interaction_modal.description.favourite": "ด้วยบัญชีใน Mastodon คุณสามารถชื่นชอบโพสต์นี้เพื่อแจ้งให้ผู้สร้างทราบว่าคุณชื่นชมโพสต์และบันทึกโพสต์ไว้สำหรับภายหลัง",
|
||||||
"interaction_modal.description.follow": "ด้วยบัญชีใน Mastodon คุณสามารถติดตาม {name} เพื่อรับโพสต์ของเขาในฟีดหน้าแรกของคุณ",
|
"interaction_modal.description.follow": "ด้วยบัญชีใน Mastodon คุณสามารถติดตาม {name} เพื่อรับโพสต์ของเขาในฟีดหน้าแรกของคุณ",
|
||||||
"interaction_modal.description.reblog": "ด้วยบัญชีใน Mastodon คุณสามารถดันโพสต์นี้เพื่อแบ่งปันโพสต์กับผู้ติดตามของคุณเอง",
|
"interaction_modal.description.reblog": "ด้วยบัญชีใน Mastodon คุณสามารถดันโพสต์นี้เพื่อแชร์โพสต์กับผู้ติดตามของคุณเอง",
|
||||||
"interaction_modal.description.reply": "ด้วยบัญชีใน Mastodon คุณสามารถตอบกลับโพสต์นี้",
|
"interaction_modal.description.reply": "ด้วยบัญชีใน Mastodon คุณสามารถตอบกลับโพสต์นี้",
|
||||||
"interaction_modal.login.action": "นำฉันกลับบ้าน",
|
"interaction_modal.login.action": "นำฉันกลับบ้าน",
|
||||||
"interaction_modal.login.prompt": "โดเมนของเซิร์ฟเวอร์บ้านของคุณ เช่น mastodon.social",
|
"interaction_modal.login.prompt": "โดเมนของเซิร์ฟเวอร์บ้านของคุณ เช่น mastodon.social",
|
||||||
|
@ -495,7 +495,7 @@
|
||||||
"onboarding.share.lead": "แจ้งให้ผู้คนทราบวิธีที่เขาสามารถค้นหาคุณใน Mastodon!",
|
"onboarding.share.lead": "แจ้งให้ผู้คนทราบวิธีที่เขาสามารถค้นหาคุณใน Mastodon!",
|
||||||
"onboarding.share.message": "ฉันคือ {username} ใน #Mastodon! มาติดตามฉันที่ {url}",
|
"onboarding.share.message": "ฉันคือ {username} ใน #Mastodon! มาติดตามฉันที่ {url}",
|
||||||
"onboarding.share.next_steps": "ขั้นตอนถัดไปที่เป็นไปได้:",
|
"onboarding.share.next_steps": "ขั้นตอนถัดไปที่เป็นไปได้:",
|
||||||
"onboarding.share.title": "แบ่งปันโปรไฟล์ของคุณ",
|
"onboarding.share.title": "แชร์โปรไฟล์ของคุณ",
|
||||||
"onboarding.start.lead": "ตอนนี้คุณเป็นส่วนหนึ่งของ Mastodon แพลตฟอร์มสื่อสังคมที่มีเอกลักษณ์เฉพาะตัว กระจายศูนย์ ที่ซึ่งคุณ—ไม่ใช่อัลกอริทึม—เรียบเรียงประสบการณ์ของคุณเอง มาช่วยให้คุณเริ่มต้นใช้งานพรมแดนทางสังคมใหม่นี้กันเลย:",
|
"onboarding.start.lead": "ตอนนี้คุณเป็นส่วนหนึ่งของ Mastodon แพลตฟอร์มสื่อสังคมที่มีเอกลักษณ์เฉพาะตัว กระจายศูนย์ ที่ซึ่งคุณ—ไม่ใช่อัลกอริทึม—เรียบเรียงประสบการณ์ของคุณเอง มาช่วยให้คุณเริ่มต้นใช้งานพรมแดนทางสังคมใหม่นี้กันเลย:",
|
||||||
"onboarding.start.skip": "ไม่ต้องการความช่วยเหลือในการเริ่มต้นใช้งาน?",
|
"onboarding.start.skip": "ไม่ต้องการความช่วยเหลือในการเริ่มต้นใช้งาน?",
|
||||||
"onboarding.start.title": "คุณทำสำเร็จแล้ว!",
|
"onboarding.start.title": "คุณทำสำเร็จแล้ว!",
|
||||||
|
@ -506,7 +506,7 @@
|
||||||
"onboarding.steps.setup_profile.body": "เพิ่มการโต้ตอบของคุณโดยการมีโปรไฟล์ที่ครอบคลุม",
|
"onboarding.steps.setup_profile.body": "เพิ่มการโต้ตอบของคุณโดยการมีโปรไฟล์ที่ครอบคลุม",
|
||||||
"onboarding.steps.setup_profile.title": "ปรับแต่งโปรไฟล์ของคุณ",
|
"onboarding.steps.setup_profile.title": "ปรับแต่งโปรไฟล์ของคุณ",
|
||||||
"onboarding.steps.share_profile.body": "แจ้งให้เพื่อน ๆ ของคุณทราบวิธีค้นหาคุณใน Mastodon",
|
"onboarding.steps.share_profile.body": "แจ้งให้เพื่อน ๆ ของคุณทราบวิธีค้นหาคุณใน Mastodon",
|
||||||
"onboarding.steps.share_profile.title": "แบ่งปันโปรไฟล์ Mastodon ของคุณ",
|
"onboarding.steps.share_profile.title": "แชร์โปรไฟล์ Mastodon ของคุณ",
|
||||||
"onboarding.tips.2fa": "<strong>คุณทราบหรือไม่?</strong> คุณสามารถรักษาความปลอดภัยบัญชีของคุณได้โดยตั้งค่าการรับรองความถูกต้องด้วยสองปัจจัยในการตั้งค่าบัญชีของคุณ การรับรองความถูกต้องด้วยสองปัจจัยทำงานร่วมกับแอป TOTP ใด ๆ ที่คุณเลือก ไม่จำเป็นต้องมีหมายเลขโทรศัพท์!",
|
"onboarding.tips.2fa": "<strong>คุณทราบหรือไม่?</strong> คุณสามารถรักษาความปลอดภัยบัญชีของคุณได้โดยตั้งค่าการรับรองความถูกต้องด้วยสองปัจจัยในการตั้งค่าบัญชีของคุณ การรับรองความถูกต้องด้วยสองปัจจัยทำงานร่วมกับแอป TOTP ใด ๆ ที่คุณเลือก ไม่จำเป็นต้องมีหมายเลขโทรศัพท์!",
|
||||||
"onboarding.tips.accounts_from_other_servers": "<strong>คุณทราบหรือไม่?</strong> เนื่องจาก Mastodon เป็นแบบกระจายศูนย์ โปรไฟล์บางส่วนที่คุณเจอจะได้รับการโฮสต์ในเซิร์ฟเวอร์อื่น ๆ ที่ไม่ใช่ของคุณ และคุณยังสามารถโต้ตอบกับเขาได้อย่างไร้รอยต่อ! เซิร์ฟเวอร์ของเขาอยู่ในครึ่งหลังของชื่อผู้ใช้ของเขา!",
|
"onboarding.tips.accounts_from_other_servers": "<strong>คุณทราบหรือไม่?</strong> เนื่องจาก Mastodon เป็นแบบกระจายศูนย์ โปรไฟล์บางส่วนที่คุณเจอจะได้รับการโฮสต์ในเซิร์ฟเวอร์อื่น ๆ ที่ไม่ใช่ของคุณ และคุณยังสามารถโต้ตอบกับเขาได้อย่างไร้รอยต่อ! เซิร์ฟเวอร์ของเขาอยู่ในครึ่งหลังของชื่อผู้ใช้ของเขา!",
|
||||||
"onboarding.tips.migration": "<strong>คุณทราบหรือไม่?</strong> หากคุณรู้สึกว่า {domain} ไม่ใช่ตัวเลือกเซิร์ฟเวอร์ที่ยอดเยี่ยมสำหรับคุณในอนาคต คุณสามารถย้ายไปยังเซิร์ฟเวอร์ Mastodon อื่นได้โดยไม่สูญเสียผู้ติดตามของคุณ คุณยังสามารถโฮสต์เซิร์ฟเวอร์ของคุณเอง!",
|
"onboarding.tips.migration": "<strong>คุณทราบหรือไม่?</strong> หากคุณรู้สึกว่า {domain} ไม่ใช่ตัวเลือกเซิร์ฟเวอร์ที่ยอดเยี่ยมสำหรับคุณในอนาคต คุณสามารถย้ายไปยังเซิร์ฟเวอร์ Mastodon อื่นได้โดยไม่สูญเสียผู้ติดตามของคุณ คุณยังสามารถโฮสต์เซิร์ฟเวอร์ของคุณเอง!",
|
||||||
|
@ -558,7 +558,7 @@
|
||||||
"report.categories.spam": "สแปม",
|
"report.categories.spam": "สแปม",
|
||||||
"report.categories.violation": "เนื้อหาละเมิดกฎของเซิร์ฟเวอร์จำนวนหนึ่งหรือมากกว่า",
|
"report.categories.violation": "เนื้อหาละเมิดกฎของเซิร์ฟเวอร์จำนวนหนึ่งหรือมากกว่า",
|
||||||
"report.category.subtitle": "เลือกที่ตรงกันที่สุด",
|
"report.category.subtitle": "เลือกที่ตรงกันที่สุด",
|
||||||
"report.category.title": "บอกเราถึงสิ่งที่กำลังเกิดขึ้นกับ {type} นี้",
|
"report.category.title": "บอกเราถึงสิ่งที่กำลังเกิดขึ้นกับ{type}นี้",
|
||||||
"report.category.title_account": "โปรไฟล์",
|
"report.category.title_account": "โปรไฟล์",
|
||||||
"report.category.title_status": "โพสต์",
|
"report.category.title_status": "โพสต์",
|
||||||
"report.close": "เสร็จสิ้น",
|
"report.close": "เสร็จสิ้น",
|
||||||
|
@ -629,7 +629,7 @@
|
||||||
"sign_in_banner.create_account": "สร้างบัญชี",
|
"sign_in_banner.create_account": "สร้างบัญชี",
|
||||||
"sign_in_banner.sign_in": "เข้าสู่ระบบ",
|
"sign_in_banner.sign_in": "เข้าสู่ระบบ",
|
||||||
"sign_in_banner.sso_redirect": "เข้าสู่ระบบหรือลงทะเบียน",
|
"sign_in_banner.sso_redirect": "เข้าสู่ระบบหรือลงทะเบียน",
|
||||||
"sign_in_banner.text": "เข้าสู่ระบบเพื่อติดตามโปรไฟล์หรือแฮชแท็ก ชื่นชอบ แบ่งปัน และตอบกลับโพสต์ คุณยังสามารถโต้ตอบจากบัญชีของคุณในเซิร์ฟเวอร์อื่น",
|
"sign_in_banner.text": "เข้าสู่ระบบเพื่อติดตามโปรไฟล์หรือแฮชแท็ก ชื่นชอบ แชร์ และตอบกลับโพสต์ คุณยังสามารถโต้ตอบจากบัญชีของคุณในเซิร์ฟเวอร์อื่น",
|
||||||
"status.admin_account": "เปิดส่วนติดต่อการควบคุมสำหรับ @{name}",
|
"status.admin_account": "เปิดส่วนติดต่อการควบคุมสำหรับ @{name}",
|
||||||
"status.admin_domain": "เปิดส่วนติดต่อการควบคุมสำหรับ {domain}",
|
"status.admin_domain": "เปิดส่วนติดต่อการควบคุมสำหรับ {domain}",
|
||||||
"status.admin_status": "เปิดโพสต์นี้ในส่วนติดต่อการควบคุม",
|
"status.admin_status": "เปิดโพสต์นี้ในส่วนติดต่อการควบคุม",
|
||||||
|
@ -675,7 +675,7 @@
|
||||||
"status.replyAll": "ตอบกลับกระทู้",
|
"status.replyAll": "ตอบกลับกระทู้",
|
||||||
"status.report": "รายงาน @{name}",
|
"status.report": "รายงาน @{name}",
|
||||||
"status.sensitive_warning": "เนื้อหาที่ละเอียดอ่อน",
|
"status.sensitive_warning": "เนื้อหาที่ละเอียดอ่อน",
|
||||||
"status.share": "แบ่งปัน",
|
"status.share": "แชร์",
|
||||||
"status.show_filter_reason": "แสดงต่อไป",
|
"status.show_filter_reason": "แสดงต่อไป",
|
||||||
"status.show_less": "แสดงน้อยลง",
|
"status.show_less": "แสดงน้อยลง",
|
||||||
"status.show_less_all": "แสดงน้อยลงทั้งหมด",
|
"status.show_less_all": "แสดงน้อยลงทั้งหมด",
|
||||||
|
|
1
app/javascript/mastodon/locales/tlh.json
Normal file
1
app/javascript/mastodon/locales/tlh.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -376,7 +376,7 @@
|
||||||
"lightbox.previous": "上一步",
|
"lightbox.previous": "上一步",
|
||||||
"limited_account_hint.action": "一律顯示個人檔案",
|
"limited_account_hint.action": "一律顯示個人檔案",
|
||||||
"limited_account_hint.title": "此個人檔案已被 {domain} 的管理員隱藏。",
|
"limited_account_hint.title": "此個人檔案已被 {domain} 的管理員隱藏。",
|
||||||
"link_preview.author": "由 {name} 提供",
|
"link_preview.author": "來自 {name}",
|
||||||
"lists.account.add": "新增至列表",
|
"lists.account.add": "新增至列表",
|
||||||
"lists.account.remove": "自列表中移除",
|
"lists.account.remove": "自列表中移除",
|
||||||
"lists.delete": "刪除列表",
|
"lists.delete": "刪除列表",
|
||||||
|
|
|
@ -100,6 +100,15 @@ const initialState = ImmutableMap({
|
||||||
body: '',
|
body: '',
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
dismissed_banners: ImmutableMap({
|
||||||
|
'public_timeline': false,
|
||||||
|
'community_timeline': false,
|
||||||
|
'home.explore_prompt': false,
|
||||||
|
'explore/links': false,
|
||||||
|
'explore/statuses': false,
|
||||||
|
'explore/tags': false,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultColumns = fromJS([
|
const defaultColumns = fromJS([
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import ready from '../ready';
|
|
||||||
|
|
||||||
export let assetHost = '';
|
|
||||||
|
|
||||||
ready(() => {
|
|
||||||
const cdnHost = document.querySelector('meta[name=cdn-host]');
|
|
||||||
if (cdnHost) {
|
|
||||||
assetHost = cdnHost.content || '';
|
|
||||||
}
|
|
||||||
});
|
|
13
app/javascript/mastodon/utils/config.ts
Normal file
13
app/javascript/mastodon/utils/config.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import ready from '../ready';
|
||||||
|
|
||||||
|
export let assetHost = '';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
ready(() => {
|
||||||
|
const cdnHost = document.querySelector<HTMLMetaElement>(
|
||||||
|
'meta[name=cdn-host]',
|
||||||
|
);
|
||||||
|
if (cdnHost) {
|
||||||
|
assetHost = cdnHost.content || '';
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,6 +0,0 @@
|
||||||
// NB: This function can still return unsafe HTML
|
|
||||||
export const unescapeHTML = (html) => {
|
|
||||||
const wrapper = document.createElement('div');
|
|
||||||
wrapper.innerHTML = html.replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n').replace(/<[^>]*>/g, '');
|
|
||||||
return wrapper.textContent;
|
|
||||||
};
|
|
9
app/javascript/mastodon/utils/html.ts
Normal file
9
app/javascript/mastodon/utils/html.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// NB: This function can still return unsafe HTML
|
||||||
|
export const unescapeHTML = (html: string) => {
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.innerHTML = html
|
||||||
|
.replace(/<br\s*\/?>/g, '\n')
|
||||||
|
.replace(/<\/p><p>/g, '\n\n')
|
||||||
|
.replace(/<[^>]*>/g, '');
|
||||||
|
return wrapper.textContent;
|
||||||
|
};
|
|
@ -1,13 +1,23 @@
|
||||||
// Copied from emoji-mart for consistency with emoji picker and since
|
// Copied from emoji-mart for consistency with emoji picker and since
|
||||||
// they don't export the icons in the package
|
// they don't export the icons in the package
|
||||||
export const loupeIcon = (
|
export const loupeIcon = (
|
||||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
|
<svg
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
viewBox='0 0 20 20'
|
||||||
|
width='13'
|
||||||
|
height='13'
|
||||||
|
>
|
||||||
<path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
|
<path d='M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z' />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const deleteIcon = (
|
export const deleteIcon = (
|
||||||
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='13' height='13'>
|
<svg
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
viewBox='0 0 20 20'
|
||||||
|
width='13'
|
||||||
|
height='13'
|
||||||
|
>
|
||||||
<path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
|
<path d='M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z' />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
|
@ -1,30 +0,0 @@
|
||||||
// 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/valid-params, 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));
|
|
||||||
}
|
|
||||||
};
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue