Gab Social. All are welcome.
This commit is contained in:
118
config/application.rb
Normal file
118
config/application.rb
Normal file
@@ -0,0 +1,118 @@
|
||||
require_relative 'boot'
|
||||
|
||||
require 'rails/all'
|
||||
|
||||
# Require the gems listed in Gemfile, including any gems
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
require_relative '../app/lib/exceptions'
|
||||
require_relative '../lib/paperclip/lazy_thumbnail'
|
||||
require_relative '../lib/paperclip/gif_transcoder'
|
||||
require_relative '../lib/paperclip/video_transcoder'
|
||||
require_relative '../lib/gabsocial/snowflake'
|
||||
require_relative '../lib/gabsocial/version'
|
||||
require_relative '../lib/devise/ldap_authenticatable'
|
||||
|
||||
Dotenv::Railtie.load
|
||||
|
||||
Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true'
|
||||
|
||||
require_relative '../lib/gabsocial/redis_config'
|
||||
|
||||
module GabSocial
|
||||
class Application < Rails::Application
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 5.2
|
||||
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration should go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||
# config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# All translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
config.i18n.available_locales = [
|
||||
:en,
|
||||
:ar,
|
||||
:ast,
|
||||
:bg,
|
||||
:bn,
|
||||
:ca,
|
||||
:co,
|
||||
:cs,
|
||||
:cy,
|
||||
:da,
|
||||
:de,
|
||||
:el,
|
||||
:eo,
|
||||
:es,
|
||||
:eu,
|
||||
:fa,
|
||||
:fi,
|
||||
:fr,
|
||||
:ga,
|
||||
:gl,
|
||||
:he,
|
||||
:hi,
|
||||
:hr,
|
||||
:hu,
|
||||
:hy,
|
||||
:id,
|
||||
:io,
|
||||
:it,
|
||||
:ja,
|
||||
:ka,
|
||||
:kk,
|
||||
:ko,
|
||||
:lt,
|
||||
:lv,
|
||||
:ms,
|
||||
:nl,
|
||||
:no,
|
||||
:oc,
|
||||
:pl,
|
||||
:pt,
|
||||
:'pt-BR',
|
||||
:ro,
|
||||
:ru,
|
||||
:sk,
|
||||
:sl,
|
||||
:sq,
|
||||
:sr,
|
||||
:'sr-Latn',
|
||||
:sv,
|
||||
:ta,
|
||||
:te,
|
||||
:th,
|
||||
:tr,
|
||||
:uk,
|
||||
:'zh-CN',
|
||||
:'zh-HK',
|
||||
:'zh-TW',
|
||||
]
|
||||
|
||||
config.i18n.default_locale = ENV['DEFAULT_LOCALE']&.to_sym
|
||||
|
||||
unless config.i18n.available_locales.include?(config.i18n.default_locale)
|
||||
config.i18n.default_locale = :en
|
||||
end
|
||||
|
||||
# config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
|
||||
# config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
|
||||
|
||||
config.active_job.queue_adapter = :sidekiq
|
||||
|
||||
config.middleware.use Rack::Attack
|
||||
config.middleware.use Rack::Deflater
|
||||
|
||||
config.to_prepare do
|
||||
Doorkeeper::AuthorizationsController.layout 'modal'
|
||||
Doorkeeper::AuthorizedApplicationsController.layout 'admin'
|
||||
Doorkeeper::Application.send :include, ApplicationExtension
|
||||
end
|
||||
end
|
||||
end
|
||||
14
config/boot.rb
Normal file
14
config/boot.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||
|
||||
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||
require 'bootsnap' # Speed up boot time by caching expensive operations.
|
||||
|
||||
Bootsnap.setup(
|
||||
cache_dir: File.expand_path('../tmp/cache', __dir__),
|
||||
development_mode: ENV.fetch('RAILS_ENV', 'development') == 'development',
|
||||
load_path_cache: true,
|
||||
autoload_paths_cache: true,
|
||||
disable_trace: false,
|
||||
compile_cache_iseq: false,
|
||||
compile_cache_yaml: false
|
||||
)
|
||||
301
config/brakeman.ignore
Normal file
301
config/brakeman.ignore
Normal file
@@ -0,0 +1,301 @@
|
||||
{
|
||||
"ignored_warnings": [
|
||||
{
|
||||
"warning_type": "Mass Assignment",
|
||||
"warning_code": 105,
|
||||
"fingerprint": "0117d2be5947ea4e4fbed9c15f23c6615b12c6892973411820c83d079808819d",
|
||||
"check_name": "PermitAttributes",
|
||||
"message": "Potentially dangerous key allowed for mass assignment",
|
||||
"file": "app/controllers/api/v1/search_controller.rb",
|
||||
"line": 30,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
||||
"code": "params.permit(:type, :offset, :min_id, :max_id, :account_id)",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Api::V1::SearchController",
|
||||
"method": "search_params"
|
||||
},
|
||||
"user_input": ":account_id",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "SQL Injection",
|
||||
"warning_code": 0,
|
||||
"fingerprint": "04dbbc249b989db2e0119bbb0f59c9818e12889d2b97c529cdc0b1526002ba4b",
|
||||
"check_name": "SQL",
|
||||
"message": "Possible SQL injection",
|
||||
"file": "app/models/report.rb",
|
||||
"line": 90,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||
"code": "Admin::ActionLog.from(\"(#{[Admin::ActionLog.where(:target_type => \"Report\", :target_id => id, :created_at => ((created_at..updated_at))).unscope(:order), Admin::ActionLog.where(:target_type => \"Account\", :target_id => target_account_id, :created_at => ((created_at..updated_at))).unscope(:order), Admin::ActionLog.where(:target_type => \"Status\", :target_id => status_ids, :created_at => ((created_at..updated_at))).unscope(:order)].map do\n \"(#{query.to_sql})\"\n end.join(\" UNION ALL \")}) AS admin_action_logs\")",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Report",
|
||||
"method": "history"
|
||||
},
|
||||
"user_input": "Admin::ActionLog.where(:target_type => \"Status\", :target_id => status_ids, :created_at => ((created_at..updated_at))).unscope(:order)",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "SQL Injection",
|
||||
"warning_code": 0,
|
||||
"fingerprint": "19df3740b8d02a9fe0eb52c939b4b87d3a2a591162a6adfa8d64e9c26aeebe6d",
|
||||
"check_name": "SQL",
|
||||
"message": "Possible SQL injection",
|
||||
"file": "app/models/status.rb",
|
||||
"line": 87,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||
"code": "result.joins(\"INNER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}\")",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Status",
|
||||
"method": null
|
||||
},
|
||||
"user_input": "id",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Mass Assignment",
|
||||
"warning_code": 105,
|
||||
"fingerprint": "28d81cc22580ef76e912b077b245f353499aa27b3826476667224c00227af2a9",
|
||||
"check_name": "PermitAttributes",
|
||||
"message": "Potentially dangerous key allowed for mass assignment",
|
||||
"file": "app/controllers/admin/reports_controller.rb",
|
||||
"line": 56,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
||||
"code": "params.permit(:account_id, :resolved, :target_account_id)",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Admin::ReportsController",
|
||||
"method": "filter_params"
|
||||
},
|
||||
"user_input": ":account_id",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Dynamic Render Path",
|
||||
"warning_code": 15,
|
||||
"fingerprint": "4b6a895e2805578d03ceedbe1d469cc75a0c759eba093722523edb4b8683c873",
|
||||
"check_name": "Render",
|
||||
"message": "Render path contains parameter value",
|
||||
"file": "app/views/admin/action_logs/index.html.haml",
|
||||
"line": 4,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
||||
"code": "render(action => Admin::ActionLog.page(params[:page]), {})",
|
||||
"render_path": [{"type":"controller","class":"Admin::ActionLogsController","method":"index","line":7,"file":"app/controllers/admin/action_logs_controller.rb","rendered":{"name":"admin/action_logs/index","file":"/home/eugr/Projects/gabsocial/app/views/admin/action_logs/index.html.haml"}}],
|
||||
"location": {
|
||||
"type": "template",
|
||||
"template": "admin/action_logs/index"
|
||||
},
|
||||
"user_input": "params[:page]",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Redirect",
|
||||
"warning_code": 18,
|
||||
"fingerprint": "5fad11cd67f905fab9b1d5739d01384a1748ebe78c5af5ac31518201925265a7",
|
||||
"check_name": "Redirect",
|
||||
"message": "Possible unprotected redirect",
|
||||
"file": "app/controllers/remote_interaction_controller.rb",
|
||||
"line": 21,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/redirect/",
|
||||
"code": "redirect_to(RemoteFollow.new(resource_params).interact_address_for(Status.find(params[:id])))",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "RemoteInteractionController",
|
||||
"method": "create"
|
||||
},
|
||||
"user_input": "RemoteFollow.new(resource_params).interact_address_for(Status.find(params[:id]))",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Dynamic Render Path",
|
||||
"warning_code": 15,
|
||||
"fingerprint": "67afc0d5f7775fa5bd91d1912e1b5505aeedef61876347546fa20f92fd6915e6",
|
||||
"check_name": "Render",
|
||||
"message": "Render path contains parameter value",
|
||||
"file": "app/views/stream_entries/embed.html.haml",
|
||||
"line": 3,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
||||
"code": "render(action => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :centered => true, :autoplay => ActiveModel::Type::Boolean.new.cast(params[:autoplay]) })",
|
||||
"render_path": [{"type":"controller","class":"StatusesController","method":"embed","line":63,"file":"app/controllers/statuses_controller.rb","rendered":{"name":"stream_entries/embed","file":"/home/eugr/Projects/gabsocial/app/views/stream_entries/embed.html.haml"}}],
|
||||
"location": {
|
||||
"type": "template",
|
||||
"template": "stream_entries/embed"
|
||||
},
|
||||
"user_input": "params[:id]",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "SQL Injection",
|
||||
"warning_code": 0,
|
||||
"fingerprint": "6f075c1484908e3ec9bed21ab7cf3c7866be8da3881485d1c82e13093aefcbd7",
|
||||
"check_name": "SQL",
|
||||
"message": "Possible SQL injection",
|
||||
"file": "app/models/status.rb",
|
||||
"line": 92,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||
"code": "result.joins(\"LEFT OUTER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}\")",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Status",
|
||||
"method": null
|
||||
},
|
||||
"user_input": "id",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Dynamic Render Path",
|
||||
"warning_code": 15,
|
||||
"fingerprint": "8d843713d99e8403f7992f3e72251b633817cf9076ffcbbad5613859d2bbc127",
|
||||
"check_name": "Render",
|
||||
"message": "Render path contains parameter value",
|
||||
"file": "app/views/admin/custom_emojis/index.html.haml",
|
||||
"line": 45,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
||||
"code": "render(action => filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]), {})",
|
||||
"render_path": [{"type":"controller","class":"Admin::CustomEmojisController","method":"index","line":11,"file":"app/controllers/admin/custom_emojis_controller.rb","rendered":{"name":"admin/custom_emojis/index","file":"/home/eugr/Projects/gabsocial/app/views/admin/custom_emojis/index.html.haml"}}],
|
||||
"location": {
|
||||
"type": "template",
|
||||
"template": "admin/custom_emojis/index"
|
||||
},
|
||||
"user_input": "params[:page]",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "SQL Injection",
|
||||
"warning_code": 0,
|
||||
"fingerprint": "9ccb9ba6a6947400e187d515e0bf719d22993d37cfc123c824d7fafa6caa9ac3",
|
||||
"check_name": "SQL",
|
||||
"message": "Possible SQL injection",
|
||||
"file": "lib/gabsocial/snowflake.rb",
|
||||
"line": 87,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||
"code": "connection.execute(\" CREATE OR REPLACE FUNCTION timestamp_id(table_name text)\\n RETURNS bigint AS\\n $$\\n DECLARE\\n time_part bigint;\\n sequence_base bigint;\\n tail bigint;\\n BEGIN\\n time_part := (\\n -- Get the time in milliseconds\\n ((date_part('epoch', now()) * 1000))::bigint\\n -- And shift it over two bytes\\n << 16);\\n\\n sequence_base := (\\n 'x' ||\\n -- Take the first two bytes (four hex characters)\\n substr(\\n -- Of the MD5 hash of the data we documented\\n md5(table_name ||\\n '#{SecureRandom.hex(16)}' ||\\n time_part::text\\n ),\\n 1, 4\\n )\\n -- And turn it into a bigint\\n )::bit(16)::bigint;\\n\\n -- Finally, add our sequence number to our base, and chop\\n -- it to the last two bytes\\n tail := (\\n (sequence_base + nextval(table_name || '_id_seq'))\\n & 65535);\\n\\n -- Return the time part and the sequence part. OR appears\\n -- faster here than addition, but they're equivalent:\\n -- time_part has no trailing two bytes, and tail is only\\n -- the last two bytes.\\n RETURN time_part | tail;\\n END\\n $$ LANGUAGE plpgsql VOLATILE;\\n\")",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "GabSocial::Snowflake",
|
||||
"method": "define_timestamp_id"
|
||||
},
|
||||
"user_input": "SecureRandom.hex(16)",
|
||||
"confidence": "Medium",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Dynamic Render Path",
|
||||
"warning_code": 15,
|
||||
"fingerprint": "9f31d941f3910dba2e9bfcd81aef4513249bd24c02d0f98e13ad44fdeeccd0e8",
|
||||
"check_name": "Render",
|
||||
"message": "Render path contains parameter value",
|
||||
"file": "app/views/admin/accounts/index.html.haml",
|
||||
"line": 47,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
||||
"code": "render(action => filtered_accounts.page(params[:page]), {})",
|
||||
"render_path": [{"type":"controller","class":"Admin::AccountsController","method":"index","line":12,"file":"app/controllers/admin/accounts_controller.rb","rendered":{"name":"admin/accounts/index","file":"/home/eugr/Projects/gabsocial/app/views/admin/accounts/index.html.haml"}}],
|
||||
"location": {
|
||||
"type": "template",
|
||||
"template": "admin/accounts/index"
|
||||
},
|
||||
"user_input": "params[:page]",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Redirect",
|
||||
"warning_code": 18,
|
||||
"fingerprint": "ba699ddcc6552c422c4ecd50d2cd217f616a2446659e185a50b05a0f2dad8d33",
|
||||
"check_name": "Redirect",
|
||||
"message": "Possible unprotected redirect",
|
||||
"file": "app/controllers/media_controller.rb",
|
||||
"line": 14,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/redirect/",
|
||||
"code": "redirect_to(MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original))",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "MediaController",
|
||||
"method": "show"
|
||||
},
|
||||
"user_input": "MediaAttachment.attached.find_by!(:shortcode => ((params[:id] or params[:medium_id]))).file.url(:original)",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Redirect",
|
||||
"warning_code": 18,
|
||||
"fingerprint": "bb7e94e60af41decb811bb32171f1b27e9bf3f4d01e9e511127362e22510eb11",
|
||||
"check_name": "Redirect",
|
||||
"message": "Possible unprotected redirect",
|
||||
"file": "app/controllers/remote_follow_controller.rb",
|
||||
"line": 19,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/redirect/",
|
||||
"code": "redirect_to(RemoteFollow.new(resource_params).subscribe_address_for(Account.find_local!(params[:account_username])))",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "RemoteFollowController",
|
||||
"method": "create"
|
||||
},
|
||||
"user_input": "RemoteFollow.new(resource_params).subscribe_address_for(Account.find_local!(params[:account_username]))",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Mass Assignment",
|
||||
"warning_code": 105,
|
||||
"fingerprint": "e867661b2c9812bc8b75a5df12b28e2a53ab97015de0638b4e732fe442561b28",
|
||||
"check_name": "PermitAttributes",
|
||||
"message": "Potentially dangerous key allowed for mass assignment",
|
||||
"file": "app/controllers/api/v1/reports_controller.rb",
|
||||
"line": 36,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
||||
"code": "params.permit(:account_id, :comment, :forward, :status_ids => ([]))",
|
||||
"render_path": null,
|
||||
"location": {
|
||||
"type": "method",
|
||||
"class": "Api::V1::ReportsController",
|
||||
"method": "report_params"
|
||||
},
|
||||
"user_input": ":account_id",
|
||||
"confidence": "High",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"warning_type": "Dynamic Render Path",
|
||||
"warning_code": 15,
|
||||
"fingerprint": "fbd0fc59adb5c6d44b60e02debb31d3af11719f534c9881e21435bbff87404d6",
|
||||
"check_name": "Render",
|
||||
"message": "Render path contains parameter value",
|
||||
"file": "app/views/stream_entries/show.html.haml",
|
||||
"line": 23,
|
||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
||||
"code": "render(partial => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { :locals => ({ Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :include_threads => true }) })",
|
||||
"render_path": [{"type":"controller","class":"StatusesController","method":"show","line":34,"file":"app/controllers/statuses_controller.rb","rendered":{"name":"stream_entries/show","file":"/home/eugr/Projects/gabsocial/app/views/stream_entries/show.html.haml"}}],
|
||||
"location": {
|
||||
"type": "template",
|
||||
"template": "stream_entries/show"
|
||||
},
|
||||
"user_input": "params[:id]",
|
||||
"confidence": "Weak",
|
||||
"note": ""
|
||||
}
|
||||
],
|
||||
"updated": "2019-02-21 02:30:29 +0100",
|
||||
"brakeman_version": "4.4.0"
|
||||
}
|
||||
35
config/database.yml
Normal file
35
config/database.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
default: &default
|
||||
adapter: postgresql
|
||||
pool: <%= ENV["DB_POOL"] || ENV['MAX_THREADS'] || 5 %>
|
||||
timeout: 5000
|
||||
encoding: unicode
|
||||
sslmode: <%= ENV['DB_SSLMODE'] || "prefer" %>
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: <%= ENV['DB_NAME'] || 'gabsocial_development' %>
|
||||
username: <%= ENV['DB_USER'] %>
|
||||
password: <%= ENV['DB_PASS'] %>
|
||||
host: <%= ENV['DB_HOST'] %>
|
||||
port: <%= ENV['DB_PORT'] %>
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
test:
|
||||
<<: *default
|
||||
database: <%= ENV['DB_NAME'] || 'gabsocial' %>_test<%= ENV['TEST_ENV_NUMBER'] %>
|
||||
username: <%= ENV['DB_USER'] %>
|
||||
password: <%= ENV['DB_PASS'] %>
|
||||
host: <%= ENV['DB_HOST'] %>
|
||||
port: <%= ENV['DB_PORT'] %>
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
database: <%= ENV['DB_NAME'] || 'gabsocial_production' %>
|
||||
username: <%= ENV['DB_USER'] || 'gabsocial' %>
|
||||
password: <%= ENV['DB_PASS'] || '' %>
|
||||
host: <%= ENV['DB_HOST'] || 'localhost' %>
|
||||
port: <%= ENV['DB_PORT'] || 5432 %>
|
||||
prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %>
|
||||
|
||||
14
config/deploy.rb
Normal file
14
config/deploy.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
lock '3.11.0'
|
||||
|
||||
set :repo_url, ENV.fetch('REPO', 'https://github.com/gab-ai-inc/gab-social.git')
|
||||
set :branch, ENV.fetch('BRANCH', 'master')
|
||||
|
||||
set :application, 'gabsocial'
|
||||
set :rbenv_type, :user
|
||||
set :rbenv_ruby, File.read('.ruby-version').strip
|
||||
set :migration_role, :app
|
||||
|
||||
append :linked_files, '.env.production', 'public/robots.txt'
|
||||
append :linked_dirs, 'vendor/bundle', 'node_modules', 'public/system'
|
||||
7
config/environment.rb
Normal file
7
config/environment.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# Load the Rails application.
|
||||
require_relative 'application'
|
||||
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
|
||||
ActiveRecord::SchemaDumper.ignore_tables = ['deprecated_preview_cards']
|
||||
96
config/environments/development.rb
Normal file
96
config/environments/development.rb
Normal file
@@ -0,0 +1,96 @@
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
# every request. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
config.cache_classes = false
|
||||
|
||||
# Do not eager load code on boot.
|
||||
config.eager_load = false
|
||||
|
||||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
# Enable/disable caching. By default caching is disabled.
|
||||
# Run rails dev:cache to toggle caching.
|
||||
if Rails.root.join('tmp/caching-dev.txt').exist?
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
config.cache_store = :redis_store, ENV['REDIS_URL'], REDIS_CACHE_PARAMS
|
||||
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{2.days.to_i}",
|
||||
}
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
config.cache_store = :null_store
|
||||
end
|
||||
|
||||
ActiveSupport::Logger.new(STDOUT).tap do |logger|
|
||||
logger.formatter = config.log_formatter
|
||||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
# Generate random VAPID keys
|
||||
vapid_key = Webpush.generate_key
|
||||
config.x.vapid_private_key = vapid_key.private_key
|
||||
config.x.vapid_public_key = vapid_key.public_key
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Debug mode disables concatenation and preprocessing of assets.
|
||||
# This option may cause significant delays in view rendering with a large
|
||||
# number of complex assets.
|
||||
config.assets.debug = true
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = true
|
||||
|
||||
# Adds additional error checking when serving assets at runtime.
|
||||
# Checks for improperly declared sprockets dependencies.
|
||||
# Raises helpful error messages.
|
||||
config.assets.raise_runtime_errors = true
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
|
||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||
# routes, locales, etc. This feature depends on the listen gem.
|
||||
# config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
||||
|
||||
config.action_mailer.default_options = { from: 'notifications@localhost' }
|
||||
|
||||
# If using a Heroku, Vagrant or generic remote development environment,
|
||||
# use letter_opener_web, accessible at /letter_opener.
|
||||
# Otherwise, use letter_opener, which launches a browser window to view sent mail.
|
||||
config.action_mailer.delivery_method = (ENV['HEROKU'] || ENV['VAGRANT'] || ENV['REMOTE_DEV']) ? :letter_opener_web : :letter_opener
|
||||
|
||||
config.after_initialize do
|
||||
Bullet.enable = true
|
||||
Bullet.bullet_logger = true
|
||||
Bullet.rails_logger = false
|
||||
|
||||
Bullet.add_whitelist type: :n_plus_one_query, class_name: 'User', association: :account
|
||||
end
|
||||
|
||||
config.x.otp_secret = ENV.fetch('OTP_SECRET', '1fc2b87989afa6351912abeebe31ffc5c476ead9bf8b3d74cbc4a302c7b69a45b40b1bbef3506ddad73e942e15ed5ca4b402bf9a66423626051104f4b5f05109')
|
||||
end
|
||||
|
||||
ActiveRecordQueryTrace.enabled = ENV['QUERY_TRACE_ENABLED'] == 'true'
|
||||
|
||||
module PrivateAddressCheck
|
||||
def self.private_address?(*)
|
||||
false
|
||||
end
|
||||
end
|
||||
105
config/environments/production.rb
Normal file
105
config/environments/production.rb
Normal file
@@ -0,0 +1,105 @@
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
# and those relying on copy on write to perform better.
|
||||
# Rake tasks automatically ignore this option for performance.
|
||||
config.eager_load = true
|
||||
|
||||
# Full error reports are disabled and caching is turned on.
|
||||
config.consider_all_requests_local = false
|
||||
config.action_controller.perform_caching = true
|
||||
config.action_controller.asset_host = ENV['CDN_HOST'] if ENV['CDN_HOST'].present?
|
||||
|
||||
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
|
||||
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
|
||||
# config.require_master_key = true
|
||||
|
||||
# Disable serving static files from the `/public` folder by default since
|
||||
# Apache or NGINX already handles this.
|
||||
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
||||
|
||||
ActiveSupport::Logger.new(STDOUT).tap do |logger|
|
||||
logger.formatter = config.log_formatter
|
||||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
# Compress JavaScripts and CSS.
|
||||
# config.assets.js_compressor = Uglifier.new(mangle: false)
|
||||
# config.assets.css_compressor = :sass
|
||||
|
||||
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||
config.assets.compile = false
|
||||
|
||||
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
||||
|
||||
# Specifies the header that your server uses for sending files.
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
||||
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
||||
|
||||
# Allow to specify public IP of reverse proxy if it's needed
|
||||
config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present?
|
||||
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym
|
||||
|
||||
# Prepend all log lines with the following tags.
|
||||
config.log_tags = [:request_id]
|
||||
|
||||
# Use a different cache store in production.
|
||||
config.cache_store = :redis_store, ENV['CACHE_REDIS_URL'], REDIS_CACHE_PARAMS
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# English when a translation cannot be found).
|
||||
config.i18n.fallbacks = [:en]
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
# Better log formatting
|
||||
config.lograge.enabled = true
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# E-mails
|
||||
config.action_mailer.default_options = { from: ENV.fetch('SMTP_FROM_ADDRESS', 'notifications@localhost') }
|
||||
|
||||
config.action_mailer.smtp_settings = {
|
||||
:port => ENV['SMTP_PORT'],
|
||||
:address => ENV['SMTP_SERVER'],
|
||||
:user_name => ENV['SMTP_LOGIN'].presence,
|
||||
:password => ENV['SMTP_PASSWORD'].presence,
|
||||
:domain => ENV['SMTP_DOMAIN'] || ENV['LOCAL_DOMAIN'],
|
||||
:authentication => ENV['SMTP_AUTH_METHOD'] == 'none' ? nil : ENV['SMTP_AUTH_METHOD'] || :plain,
|
||||
:ca_file => ENV['SMTP_CA_FILE'].presence,
|
||||
:openssl_verify_mode => ENV['SMTP_OPENSSL_VERIFY_MODE'],
|
||||
:enable_starttls_auto => ENV['SMTP_ENABLE_STARTTLS_AUTO'] || true,
|
||||
:tls => ENV['SMTP_TLS'].presence,
|
||||
}
|
||||
|
||||
config.action_mailer.delivery_method = ENV.fetch('SMTP_DELIVERY_METHOD', 'smtp').to_sym
|
||||
|
||||
config.action_dispatch.default_headers = {
|
||||
'Server' => 'GabSocial',
|
||||
'X-Frame-Options' => 'DENY',
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
'X-XSS-Protection' => '1; mode=block',
|
||||
}
|
||||
|
||||
config.x.otp_secret = ENV.fetch('OTP_SECRET')
|
||||
end
|
||||
72
config/environments/test.rb
Normal file
72
config/environments/test.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
# and recreated between test runs. Don't rely on the data there!
|
||||
config.cache_classes = true
|
||||
|
||||
# Do not eager load code on boot. This avoids loading your whole application
|
||||
# just for the purpose of running a single test. If you are using a tool that
|
||||
# preloads Rails for running tests, you may have to set it to true.
|
||||
config.eager_load = false
|
||||
|
||||
# Configure public file server for tests with Cache-Control for performance.
|
||||
config.public_file_server.enabled = true
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
|
||||
}
|
||||
config.assets.digest = false
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
# The default store, file_store is shared by processes parallelly executed
|
||||
# and should not be used.
|
||||
config.cache_store = :memory_store
|
||||
|
||||
# Raise exceptions instead of rendering exception templates.
|
||||
config.action_dispatch.show_exceptions = false
|
||||
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
config.action_mailer.default_options = { from: 'notifications@localhost' }
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
# The :test delivery method accumulates sent emails in the
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
config.x.otp_secret = '100c7faeef00caa29242f6b04156742bf76065771fd4117990c4282b8748ff3d99f8fdae97c982ab5bd2e6756a159121377cce4421f4a8ecd2d67bd7749a3fb4'
|
||||
|
||||
# Generate random VAPID keys
|
||||
vapid_key = Webpush.generate_key
|
||||
config.x.vapid_private_key = vapid_key.private_key
|
||||
config.x.vapid_public_key = vapid_key.public_key
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
|
||||
config.i18n.default_locale = :en
|
||||
config.i18n.fallbacks = true
|
||||
end
|
||||
|
||||
Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"
|
||||
|
||||
# set fake_data for pam, don't do real calls, just use fake data
|
||||
if ENV['PAM_ENABLED'] == 'true'
|
||||
Rpam2.fake_data =
|
||||
{
|
||||
usernames: Set['pam_user1', 'pam_user2'],
|
||||
servicenames: Set['pam_test', 'pam_test_controlled'],
|
||||
password: '123456',
|
||||
env: { email: 'pam@example.com' }
|
||||
}
|
||||
end
|
||||
62
config/i18n-tasks.yml
Normal file
62
config/i18n-tasks.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
|
||||
|
||||
# The "main" locale.
|
||||
base_locale: en
|
||||
data:
|
||||
read:
|
||||
- config/locales/%{locale}.yml
|
||||
- config/locales/**/*.%{locale}.yml
|
||||
|
||||
write:
|
||||
- ['{devise, simple_form, doorkeeper}.*', 'config/locales/\1.%{locale}.yml']
|
||||
- config/locales/%{locale}.yml
|
||||
|
||||
yaml:
|
||||
write:
|
||||
line_width: -1
|
||||
|
||||
search:
|
||||
paths:
|
||||
- app/
|
||||
- config/navigation.rb
|
||||
|
||||
relative_roots:
|
||||
- app/controllers
|
||||
- app/helpers
|
||||
- app/mailers
|
||||
- app/views
|
||||
|
||||
exclude:
|
||||
- app/assets/images
|
||||
- app/assets/fonts
|
||||
- app/assets/videos
|
||||
|
||||
ignore_missing:
|
||||
- 'activemodel.errors.*'
|
||||
- 'activerecord.attributes.*'
|
||||
- 'activerecord.errors.*'
|
||||
- '{pagination,doorkeeper}.*'
|
||||
- '{date,datetime,time,number}.*'
|
||||
- 'errors.messages.*'
|
||||
- 'activerecord.errors.models.doorkeeper/*'
|
||||
- 'sessions.{browsers,platforms}.*'
|
||||
- 'terms.body_html'
|
||||
- 'application_mailer.salutation'
|
||||
- 'errors.500'
|
||||
- 'auth.providers.*'
|
||||
|
||||
ignore_unused:
|
||||
- 'activemodel.errors.*'
|
||||
- 'activerecord.attributes.*'
|
||||
- 'activerecord.errors.*'
|
||||
- '{devise,pagination,doorkeeper}.*'
|
||||
- '{date,datetime,time,number}.*'
|
||||
- 'simple_form.{yes,no}'
|
||||
- 'simple_form.{placeholders,hints,labels}.*'
|
||||
- 'simple_form.{error_notification,required}.:'
|
||||
- 'errors.messages.*'
|
||||
- 'activerecord.errors.models.doorkeeper/*'
|
||||
- 'errors.429'
|
||||
- 'admin.accounts.roles.*'
|
||||
- 'admin.action_logs.actions.*'
|
||||
- 'statuses.attached.*'
|
||||
15
config/initializers/0_post_deployment_migrations.rb
Normal file
15
config/initializers/0_post_deployment_migrations.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# Post deployment migrations are included by default. This file must be loaded
|
||||
# before other initializers as Rails may otherwise memoize a list of migrations
|
||||
# excluding the post deployment migrations.
|
||||
|
||||
unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS']
|
||||
Rails.application.config.paths['db'].each do |db_path|
|
||||
path = Rails.root.join(db_path, 'post_migrate').to_s
|
||||
|
||||
Rails.application.config.paths['db/migrate'] << path
|
||||
|
||||
# Rails memoizes migrations at certain points where it won't read the above
|
||||
# path just yet. As such we must also update the following list of paths.
|
||||
ActiveRecord::Migrator.migrations_paths << path
|
||||
end
|
||||
end
|
||||
29
config/initializers/1_hosts.rb
Normal file
29
config/initializers/1_hosts.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
port = ENV.fetch('PORT') { 3000 }
|
||||
host = ENV.fetch('LOCAL_DOMAIN') { "localhost:#{port}" }
|
||||
web_host = ENV.fetch('WEB_DOMAIN') { host }
|
||||
|
||||
alternate_domains = ENV.fetch('ALTERNATE_DOMAINS') { '' }
|
||||
|
||||
Rails.application.configure do
|
||||
https = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'
|
||||
|
||||
config.x.local_domain = host
|
||||
config.x.web_domain = web_host
|
||||
config.x.use_https = https
|
||||
config.x.use_s3 = ENV['S3_ENABLED'] == 'true'
|
||||
config.x.use_swift = ENV['SWIFT_ENABLED'] == 'true'
|
||||
|
||||
config.x.alternate_domains = alternate_domains.split(/\s*,\s*/)
|
||||
|
||||
config.action_mailer.default_url_options = { host: web_host, protocol: https ? 'https://' : 'http://', trailing_slash: false }
|
||||
|
||||
config.x.streaming_api_base_url = ENV.fetch('STREAMING_API_BASE_URL') do
|
||||
if Rails.env.production?
|
||||
"ws#{https ? 's' : ''}://#{web_host}"
|
||||
else
|
||||
"ws://#{ENV['REMOTE_DEV'] == 'true' ? host.split(':').first : 'localhost'}:4000"
|
||||
end
|
||||
end
|
||||
end
|
||||
24
config/initializers/active_model_serializers.rb
Normal file
24
config/initializers/active_model_serializers.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
ActiveModelSerializers.config.tap do |config|
|
||||
config.default_includes = '**'
|
||||
end
|
||||
|
||||
ActiveSupport::Notifications.unsubscribe(ActiveModelSerializers::Logging::RENDER_EVENT)
|
||||
|
||||
class ActiveModel::Serializer::Reflection
|
||||
# We monkey-patch this method so that when we include associations in a serializer,
|
||||
# the nested serializers can send information about used contexts upwards back to
|
||||
# the root. We do this via instance_options because the nesting can be dynamic.
|
||||
def build_association(parent_serializer, parent_serializer_options, include_slice = {})
|
||||
serializer = options[:serializer]
|
||||
|
||||
parent_serializer_options.merge!(named_contexts: serializer._named_contexts, context_extensions: serializer._context_extensions) if serializer.respond_to?(:_named_contexts)
|
||||
|
||||
association_options = {
|
||||
parent_serializer: parent_serializer,
|
||||
parent_serializer_options: parent_serializer_options,
|
||||
include_slice: include_slice,
|
||||
}
|
||||
|
||||
ActiveModel::Serializer::Association.new(self, association_options)
|
||||
end
|
||||
end
|
||||
6
config/initializers/application_controller_renderer.rb
Normal file
6
config/initializers/application_controller_renderer.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# ApplicationController.renderer.defaults.merge!(
|
||||
# http_host: 'example.org',
|
||||
# https: false
|
||||
# )
|
||||
13
config/initializers/assets.rb
Normal file
13
config/initializers/assets.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = '1.0'
|
||||
|
||||
# Add additional assets to the asset load path
|
||||
# Rails.application.config.assets.paths << 'node_modules'
|
||||
|
||||
# Precompile additional assets.
|
||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||
# Rails.application.config.assets.precompile += %w()
|
||||
|
||||
Rails.application.config.assets.initialize_on_precompile = true
|
||||
7
config/initializers/backtrace_silencers.rb
Normal file
7
config/initializers/backtrace_silencers.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
||||
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
||||
|
||||
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
||||
# Rails.backtrace_cleaner.remove_silencers!
|
||||
6
config/initializers/blacklists.rb
Normal file
6
config/initializers/blacklists.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
|
||||
config.x.email_domains_whitelist = ENV.fetch('EMAIL_DOMAIN_WHITELIST') { '' }
|
||||
end
|
||||
24
config/initializers/chewy.rb
Normal file
24
config/initializers/chewy.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
enabled = ENV['ES_ENABLED'] == 'true'
|
||||
host = ENV.fetch('ES_HOST') { 'localhost' }
|
||||
port = ENV.fetch('ES_PORT') { 9200 }
|
||||
fallback_prefix = ENV.fetch('REDIS_NAMESPACE') { nil }
|
||||
prefix = ENV.fetch('ES_PREFIX') { fallback_prefix }
|
||||
|
||||
Chewy.settings = {
|
||||
host: "#{host}:#{port}",
|
||||
prefix: prefix,
|
||||
enabled: enabled,
|
||||
journal: false,
|
||||
sidekiq: { queue: 'pull' },
|
||||
}
|
||||
|
||||
Chewy.root_strategy = enabled ? :sidekiq : :bypass
|
||||
Chewy.request_strategy = enabled ? :sidekiq : :bypass
|
||||
|
||||
module Chewy
|
||||
class << self
|
||||
def enabled?
|
||||
settings[:enabled]
|
||||
end
|
||||
end
|
||||
end
|
||||
34
config/initializers/content_security_policy.rb
Normal file
34
config/initializers/content_security_policy.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# Define an application-wide content security policy
|
||||
# For further information see the following documentation
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
||||
|
||||
base_host = Rails.configuration.x.web_domain
|
||||
assets_host = Rails.configuration.action_controller.asset_host
|
||||
assets_host ||= "http#{Rails.configuration.x.use_https ? 's' : ''}://#{base_host}"
|
||||
|
||||
Rails.application.config.content_security_policy do |p|
|
||||
p.base_uri :none
|
||||
p.default_src :none
|
||||
p.frame_ancestors :none
|
||||
p.font_src :self, assets_host
|
||||
p.img_src :self, :https, :data, :blob, assets_host
|
||||
p.style_src :self, :unsafe_inline, assets_host
|
||||
p.media_src :self, :https, :data, assets_host
|
||||
p.frame_src :self, :https
|
||||
p.manifest_src :self, assets_host
|
||||
|
||||
if Rails.env.development?
|
||||
webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{Webpacker.dev_server.host_with_port}" }
|
||||
|
||||
p.connect_src :self, :blob, assets_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls
|
||||
p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host
|
||||
else
|
||||
p.connect_src :self, :blob, assets_host, Rails.configuration.x.streaming_api_base_url
|
||||
p.script_src :self, assets_host
|
||||
end
|
||||
end
|
||||
|
||||
# Report CSP violations to a specified URI
|
||||
# For further information see the following documentation:
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|
||||
# Rails.application.config.content_security_policy_report_only = true
|
||||
5
config/initializers/cookies_serializer.rb
Normal file
5
config/initializers/cookies_serializer.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Specify a serializer for the signed and encrypted cookie jars.
|
||||
# Valid options are :json, :marshal, and :hybrid.
|
||||
Rails.application.config.action_dispatch.cookies_serializer = :json
|
||||
34
config/initializers/cors.rb
Normal file
34
config/initializers/cors.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Avoid CORS issues when API is called from the frontend app.
|
||||
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
|
||||
|
||||
# Read more: https://github.com/cyu/rack-cors
|
||||
|
||||
Rails.application.config.middleware.insert_before 0, Rack::Cors do
|
||||
allow do
|
||||
origins '*'
|
||||
|
||||
resource '/.well-known/*',
|
||||
headers: :any,
|
||||
methods: [:get],
|
||||
credentials: false
|
||||
resource '/@:username',
|
||||
headers: :any,
|
||||
methods: [:get],
|
||||
credentials: false
|
||||
resource '/users/:username',
|
||||
headers: :any,
|
||||
methods: [:get],
|
||||
credentials: false
|
||||
resource '/api/*',
|
||||
headers: :any,
|
||||
methods: [:post, :put, :delete, :get, :patch, :options],
|
||||
credentials: false,
|
||||
expose: ['Link', 'X-RateLimit-Reset', 'X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-Request-Id']
|
||||
resource '/oauth/token',
|
||||
headers: :any,
|
||||
methods: [:post],
|
||||
credentials: false
|
||||
end
|
||||
end
|
||||
3
config/initializers/delivery_job.rb
Normal file
3
config/initializers/delivery_job.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
ActionMailer::DeliveryJob.class_eval do
|
||||
discard_on ActiveJob::DeserializationError
|
||||
end
|
||||
369
config/initializers/devise.rb
Normal file
369
config/initializers/devise.rb
Normal file
@@ -0,0 +1,369 @@
|
||||
Warden::Manager.after_set_user except: :fetch do |user, warden|
|
||||
if user.session_active?(warden.cookies.signed['_session_id'] || warden.raw_session['auth_id'])
|
||||
session_id = warden.cookies.signed['_session_id'] || warden.raw_session['auth_id']
|
||||
else
|
||||
session_id = user.activate_session(warden.request)
|
||||
end
|
||||
|
||||
warden.cookies.signed['_session_id'] = {
|
||||
value: session_id,
|
||||
expires: 1.year.from_now,
|
||||
httponly: true,
|
||||
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
||||
}
|
||||
end
|
||||
|
||||
Warden::Manager.after_fetch do |user, warden|
|
||||
if user.session_active?(warden.cookies.signed['_session_id'] || warden.raw_session['auth_id'])
|
||||
warden.cookies.signed['_session_id'] = {
|
||||
value: warden.cookies.signed['_session_id'] || warden.raw_session['auth_id'],
|
||||
expires: 1.year.from_now,
|
||||
httponly: true,
|
||||
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
||||
}
|
||||
else
|
||||
warden.logout
|
||||
throw :warden, message: :unauthenticated
|
||||
end
|
||||
end
|
||||
|
||||
Warden::Manager.before_logout do |_, warden|
|
||||
SessionActivation.deactivate warden.cookies.signed['_session_id']
|
||||
warden.cookies.delete('_session_id')
|
||||
end
|
||||
|
||||
module Devise
|
||||
mattr_accessor :pam_authentication
|
||||
@@pam_authentication = false
|
||||
mattr_accessor :pam_controlled_service
|
||||
@@pam_controlled_service = nil
|
||||
|
||||
mattr_accessor :check_at_sign
|
||||
@@check_at_sign = false
|
||||
|
||||
mattr_accessor :ldap_authentication
|
||||
@@ldap_authentication = false
|
||||
mattr_accessor :ldap_host
|
||||
@@ldap_host = nil
|
||||
mattr_accessor :ldap_port
|
||||
@@ldap_port = nil
|
||||
mattr_accessor :ldap_method
|
||||
@@ldap_method = nil
|
||||
mattr_accessor :ldap_base
|
||||
@@ldap_base = nil
|
||||
mattr_accessor :ldap_uid
|
||||
@@ldap_uid = nil
|
||||
mattr_accessor :ldap_bind_dn
|
||||
@@ldap_bind_dn = nil
|
||||
mattr_accessor :ldap_password
|
||||
@@ldap_password = nil
|
||||
mattr_accessor :ldap_tls_no_verify
|
||||
@@ldap_tls_no_verify = false
|
||||
mattr_accessor :ldap_search_filter
|
||||
@@ldap_search_filter = nil
|
||||
|
||||
class Strategies::PamAuthenticatable
|
||||
def valid?
|
||||
super && ::Devise.pam_authentication
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Devise.setup do |config|
|
||||
config.warden do |manager|
|
||||
manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_authentication
|
||||
manager.default_strategies(scope: :user).unshift :pam_authenticatable if Devise.pam_authentication
|
||||
manager.default_strategies(scope: :user).unshift :two_factor_authenticatable
|
||||
manager.default_strategies(scope: :user).unshift :two_factor_backupable
|
||||
end
|
||||
|
||||
# The secret key used by Devise. Devise uses this key to generate
|
||||
# random tokens. Changing this key will render invalid all existing
|
||||
# confirmation, reset password and unlock tokens in the database.
|
||||
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
|
||||
# by default. You can change it below and use your own secret key.
|
||||
# config.secret_key = '2f86974c4dd7735170fd70fbf399f7a477ffd635ef240d07a22cf4bd7cd13dbae17c4383a2996d0c1e79a991ec18a91a17424c53e4771adb75a8b21904bd1403'
|
||||
|
||||
# ==> Mailer Configuration
|
||||
# Configure the e-mail address which will be shown in Devise::Mailer,
|
||||
# note that it will be overwritten if you use your own mailer class
|
||||
# with default "from" parameter.
|
||||
# config.mailer_sender = ENV['SMTP_FROM_ADDRESS'] || 'notifications@localhost'
|
||||
|
||||
# Configure the class responsible to send e-mails.
|
||||
config.mailer = 'UserMailer'
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default) and
|
||||
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
||||
# available as additional gems.
|
||||
require 'devise/orm/active_record'
|
||||
|
||||
# ==> Configuration for any authentication mechanism
|
||||
# Configure which keys are used when authenticating a user. The default is
|
||||
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||
# authenticating a user, both parameters are required. Remember that those
|
||||
# parameters are used only when authenticating and not when retrieving from
|
||||
# session. If you need permissions, you should implement that in a before filter.
|
||||
# You can also supply a hash where the value is a boolean determining whether
|
||||
# or not authentication should be aborted when the value is not present.
|
||||
# config.authentication_keys = [:email]
|
||||
|
||||
# Configure parameters from the request object used for authentication. Each entry
|
||||
# given should be a request method and it will automatically be passed to the
|
||||
# find_for_authentication method and considered in your model lookup. For instance,
|
||||
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
|
||||
# The same considerations mentioned for authentication_keys also apply to request_keys.
|
||||
# config.request_keys = []
|
||||
|
||||
# Configure which authentication keys should be case-insensitive.
|
||||
# These keys will be downcased upon creating or modifying a user and when used
|
||||
# to authenticate or find a user. Default is :email.
|
||||
config.case_insensitive_keys = [:email]
|
||||
|
||||
# Configure which authentication keys should have whitespace stripped.
|
||||
# These keys will have whitespace before and after removed upon creating or
|
||||
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||
config.strip_whitespace_keys = [:email]
|
||||
|
||||
# Tell if authentication through request.params is enabled. True by default.
|
||||
# It can be set to an array that will enable params authentication only for the
|
||||
# given strategies, for example, `config.params_authenticatable = [:database]` will
|
||||
# enable it only for database (email + password) authentication.
|
||||
# config.params_authenticatable = true
|
||||
|
||||
# Tell if authentication through HTTP Auth is enabled. False by default.
|
||||
# It can be set to an array that will enable http authentication only for the
|
||||
# given strategies, for example, `config.http_authenticatable = [:database]` will
|
||||
# enable it only for database authentication. The supported strategies are:
|
||||
# :database = Support basic authentication with authentication key + password
|
||||
config.http_authenticatable = [:pam, :database]
|
||||
|
||||
# If 401 status code should be returned for AJAX requests. True by default.
|
||||
# config.http_authenticatable_on_xhr = true
|
||||
|
||||
# The realm used in Http Basic Authentication. 'Application' by default.
|
||||
# config.http_authentication_realm = 'Application'
|
||||
|
||||
# It will change confirmation, password recovery and other workflows
|
||||
# to behave the same regardless if the e-mail provided was right or wrong.
|
||||
# Does not affect registerable.
|
||||
# See : https://github.com/plataformatec/devise/wiki/How-To:-Using-paranoid-mode,-avoid-user-enumeration-on-registerable
|
||||
config.paranoid = true
|
||||
|
||||
# By default Devise will store the user in session. You can skip storage for
|
||||
# particular strategies by setting this option.
|
||||
# Notice that if you are skipping storage for all authentication paths, you
|
||||
# may want to disable generating routes to Devise's sessions controller by
|
||||
# passing skip: :sessions to `devise_for` in your config/routes.rb
|
||||
config.skip_session_storage = [:http_auth]
|
||||
|
||||
# By default, Devise cleans up the CSRF token on authentication to
|
||||
# avoid CSRF token fixation attacks. This means that, when using AJAX
|
||||
# requests for sign in and sign up, you need to get a new CSRF token
|
||||
# from the server. You can disable this option at your own risk.
|
||||
# config.clean_up_csrf_token_on_authentication = true
|
||||
|
||||
# ==> Configuration for :database_authenticatable
|
||||
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
||||
# using other encryptors, it sets how many times you want the password re-encrypted.
|
||||
#
|
||||
# Limiting the stretches to just one in testing will increase the performance of
|
||||
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
|
||||
# a value less than 10 in other environments. Note that, for bcrypt (the default
|
||||
# encryptor), the cost increases exponentially with the number of stretches (e.g.
|
||||
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
|
||||
config.stretches = Rails.env.test? ? 1 : 10
|
||||
|
||||
# Setup a pepper to generate the encrypted password.
|
||||
# config.pepper = '104d16705f794923e77c5e5167b52452d00646dc952a2d30b541c24086e647012c7b9625f253c51912e455981e503446772973d5f1638631196c819d7137fad4'
|
||||
|
||||
# Send a notification to the original email when the user's email is changed.
|
||||
config.send_email_changed_notification = true
|
||||
|
||||
# Send a notification email when the user's password is changed
|
||||
config.send_password_change_notification = true
|
||||
|
||||
# ==> Configuration for :confirmable
|
||||
# A period that the user is allowed to access the website even without
|
||||
# confirming their account. For instance, if set to 2.days, the user will be
|
||||
# able to access the website for two days without confirming their account,
|
||||
# access will be blocked just in the third day. Default is 0.days, meaning
|
||||
# the user cannot access the website without confirming their account.
|
||||
# config.allow_unconfirmed_access_for = 2.days
|
||||
|
||||
# A period that the user is allowed to confirm their account before their
|
||||
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
||||
# their account within 3 days after the mail was sent, but on the fourth day
|
||||
# their account can't be confirmed with the token any more.
|
||||
# Default is nil, meaning there is no restriction on how long a user can take
|
||||
# before confirming their account.
|
||||
config.confirm_within = 2.days
|
||||
|
||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||
# db field (see migrations). Until confirmed, new email is stored in
|
||||
# unconfirmed_email column, and copied to email column on successful confirmation.
|
||||
config.reconfirmable = true
|
||||
|
||||
# Defines which key will be used when confirming an account
|
||||
# config.confirmation_keys = [:email]
|
||||
|
||||
# ==> Configuration for :rememberable
|
||||
# The time the user will be remembered without asking for credentials again.
|
||||
config.remember_for = 1.year
|
||||
|
||||
# Invalidates all the remember me tokens when the user signs out.
|
||||
config.expire_all_remember_me_on_sign_out = true
|
||||
|
||||
# If true, extends the user's remember period when remembered via cookie.
|
||||
# config.extend_remember_period = false
|
||||
|
||||
# Options to be passed to the created cookie. For instance, you can set
|
||||
# secure: true in order to force SSL only cookies.
|
||||
config.rememberable_options = { secure: true }
|
||||
|
||||
# ==> Configuration for :validatable
|
||||
# Range for password length.
|
||||
config.password_length = 8..72
|
||||
|
||||
# Email regex used to validate email formats. It simply asserts that
|
||||
# one (and only one) @ exists in the given string. This is mainly
|
||||
# to give user feedback and not to assert the e-mail validity.
|
||||
# config.email_regexp = /\A[^@]+@[^@]+\z/
|
||||
|
||||
# ==> Configuration for :timeoutable
|
||||
# The time you want to timeout the user session without activity. After this
|
||||
# time the user will be asked for credentials again. Default is 30 minutes.
|
||||
# config.timeout_in = 30.minutes
|
||||
|
||||
# ==> Configuration for :lockable
|
||||
# Defines which strategy will be used to lock an account.
|
||||
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
|
||||
# :none = No lock strategy. You should handle locking by yourself.
|
||||
# config.lock_strategy = :failed_attempts
|
||||
|
||||
# Defines which key will be used when locking and unlocking an account
|
||||
# config.unlock_keys = [:email]
|
||||
|
||||
# Defines which strategy will be used to unlock an account.
|
||||
# :email = Sends an unlock link to the user email
|
||||
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
||||
# :both = Enables both strategies
|
||||
# :none = No unlock strategy. You should handle unlocking by yourself.
|
||||
# config.unlock_strategy = :both
|
||||
|
||||
# Number of authentication tries before locking an account if lock_strategy
|
||||
# is failed attempts.
|
||||
# config.maximum_attempts = 20
|
||||
|
||||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# Warn on the last attempt before the account is locked.
|
||||
# config.last_attempt_warning = true
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
# Defines which key will be used when recovering the password for an account
|
||||
# config.reset_password_keys = [:email]
|
||||
|
||||
# Time interval you can reset your password with a reset password key.
|
||||
# Don't put a too small interval or your users won't have the time to
|
||||
# change their passwords.
|
||||
config.reset_password_within = 6.hours
|
||||
|
||||
# When set to false, does not sign a user in automatically after their password is
|
||||
# reset. Defaults to true, so a user is signed in automatically after a reset.
|
||||
config.sign_in_after_reset_password = false
|
||||
|
||||
# ==> Configuration for :encryptable
|
||||
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
|
||||
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
|
||||
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
|
||||
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
|
||||
# REST_AUTH_SITE_KEY to pepper).
|
||||
#
|
||||
# Require the `devise-encryptable` gem when using anything other than bcrypt
|
||||
# config.encryptor = :sha512
|
||||
|
||||
# ==> Scopes configuration
|
||||
# Turn scoped views on. Before rendering "sessions/new", it will first check for
|
||||
# "users/sessions/new". It's turned off by default because it's slower if you
|
||||
# are using only default views.
|
||||
# config.scoped_views = false
|
||||
|
||||
# Configure the default scope given to Warden. By default it's the first
|
||||
# devise role declared in your routes (usually :user).
|
||||
# config.default_scope = :user
|
||||
|
||||
# Set this configuration to false if you want /users/sign_out to sign out
|
||||
# only the current scope. By default, Devise signs out all scopes.
|
||||
# config.sign_out_all_scopes = true
|
||||
|
||||
# ==> Navigation configuration
|
||||
# Lists the formats that should be treated as navigational. Formats like
|
||||
# :html, should redirect to the sign in page when the user does not have
|
||||
# access, but formats like :xml or :json, should return 401.
|
||||
#
|
||||
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||
# should add them to the navigational formats lists.
|
||||
#
|
||||
# The "*/*" below is required to match Internet Explorer requests.
|
||||
# config.navigational_formats = ['*/*', :html]
|
||||
|
||||
# The default HTTP method used to sign out a resource. Default is :delete.
|
||||
config.sign_out_via = :delete
|
||||
|
||||
# ==> OmniAuth
|
||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||
# up on your models and hooks.
|
||||
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not supported by Devise, or
|
||||
# change the failure app, you can configure them inside the config.warden block.
|
||||
#
|
||||
# config.warden do |manager|
|
||||
# manager.intercept_401 = false
|
||||
# manager.default_strategies(scope: :user).unshift :some_external_strategy
|
||||
# end
|
||||
|
||||
# ==> Mountable engine configurations
|
||||
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
|
||||
# is mountable, there are some extra configurations to be taken into account.
|
||||
# The following options are available, assuming the engine is mounted as:
|
||||
#
|
||||
# mount MyEngine, at: '/my_engine'
|
||||
#
|
||||
# The router that invoked `devise_for`, in the example above, would be:
|
||||
# config.router_name = :my_engine
|
||||
#
|
||||
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
|
||||
# so you need to do it manually. For the users scope, it would be:
|
||||
# config.omniauth_path_prefix = '/my_engine/users/auth'
|
||||
|
||||
if ENV['PAM_ENABLED'] == 'true'
|
||||
config.pam_authentication = true
|
||||
config.usernamefield = nil
|
||||
config.emailfield = 'email'
|
||||
config.check_at_sign = true
|
||||
config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] }
|
||||
config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' }
|
||||
config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE') { nil }
|
||||
end
|
||||
|
||||
if ENV['LDAP_ENABLED'] == 'true'
|
||||
config.ldap_authentication = true
|
||||
config.check_at_sign = true
|
||||
config.ldap_host = ENV.fetch('LDAP_HOST', 'localhost')
|
||||
config.ldap_port = ENV.fetch('LDAP_PORT', 389).to_i
|
||||
config.ldap_method = ENV.fetch('LDAP_METHOD', :simple_tls).to_sym
|
||||
config.ldap_base = ENV.fetch('LDAP_BASE')
|
||||
config.ldap_bind_dn = ENV.fetch('LDAP_BIND_DN')
|
||||
config.ldap_password = ENV.fetch('LDAP_PASSWORD')
|
||||
config.ldap_uid = ENV.fetch('LDAP_UID', 'cn')
|
||||
config.ldap_tls_no_verify = ENV['LDAP_TLS_NO_VERIFY'] == 'true'
|
||||
config.ldap_search_filter = ENV.fetch('LDAP_SEARCH_FILTER', '%{uid}=%{email}')
|
||||
end
|
||||
end
|
||||
138
config/initializers/doorkeeper.rb
Normal file
138
config/initializers/doorkeeper.rb
Normal file
@@ -0,0 +1,138 @@
|
||||
Doorkeeper.configure do
|
||||
# Change the ORM that doorkeeper will use (needs plugins)
|
||||
orm :active_record
|
||||
|
||||
# This block will be called to check whether the resource owner is authenticated or not.
|
||||
resource_owner_authenticator do
|
||||
current_user || redirect_to(new_user_session_url)
|
||||
end
|
||||
|
||||
resource_owner_from_credentials do |_routes|
|
||||
user = User.find_by(email: request.params[:username])
|
||||
user if !user&.otp_required_for_login? && user&.valid_password?(request.params[:password])
|
||||
end
|
||||
|
||||
# If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
|
||||
admin_authenticator do
|
||||
current_user&.admin? || redirect_to(new_user_session_url)
|
||||
end
|
||||
|
||||
# Authorization Code expiration time (default 10 minutes).
|
||||
# authorization_code_expires_in 10.minutes
|
||||
|
||||
# Access token expiration time (default 2 hours).
|
||||
# If you want to disable expiration, set this to nil.
|
||||
access_token_expires_in nil
|
||||
|
||||
# Assign a custom TTL for implicit grants.
|
||||
# custom_access_token_expires_in do |oauth_client|
|
||||
# oauth_client.application.additional_settings.implicit_oauth_expiration
|
||||
# end
|
||||
|
||||
# Use a custom class for generating the access token.
|
||||
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
||||
# access_token_generator "::Doorkeeper::JWT"
|
||||
|
||||
# The controller Doorkeeper::ApplicationController inherits from.
|
||||
# Defaults to ActionController::Base.
|
||||
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
||||
base_controller 'ApplicationController'
|
||||
|
||||
# Reuse access token for the same resource owner within an application (disabled by default)
|
||||
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
||||
reuse_access_token
|
||||
|
||||
# Issue access tokens with refresh token (disabled by default)
|
||||
# use_refresh_token
|
||||
|
||||
# Provide support for an owner to be assigned to each registered application (disabled by default)
|
||||
# Optional parameter :confirmation => true (default false) if you want to enforce ownership of
|
||||
# a registered application
|
||||
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
|
||||
enable_application_owner
|
||||
|
||||
# Define access token scopes for your provider
|
||||
# For more information go to
|
||||
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
|
||||
default_scopes :read
|
||||
optional_scopes :write,
|
||||
:'write:accounts',
|
||||
:'write:blocks',
|
||||
:'write:conversations',
|
||||
:'write:favourites',
|
||||
:'write:filters',
|
||||
:'write:follows',
|
||||
:'write:lists',
|
||||
:'write:media',
|
||||
:'write:mutes',
|
||||
:'write:notifications',
|
||||
:'write:reports',
|
||||
:'write:statuses',
|
||||
:read,
|
||||
:'read:accounts',
|
||||
:'read:blocks',
|
||||
:'read:favourites',
|
||||
:'read:filters',
|
||||
:'read:follows',
|
||||
:'read:lists',
|
||||
:'read:mutes',
|
||||
:'read:notifications',
|
||||
:'read:search',
|
||||
:'read:statuses',
|
||||
:follow,
|
||||
:push
|
||||
|
||||
# Change the way client credentials are retrieved from the request object.
|
||||
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
||||
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
|
||||
# Check out the wiki for more information on customization
|
||||
# client_credentials :from_basic, :from_params
|
||||
|
||||
# Change the way access token is authenticated from the request object.
|
||||
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
||||
# falls back to the `:access_token` or `:bearer_token` params from the `params` object.
|
||||
# Check out the wiki for more information on customization
|
||||
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
|
||||
|
||||
# Change the native redirect uri for client apps
|
||||
# When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
|
||||
# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
|
||||
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
|
||||
#
|
||||
# native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
|
||||
|
||||
# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
|
||||
# by default in non-development environments). OAuth2 delegates security in
|
||||
# communication to the HTTPS protocol so it is wise to keep this enabled.
|
||||
#
|
||||
force_ssl_in_redirect_uri false
|
||||
|
||||
# Specify what grant flows are enabled in array of Strings. The valid
|
||||
# strings and the flows they enable are:
|
||||
#
|
||||
# "authorization_code" => Authorization Code Grant Flow
|
||||
# "implicit" => Implicit Grant Flow
|
||||
# "password" => Resource Owner Password Credentials Grant Flow
|
||||
# "client_credentials" => Client Credentials Grant Flow
|
||||
#
|
||||
# If not specified, Doorkeeper enables authorization_code and
|
||||
# client_credentials.
|
||||
#
|
||||
# implicit and password grant flows have risks that you should understand
|
||||
# before enabling:
|
||||
# http://tools.ietf.org/html/rfc6819#section-4.4.2
|
||||
# http://tools.ietf.org/html/rfc6819#section-4.4.3
|
||||
#
|
||||
|
||||
grant_flows %w(authorization_code password client_credentials)
|
||||
|
||||
# Under some circumstances you might want to have applications auto-approved,
|
||||
# so that the user skips the authorization step.
|
||||
# For example if dealing with a trusted application.
|
||||
skip_authorization do |resource_owner, client|
|
||||
client.application.superapp?
|
||||
end
|
||||
|
||||
# WWW-Authenticate Realm (default "Doorkeeper").
|
||||
# realm "Doorkeeper"
|
||||
end
|
||||
5
config/initializers/fast_blank.rb
Normal file
5
config/initializers/fast_blank.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
if String.method_defined?(:blank_as?)
|
||||
class String
|
||||
alias_method :blank?, :blank_as?
|
||||
end
|
||||
end
|
||||
3
config/initializers/ffmpeg.rb
Normal file
3
config/initializers/ffmpeg.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
if ENV['FFMPEG_BINARY'].present?
|
||||
FFMPEG.ffmpeg_binary = ENV['FFMPEG_BINARY']
|
||||
end
|
||||
4
config/initializers/filter_parameter_logging.rb
Normal file
4
config/initializers/filter_parameter_logging.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
Rails.application.config.filter_parameters += [:password, :private_key, :public_key, :otp_attempt]
|
||||
24
config/initializers/http_client_proxy.rb
Normal file
24
config/initializers/http_client_proxy.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
Rails.application.configure do
|
||||
config.x.http_client_proxy = {}
|
||||
if ENV['http_proxy'].present?
|
||||
proxy = URI.parse(ENV['http_proxy'])
|
||||
raise "Unsupported proxy type: #{proxy.scheme}" unless %w(http https).include? proxy.scheme
|
||||
raise "No proxy host" unless proxy.host
|
||||
|
||||
host = proxy.host
|
||||
host = host[1...-1] if host[0] == '[' # for IPv6 address
|
||||
config.x.http_client_proxy[:proxy] = { proxy_address: host, proxy_port: proxy.port, proxy_username: proxy.user, proxy_password: proxy.password }.compact
|
||||
end
|
||||
|
||||
config.x.access_to_hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
|
||||
end
|
||||
|
||||
module Goldfinger
|
||||
def self.finger(uri, opts = {})
|
||||
to_hidden = /\.(onion|i2p)(:\d+)?$/.match(uri)
|
||||
raise GabSocial::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && to_hidden
|
||||
opts = { ssl: !to_hidden, headers: {} }.merge(Rails.configuration.x.http_client_proxy).merge(opts)
|
||||
opts[:headers]['User-Agent'] ||= GabSocial::Version.user_agent
|
||||
Goldfinger::Client.new(uri, opts).finger
|
||||
end
|
||||
end
|
||||
5
config/initializers/httplog.rb
Normal file
5
config/initializers/httplog.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
HttpLog.configure do |config|
|
||||
config.logger = Rails.logger
|
||||
config.color = { color: :yellow }
|
||||
config.compact_log = true
|
||||
end
|
||||
21
config/initializers/inflections.rb
Normal file
21
config/initializers/inflections.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new inflection rules using the following format. Inflections
|
||||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, '\1en'
|
||||
# inflect.singular /^(ox)en/i, '\1'
|
||||
# inflect.irregular 'person', 'people'
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
|
||||
ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
inflect.acronym 'StatsD'
|
||||
inflect.acronym 'OEmbed'
|
||||
inflect.acronym 'OStatus'
|
||||
inflect.acronym 'ActivityPub'
|
||||
inflect.acronym 'PubSubHubbub'
|
||||
inflect.acronym 'ActivityStreams'
|
||||
inflect.acronym 'JsonLd'
|
||||
end
|
||||
18
config/initializers/instrumentation.rb
Normal file
18
config/initializers/instrumentation.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
instrumentation_hostname = ENV.fetch('INSTRUMENTATION_HOSTNAME') { 'localhost' }
|
||||
|
||||
ActiveSupport::Notifications.subscribe(/process_action.action_controller/) do |*args|
|
||||
event = ActiveSupport::Notifications::Event.new(*args)
|
||||
controller = event.payload[:controller]
|
||||
action = event.payload[:action]
|
||||
format = event.payload[:format] || 'all'
|
||||
format = 'all' if format == '*/*'
|
||||
status = event.payload[:status]
|
||||
key = "#{controller}.#{action}.#{format}.#{instrumentation_hostname}"
|
||||
|
||||
ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.total_duration", value: event.duration
|
||||
ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.db_time", value: event.payload[:db_runtime]
|
||||
ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.view_time", value: event.payload[:view_runtime]
|
||||
ActiveSupport::Notifications.instrument :performance, measurement: "#{key}.status.#{status}"
|
||||
end
|
||||
3
config/initializers/json_ld.rb
Normal file
3
config/initializers/json_ld.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../lib/json_ld/security'
|
||||
7
config/initializers/kaminari_config.rb
Normal file
7
config/initializers/kaminari_config.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Kaminari.configure do |config|
|
||||
config.default_per_page = 40
|
||||
config.window = 1
|
||||
config.outer_window = 1
|
||||
end
|
||||
4
config/initializers/mime_types.rb
Normal file
4
config/initializers/mime_types.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
Mime::Type.register 'application/json', :json, %w(text/x-json application/jsonrequest application/jrd+json application/activity+json application/ld+json)
|
||||
Mime::Type.register 'text/xml', :xml, %w(application/xml application/atom+xml application/xrd+xml)
|
||||
1
config/initializers/oj.rb
Normal file
1
config/initializers/oj.rb
Normal file
@@ -0,0 +1 @@
|
||||
Oj.default_options = { mode: :compat, time_format: :ruby, use_to_json: true }
|
||||
65
config/initializers/omniauth.rb
Normal file
65
config/initializers/omniauth.rb
Normal file
@@ -0,0 +1,65 @@
|
||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
# Vanilla omniauth stategies
|
||||
end
|
||||
|
||||
Devise.setup do |config|
|
||||
# Devise omniauth strategies
|
||||
options = {}
|
||||
options[:redirect_at_sign_in] = ENV['OAUTH_REDIRECT_AT_SIGN_IN'] == 'true'
|
||||
|
||||
# CAS strategy
|
||||
if ENV['CAS_ENABLED'] == 'true'
|
||||
cas_options = options
|
||||
cas_options[:url] = ENV['CAS_URL'] if ENV['CAS_URL']
|
||||
cas_options[:host] = ENV['CAS_HOST'] if ENV['CAS_HOST']
|
||||
cas_options[:port] = ENV['CAS_PORT'] if ENV['CAS_PORT']
|
||||
cas_options[:ssl] = ENV['CAS_SSL'] == 'true' if ENV['CAS_SSL']
|
||||
cas_options[:service_validate_url] = ENV['CAS_VALIDATE_URL'] if ENV['CAS_VALIDATE_URL']
|
||||
cas_options[:callback_url] = ENV['CAS_CALLBACK_URL'] if ENV['CAS_CALLBACK_URL']
|
||||
cas_options[:logout_url] = ENV['CAS_LOGOUT_URL'] if ENV['CAS_LOGOUT_URL']
|
||||
cas_options[:login_url] = ENV['CAS_LOGIN_URL'] if ENV['CAS_LOGIN_URL']
|
||||
cas_options[:uid_field] = ENV['CAS_UID_FIELD'] || 'user' if ENV['CAS_UID_FIELD']
|
||||
cas_options[:ca_path] = ENV['CAS_CA_PATH'] if ENV['CAS_CA_PATH']
|
||||
cas_options[:disable_ssl_verification] = ENV['CAS_DISABLE_SSL_VERIFICATION'] == 'true'
|
||||
cas_options[:uid_key] = ENV['CAS_UID_KEY'] || 'user'
|
||||
cas_options[:name_key] = ENV['CAS_NAME_KEY'] || 'name'
|
||||
cas_options[:email_key] = ENV['CAS_EMAIL_KEY'] || 'email'
|
||||
cas_options[:nickname_key] = ENV['CAS_NICKNAME_KEY'] || 'nickname'
|
||||
cas_options[:first_name_key] = ENV['CAS_FIRST_NAME_KEY'] || 'firstname'
|
||||
cas_options[:last_name_key] = ENV['CAS_LAST_NAME_KEY'] || 'lastname'
|
||||
cas_options[:location_key] = ENV['CAS_LOCATION_KEY'] || 'location'
|
||||
cas_options[:image_key] = ENV['CAS_IMAGE_KEY'] || 'image'
|
||||
cas_options[:phone_key] = ENV['CAS_PHONE_KEY'] || 'phone'
|
||||
config.omniauth :cas, cas_options
|
||||
end
|
||||
|
||||
# SAML strategy
|
||||
if ENV['SAML_ENABLED'] == 'true'
|
||||
saml_options = options
|
||||
saml_options[:assertion_consumer_service_url] = ENV['SAML_ACS_URL'] if ENV['SAML_ACS_URL']
|
||||
saml_options[:issuer] = ENV['SAML_ISSUER'] if ENV['SAML_ISSUER']
|
||||
saml_options[:idp_sso_target_url] = ENV['SAML_IDP_SSO_TARGET_URL'] if ENV['SAML_IDP_SSO_TARGET_URL']
|
||||
saml_options[:idp_sso_target_url_runtime_params] = ENV['SAML_IDP_SSO_TARGET_PARAMS'] if ENV['SAML_IDP_SSO_TARGET_PARAMS'] # FIXME: Should be parsable Hash
|
||||
saml_options[:idp_cert] = ENV['SAML_IDP_CERT'] if ENV['SAML_IDP_CERT']
|
||||
saml_options[:idp_cert_fingerprint] = ENV['SAML_IDP_CERT_FINGERPRINT'] if ENV['SAML_IDP_CERT_FINGERPRINT']
|
||||
saml_options[:idp_cert_fingerprint_validator] = ENV['SAML_IDP_CERT_FINGERPRINT_VALIDATOR'] if ENV['SAML_IDP_CERT_FINGERPRINT_VALIDATOR'] # FIXME: Should be Lambda { |fingerprint| }
|
||||
saml_options[:name_identifier_format] = ENV['SAML_NAME_IDENTIFIER_FORMAT'] if ENV['SAML_NAME_IDENTIFIER_FORMAT']
|
||||
saml_options[:request_attributes] = {}
|
||||
saml_options[:certificate] = ENV['SAML_CERT'] if ENV['SAML_CERT']
|
||||
saml_options[:private_key] = ENV['SAML_PRIVATE_KEY'] if ENV['SAML_PRIVATE_KEY']
|
||||
saml_options[:security] = {}
|
||||
saml_options[:security][:want_assertions_signed] = ENV['SAML_SECURITY_WANT_ASSERTION_SIGNED'] == 'true'
|
||||
saml_options[:security][:want_assertions_encrypted] = ENV['SAML_SECURITY_WANT_ASSERTION_ENCRYPTED'] == 'true'
|
||||
saml_options[:security][:assume_email_is_verified] = ENV['SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED'] == 'true'
|
||||
saml_options[:attribute_statements] = {}
|
||||
saml_options[:attribute_statements][:uid] = [ENV['SAML_ATTRIBUTES_STATEMENTS_UID']] if ENV['SAML_ATTRIBUTES_STATEMENTS_UID']
|
||||
saml_options[:attribute_statements][:email] = [ENV['SAML_ATTRIBUTES_STATEMENTS_EMAIL']] if ENV['SAML_ATTRIBUTES_STATEMENTS_EMAIL']
|
||||
saml_options[:attribute_statements][:full_name] = [ENV['SAML_ATTRIBUTES_STATEMENTS_FULL_NAME']] if ENV['SAML_ATTRIBUTES_STATEMENTS_FULL_NAME']
|
||||
saml_options[:attribute_statements][:first_name] = [ENV['SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME']] if ENV['SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME']
|
||||
saml_options[:attribute_statements][:last_name] = [ENV['SAML_ATTRIBUTES_STATEMENTS_LAST_NAME']] if ENV['SAML_ATTRIBUTES_STATEMENTS_LAST_NAME']
|
||||
saml_options[:attribute_statements][:verified] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']
|
||||
saml_options[:attribute_statements][:verified_email] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']
|
||||
saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE']
|
||||
config.omniauth :saml, saml_options
|
||||
end
|
||||
end
|
||||
8
config/initializers/open_uri_redirection.rb
Normal file
8
config/initializers/open_uri_redirection.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
require 'open-uri'
|
||||
|
||||
module OpenURI
|
||||
def self.redirectable?(uri1, uri2) # :nodoc:
|
||||
uri1.scheme.casecmp(uri2.scheme).zero? ||
|
||||
(/\A(?:http|https|ftp)\z/i =~ uri1.scheme && /\A(?:http|https|ftp)\z/i =~ uri2.scheme)
|
||||
end
|
||||
end
|
||||
0
config/initializers/pagination.rb
Normal file
0
config/initializers/pagination.rb
Normal file
86
config/initializers/paperclip.rb
Normal file
86
config/initializers/paperclip.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Paperclip.options[:read_timeout] = 60
|
||||
|
||||
Paperclip.interpolates :filename do |attachment, style|
|
||||
return attachment.original_filename if style == :original
|
||||
[basename(attachment, style), extension(attachment, style)].delete_if(&:blank?).join('.')
|
||||
end
|
||||
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
use_timestamp: false,
|
||||
path: ':class/:attachment/:id_partition/:style/:filename',
|
||||
storage: :fog
|
||||
)
|
||||
|
||||
if ENV['S3_ENABLED'] == 'true'
|
||||
require 'aws-sdk-s3'
|
||||
|
||||
s3_region = ENV.fetch('S3_REGION') { 'us-east-1' }
|
||||
s3_protocol = ENV.fetch('S3_PROTOCOL') { 'https' }
|
||||
s3_hostname = ENV.fetch('S3_HOSTNAME') { "s3-#{s3_region}.amazonaws.com" }
|
||||
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
storage: :s3,
|
||||
s3_protocol: s3_protocol,
|
||||
s3_host_name: s3_hostname,
|
||||
s3_headers: {
|
||||
'Cache-Control' => 'public, max-age=315576000, immutable',
|
||||
},
|
||||
s3_permissions: ENV.fetch('S3_PERMISSION') { 'public-read' },
|
||||
s3_region: s3_region,
|
||||
s3_credentials: {
|
||||
bucket: ENV['S3_BUCKET'],
|
||||
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
||||
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
|
||||
},
|
||||
s3_options: {
|
||||
signature_version: ENV.fetch('S3_SIGNATURE_VERSION') { 'v4' },
|
||||
http_open_timeout: 5,
|
||||
http_read_timeout: 5,
|
||||
http_idle_timeout: 5,
|
||||
}
|
||||
)
|
||||
|
||||
if ENV.has_key?('S3_ENDPOINT')
|
||||
Paperclip::Attachment.default_options[:s3_options].merge!(
|
||||
endpoint: ENV['S3_ENDPOINT'],
|
||||
force_path_style: true
|
||||
)
|
||||
Paperclip::Attachment.default_options[:url] = ':s3_path_url'
|
||||
end
|
||||
|
||||
if ENV.has_key?('S3_ALIAS_HOST') || ENV.has_key?('S3_CLOUDFRONT_HOST')
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
url: ':s3_alias_url',
|
||||
s3_host_alias: ENV['S3_ALIAS_HOST'] || ENV['S3_CLOUDFRONT_HOST']
|
||||
)
|
||||
end
|
||||
elsif ENV['SWIFT_ENABLED'] == 'true'
|
||||
require 'fog/openstack'
|
||||
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
fog_credentials: {
|
||||
provider: 'OpenStack',
|
||||
openstack_username: ENV['SWIFT_USERNAME'],
|
||||
openstack_project_id: ENV['SWIFT_PROJECT_ID'],
|
||||
openstack_project_name: ENV['SWIFT_TENANT'],
|
||||
openstack_tenant: ENV['SWIFT_TENANT'], # Some OpenStack-v2 ignores project_name but needs tenant
|
||||
openstack_api_key: ENV['SWIFT_PASSWORD'],
|
||||
openstack_auth_url: ENV['SWIFT_AUTH_URL'],
|
||||
openstack_domain_name: ENV.fetch('SWIFT_DOMAIN_NAME') { 'default' },
|
||||
openstack_region: ENV['SWIFT_REGION'],
|
||||
openstack_cache_ttl: ENV.fetch('SWIFT_CACHE_TTL') { 60 },
|
||||
},
|
||||
fog_directory: ENV['SWIFT_CONTAINER'],
|
||||
fog_host: ENV['SWIFT_OBJECT_URL'],
|
||||
fog_public: true
|
||||
)
|
||||
else
|
||||
Paperclip::Attachment.default_options.merge!(
|
||||
storage: :filesystem,
|
||||
use_timestamp: true,
|
||||
path: (ENV['PAPERCLIP_ROOT_PATH'] || ':rails_root/public/system') + '/:class/:attachment/:id_partition/:style/:filename',
|
||||
url: (ENV['PAPERCLIP_ROOT_URL'] || '/system') + '/:class/:attachment/:id_partition/:style/:filename',
|
||||
)
|
||||
end
|
||||
6
config/initializers/premailer_rails.rb
Normal file
6
config/initializers/premailer_rails.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
require_relative '../../lib/gabsocial/premailer_webpack_strategy'
|
||||
|
||||
Premailer::Rails.config.merge!(remove_ids: true,
|
||||
adapter: :nokogiri,
|
||||
generate_text_part: false,
|
||||
strategies: [PremailerWebpackStrategy])
|
||||
109
config/initializers/rack_attack.rb
Normal file
109
config/initializers/rack_attack.rb
Normal file
@@ -0,0 +1,109 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'doorkeeper/grape/authorization_decorator'
|
||||
|
||||
class Rack::Attack
|
||||
class Request
|
||||
def authenticated_token
|
||||
return @token if defined?(@token)
|
||||
|
||||
@token = Doorkeeper::OAuth::Token.authenticate(
|
||||
Doorkeeper::Grape::AuthorizationDecorator.new(self),
|
||||
*Doorkeeper.configuration.access_token_methods
|
||||
)
|
||||
end
|
||||
|
||||
def remote_ip
|
||||
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
|
||||
end
|
||||
|
||||
def authenticated_user_id
|
||||
authenticated_token&.resource_owner_id
|
||||
end
|
||||
|
||||
def unauthenticated?
|
||||
!authenticated_user_id
|
||||
end
|
||||
|
||||
def api_request?
|
||||
path.start_with?('/api')
|
||||
end
|
||||
|
||||
def web_request?
|
||||
!api_request?
|
||||
end
|
||||
|
||||
def paging_request?
|
||||
params['page'].present? || params['min_id'].present? || params['max_id'].present? || params['since_id'].present?
|
||||
end
|
||||
end
|
||||
|
||||
PROTECTED_PATHS = %w(
|
||||
/auth/sign_in
|
||||
/auth
|
||||
/auth/password
|
||||
).freeze
|
||||
|
||||
PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ })
|
||||
|
||||
# Always allow requests from localhost
|
||||
# (blocklist & throttles are skipped)
|
||||
Rack::Attack.safelist('allow from localhost') do |req|
|
||||
# Requests are allowed if the return value is truthy
|
||||
req.remote_ip == '127.0.0.1' || req.remote_ip == '::1'
|
||||
end
|
||||
|
||||
throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req|
|
||||
req.authenticated_user_id if req.api_request?
|
||||
end
|
||||
|
||||
throttle('throttle_unauthenticated_api', limit: 300, period: 5.minutes) do |req|
|
||||
req.remote_ip if req.api_request? && req.unauthenticated?
|
||||
end
|
||||
|
||||
throttle('throttle_api_media', limit: 30, period: 30.minutes) do |req|
|
||||
req.authenticated_user_id if req.post? && req.path.start_with?('/api/v1/media')
|
||||
end
|
||||
|
||||
throttle('throttle_media_proxy', limit: 30, period: 30.minutes) do |req|
|
||||
req.remote_ip if req.path.start_with?('/media_proxy')
|
||||
end
|
||||
|
||||
throttle('throttle_api_sign_up', limit: 5, period: 30.minutes) do |req|
|
||||
req.remote_ip if req.post? && req.path == '/api/v1/accounts'
|
||||
end
|
||||
|
||||
# Throttle paging, as it is mainly used for public pages and AP collections
|
||||
throttle('throttle_authenticated_paging', limit: 300, period: 15.minutes) do |req|
|
||||
req.authenticated_user_id if req.paging_request?
|
||||
end
|
||||
|
||||
throttle('throttle_unauthenticated_paging', limit: 300, period: 15.minutes) do |req|
|
||||
req.remote_ip if req.paging_request? && req.unauthenticated?
|
||||
end
|
||||
|
||||
API_DELETE_REBLOG_REGEX = /\A\/api\/v1\/statuses\/[\d]+\/unreblog/.freeze
|
||||
API_DELETE_STATUS_REGEX = /\A\/api\/v1\/statuses\/[\d]+/.freeze
|
||||
|
||||
throttle('throttle_api_delete', limit: 30, period: 30.minutes) do |req|
|
||||
req.authenticated_user_id if (req.post? && req.path =~ API_DELETE_REBLOG_REGEX) || (req.delete? && req.path =~ API_DELETE_STATUS_REGEX)
|
||||
end
|
||||
|
||||
throttle('protected_paths', limit: 25, period: 5.minutes) do |req|
|
||||
req.remote_ip if req.post? && req.path =~ PROTECTED_PATHS_REGEX
|
||||
end
|
||||
|
||||
self.throttled_response = lambda do |env|
|
||||
now = Time.now.utc
|
||||
match_data = env['rack.attack.match_data']
|
||||
|
||||
headers = {
|
||||
'Content-Type' => 'application/json',
|
||||
'X-RateLimit-Limit' => match_data[:limit].to_s,
|
||||
'X-RateLimit-Remaining' => '0',
|
||||
'X-RateLimit-Reset' => (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6),
|
||||
}
|
||||
|
||||
[429, headers, [{ error: I18n.t('errors.429') }.to_json]]
|
||||
end
|
||||
end
|
||||
6
config/initializers/rack_attack_logging.rb
Normal file
6
config/initializers/rack_attack_logging.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
ActiveSupport::Notifications.subscribe(/rack_attack/) do |_name, _start, _finish, _request_id, payload|
|
||||
req = payload[:request]
|
||||
|
||||
next unless [:throttle, :blacklist].include? req.env['rack.attack.match_type']
|
||||
Rails.logger.info("Rate limit hit (#{req.env['rack.attack.match_type']}): #{req.ip} #{req.request_method} #{req.fullpath}")
|
||||
end
|
||||
14
config/initializers/redis.rb
Normal file
14
config/initializers/redis.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
redis_connection = Redis.new(
|
||||
url: ENV['REDIS_URL'],
|
||||
driver: :hiredis
|
||||
)
|
||||
|
||||
namespace = ENV.fetch('REDIS_NAMESPACE') { nil }
|
||||
|
||||
if namespace
|
||||
Redis.current = Redis::Namespace.new(namespace, redis: redis_connection)
|
||||
else
|
||||
Redis.current = redis_connection
|
||||
end
|
||||
5
config/initializers/session_activations.rb
Normal file
5
config/initializers/session_activations.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
config.x.max_session_activations = ENV['MAX_SESSION_ACTIVATIONS'] || 10
|
||||
end
|
||||
3
config/initializers/session_store.rb
Normal file
3
config/initializers/session_store.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
Rails.application.config.session_store :cookie_store, key: '_gabsocial_session', secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true')
|
||||
22
config/initializers/sidekiq.rb
Normal file
22
config/initializers/sidekiq.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
namespace = ENV.fetch('REDIS_NAMESPACE') { nil }
|
||||
redis_params = { url: ENV['REDIS_URL'] }
|
||||
|
||||
if namespace
|
||||
redis_params[:namespace] = namespace
|
||||
end
|
||||
|
||||
Sidekiq.configure_server do |config|
|
||||
config.redis = redis_params
|
||||
|
||||
config.server_middleware do |chain|
|
||||
chain.add SidekiqErrorHandler
|
||||
end
|
||||
end
|
||||
|
||||
Sidekiq.configure_client do |config|
|
||||
config.redis = redis_params
|
||||
end
|
||||
|
||||
Sidekiq::Logging.logger.level = ::Logger.const_get(ENV.fetch('RAILS_LOG_LEVEL', 'info').upcase.to_s)
|
||||
206
config/initializers/simple_form.rb
Normal file
206
config/initializers/simple_form.rb
Normal file
@@ -0,0 +1,206 @@
|
||||
# Use this setup block to configure all options available in SimpleForm.
|
||||
|
||||
module AppendComponent
|
||||
def append(wrapper_options = nil)
|
||||
@append ||= begin
|
||||
options[:append].to_s.html_safe if options[:append].present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SimpleForm.include_component(AppendComponent)
|
||||
|
||||
SimpleForm.setup do |config|
|
||||
# Wrappers are used by the form builder to generate a
|
||||
# complete input. You can remove any component from the
|
||||
# wrapper, change the order or even add your own to the
|
||||
# stack. The options given below are used to wrap the
|
||||
# whole input.
|
||||
config.wrappers :default, class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
||||
## Extensions enabled by default
|
||||
# Any of these extensions can be disabled for a
|
||||
# given input by passing: `f.input EXTENSION_NAME => false`.
|
||||
# You can make any of these extensions optional by
|
||||
# renaming `b.use` to `b.optional`.
|
||||
|
||||
# Determines whether to use HTML5 (:email, :url, ...)
|
||||
# and required attributes
|
||||
b.use :html5
|
||||
|
||||
# Calculates placeholders automatically from I18n
|
||||
# You can also pass a string as f.input placeholder: "Placeholder"
|
||||
b.use :placeholder
|
||||
|
||||
## Optional extensions
|
||||
# They are disabled unless you pass `f.input EXTENSION_NAME => true`
|
||||
# to the input. If so, they will retrieve the values from the model
|
||||
# if any exists. If you want to enable any of those
|
||||
# extensions by default, you can change `b.optional` to `b.use`.
|
||||
|
||||
# Calculates maxlength from length validations for string inputs
|
||||
b.optional :maxlength
|
||||
|
||||
# Calculates pattern from format validations for string inputs
|
||||
b.optional :pattern
|
||||
|
||||
# Calculates min and max from length validations for numeric inputs
|
||||
b.optional :min_max
|
||||
|
||||
# Calculates readonly automatically from readonly attributes
|
||||
b.optional :readonly
|
||||
|
||||
## Inputs
|
||||
b.use :input
|
||||
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
||||
b.use :error, wrap_with: { tag: :span, class: :error }
|
||||
|
||||
## full_messages_for
|
||||
# If you want to display the full error message for the attribute, you can
|
||||
# use the component :full_error, like:
|
||||
#
|
||||
# b.use :full_error, wrap_with: { tag: :span, class: :error }
|
||||
end
|
||||
|
||||
config.wrappers :with_label, class: [:input, :with_label], hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
||||
b.use :html5
|
||||
|
||||
b.wrapper tag: :div, class: :label_input do |ba|
|
||||
ba.use :label
|
||||
|
||||
ba.wrapper tag: :div, class: :label_input__wrapper do |bb|
|
||||
bb.use :input
|
||||
bb.optional :append, wrap_with: { tag: :div, class: 'label_input__append' }
|
||||
end
|
||||
end
|
||||
|
||||
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
||||
b.use :error, wrap_with: { tag: :span, class: :error }
|
||||
end
|
||||
|
||||
config.wrappers :with_floating_label, class: [:input, :with_floating_label], hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
||||
b.use :html5
|
||||
b.use :label_input, wrap_with: { tag: :div, class: :label_input }
|
||||
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
||||
b.use :error, wrap_with: { tag: :span, class: :error }
|
||||
end
|
||||
|
||||
config.wrappers :with_block_label, class: [:input, :with_block_label], hint_class: :field_with_hint, error_class: :field_with_errors do |b|
|
||||
b.use :html5
|
||||
b.use :label
|
||||
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
||||
b.use :input
|
||||
b.use :error, wrap_with: { tag: :span, class: :error }
|
||||
end
|
||||
|
||||
# The default wrapper to be used by the FormBuilder.
|
||||
config.default_wrapper = :default
|
||||
|
||||
# Define the way to render check boxes / radio buttons with labels.
|
||||
# Defaults to :nested for bootstrap config.
|
||||
# inline: input + label
|
||||
# nested: label > input
|
||||
config.boolean_style = :nested
|
||||
|
||||
# Default class for buttons
|
||||
config.button_class = 'btn'
|
||||
|
||||
# Method used to tidy up errors. Specify any Rails Array method.
|
||||
# :first lists the first message for each field.
|
||||
# Use :to_sentence to list all errors for each field.
|
||||
# config.error_method = :first
|
||||
|
||||
# Default tag used for error notification helper.
|
||||
config.error_notification_tag = :div
|
||||
|
||||
# CSS class to add for error notification helper.
|
||||
config.error_notification_class = 'error_notification'
|
||||
|
||||
# ID to add for error notification helper.
|
||||
# config.error_notification_id = nil
|
||||
|
||||
# Series of attempts to detect a default label method for collection.
|
||||
# config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
|
||||
|
||||
# Series of attempts to detect a default value method for collection.
|
||||
# config.collection_value_methods = [ :id, :to_s ]
|
||||
|
||||
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
|
||||
# config.collection_wrapper_tag = nil
|
||||
|
||||
# You can define the class to use on all collection wrappers. Defaulting to none.
|
||||
# config.collection_wrapper_class = nil
|
||||
|
||||
# You can wrap each item in a collection of radio/check boxes with a tag,
|
||||
# defaulting to :span.
|
||||
# config.item_wrapper_tag = :span
|
||||
|
||||
# You can define a class to use in all item wrappers. Defaulting to none.
|
||||
# config.item_wrapper_class = nil
|
||||
|
||||
# How the label text should be generated altogether with the required text.
|
||||
config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
|
||||
|
||||
# You can define the class to use on all labels. Default is nil.
|
||||
# config.label_class = nil
|
||||
|
||||
# You can define the default class to be used on forms. Can be overridden
|
||||
# with `html: { :class }`. Defaulting to none.
|
||||
# config.default_form_class = nil
|
||||
|
||||
# You can define which elements should obtain additional classes
|
||||
# config.generate_additional_classes_for = [:wrapper, :label, :input]
|
||||
|
||||
# Whether attributes are required by default (or not). Default is true.
|
||||
# config.required_by_default = true
|
||||
|
||||
# Tell browsers whether to use the native HTML5 validations (novalidate form option).
|
||||
# These validations are enabled in SimpleForm's internal config but disabled by default
|
||||
# in this configuration, which is recommended due to some quirks from different browsers.
|
||||
# To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
|
||||
# change this configuration to true.
|
||||
config.browser_validations = false
|
||||
|
||||
# Collection of methods to detect if a file type was given.
|
||||
# config.file_methods = [ :mounted_as, :file?, :public_filename ]
|
||||
|
||||
# Custom mappings for input types. This should be a hash containing a regexp
|
||||
# to match as key, and the input type that will be used when the field name
|
||||
# matches the regexp as value.
|
||||
# config.input_mappings = { /count/ => :integer }
|
||||
|
||||
# Custom wrappers for input types. This should be a hash containing an input
|
||||
# type as key and the wrapper that will be used for all inputs with specified type.
|
||||
# config.wrapper_mappings = { string: :prepend }
|
||||
|
||||
# Namespaces where SimpleForm should look for custom input classes that
|
||||
# override default inputs.
|
||||
# config.custom_inputs_namespaces << "CustomInputs"
|
||||
|
||||
# Default priority for time_zone inputs.
|
||||
# config.time_zone_priority = nil
|
||||
|
||||
# Default priority for country inputs.
|
||||
# config.country_priority = nil
|
||||
|
||||
# When false, do not use translations for labels.
|
||||
# config.translate_labels = true
|
||||
|
||||
# Automatically discover new inputs in Rails' autoload path.
|
||||
# config.inputs_discovery = true
|
||||
|
||||
# Cache SimpleForm inputs discovery
|
||||
# config.cache_discovery = !Rails.env.development?
|
||||
|
||||
# Default class for inputs
|
||||
# config.input_class = nil
|
||||
|
||||
# Define the default class of the input wrapper of the boolean input.
|
||||
config.boolean_label_class = 'checkbox'
|
||||
|
||||
# Defines if the default input wrapper class should be included in radio
|
||||
# collection wrappers.
|
||||
# config.include_default_input_wrapper_class = true
|
||||
|
||||
# Defines which i18n scope will be used in Simple Form.
|
||||
# config.i18n_scope = 'simple_form'
|
||||
end
|
||||
5
config/initializers/single_user_mode.rb
Normal file
5
config/initializers/single_user_mode.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
config.x.single_user_mode = ENV['SINGLE_USER_MODE'] == 'true'
|
||||
end
|
||||
15
config/initializers/statsd.rb
Normal file
15
config/initializers/statsd.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
if ENV['STATSD_ADDR'].present?
|
||||
host, port = ENV['STATSD_ADDR'].split(':')
|
||||
|
||||
statsd = ::Statsd.new(host, port)
|
||||
statsd.namespace = ENV.fetch('STATSD_NAMESPACE') { ['GabSocial', Rails.env].join('.') }
|
||||
|
||||
::NSA.inform_statsd(statsd) do |informant|
|
||||
informant.collect(:action_controller, :web)
|
||||
informant.collect(:active_record, :db)
|
||||
informant.collect(:active_support_cache, :cache)
|
||||
informant.collect(:sidekiq, :sidekiq)
|
||||
end
|
||||
end
|
||||
4
config/initializers/stoplight.rb
Normal file
4
config/initializers/stoplight.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
require 'stoplight'
|
||||
|
||||
Stoplight::Light.default_data_store = Stoplight::DataStore::Redis.new(Redis.current)
|
||||
Stoplight::Light.default_notifiers = [Stoplight::Notifier::Logger.new(Rails.logger)]
|
||||
3
config/initializers/strong_migrations.rb
Normal file
3
config/initializers/strong_migrations.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
StrongMigrations.start_after = 20170924022025
|
||||
3
config/initializers/suppress_csrf_warnings.rb
Normal file
3
config/initializers/suppress_csrf_warnings.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
ActionController::Base.log_warning_on_csrf_failure = false
|
||||
11
config/initializers/trusted_proxies.rb
Normal file
11
config/initializers/trusted_proxies.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
module Rack
|
||||
class Request
|
||||
def trusted_proxy?(ip)
|
||||
if Rails.application.config.action_dispatch.trusted_proxies.nil?
|
||||
super
|
||||
else
|
||||
Rails.application.config.action_dispatch.trusted_proxies.any? { |proxy| proxy === ip }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
41
config/initializers/twitter_regex.rb
Normal file
41
config/initializers/twitter_regex.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
module Twitter
|
||||
class Regex
|
||||
REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}<>\(\)\?]/iou
|
||||
REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}\(\)\?!\*"'「」<>;:=\,\.\$%\[\]~&\|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou
|
||||
REGEXEN[:valid_url_balanced_parens] = /
|
||||
\(
|
||||
(?:
|
||||
#{REGEXEN[:valid_general_url_path_chars]}+
|
||||
|
|
||||
# allow one nested level of balanced parentheses
|
||||
(?:
|
||||
#{REGEXEN[:valid_general_url_path_chars]}*
|
||||
\(
|
||||
#{REGEXEN[:valid_general_url_path_chars]}+
|
||||
\)
|
||||
#{REGEXEN[:valid_general_url_path_chars]}*
|
||||
)
|
||||
)
|
||||
\)
|
||||
/iox
|
||||
REGEXEN[:valid_url_path] = /(?:
|
||||
(?:
|
||||
#{REGEXEN[:valid_general_url_path_chars]}*
|
||||
(?:#{REGEXEN[:valid_url_balanced_parens]} #{REGEXEN[:valid_general_url_path_chars]}*)*
|
||||
#{REGEXEN[:valid_url_path_ending_chars]}
|
||||
)|(?:#{REGEXEN[:valid_general_url_path_chars]}+\/)
|
||||
)/iox
|
||||
REGEXEN[:valid_url] = %r{
|
||||
( # $1 total match
|
||||
(#{REGEXEN[:valid_url_preceding_chars]}) # $2 Preceding character
|
||||
( # $3 URL
|
||||
((https?|dat|dweb|ipfs|ipns|ssb|gopher):\/\/)? # $4 Protocol (optional)
|
||||
(#{REGEXEN[:valid_domain]}) # $5 Domain(s)
|
||||
(?::(#{REGEXEN[:valid_port_number]}))? # $6 Port number (optional)
|
||||
(/#{REGEXEN[:valid_url_path]}*)? # $7 URL Path and anchor
|
||||
(\?#{REGEXEN[:valid_url_query_chars]}*#{REGEXEN[:valid_url_query_ending_chars]})? # $8 Query String
|
||||
)
|
||||
)
|
||||
}iox
|
||||
end
|
||||
end
|
||||
16
config/initializers/vapid.rb
Normal file
16
config/initializers/vapid.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
# You can generate the keys using the following command (first is the private key, second is the public one)
|
||||
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
||||
# be invalidated, requiring the users to access the website again to resubscribe.
|
||||
#
|
||||
# Generate with `rake gabsocial:webpush:generate_vapid_key` task (`docker-compose run --rm web rake gabsocial:webpush:generate_vapid_key` if you use docker compose)
|
||||
#
|
||||
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
||||
|
||||
if Rails.env.production?
|
||||
config.x.vapid_private_key = ENV['VAPID_PRIVATE_KEY']
|
||||
config.x.vapid_public_key = ENV['VAPID_PUBLIC_KEY']
|
||||
end
|
||||
end
|
||||
14
config/initializers/wrap_parameters.rb
Normal file
14
config/initializers/wrap_parameters.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# This file contains settings for ActionController::ParamsWrapper which
|
||||
# is enabled by default.
|
||||
|
||||
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||
ActiveSupport.on_load(:action_controller) do
|
||||
wrap_parameters format: [:json]
|
||||
end
|
||||
|
||||
# To enable root element in JSON for ActiveRecord objects.
|
||||
# ActiveSupport.on_load(:active_record) do
|
||||
# self.include_root_in_json = true
|
||||
# end
|
||||
13
config/locales/activerecord.ar.yml
Normal file
13
config/locales/activerecord.ar.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
ar:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: فقط حروف و أرقام و سطور سفلية
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: المنشور موجود مِن قبل
|
||||
9
config/locales/activerecord.ast.yml
Normal file
9
config/locales/activerecord.ast.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
ast:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: namái lletres, númberos y guiones baxos
|
||||
16
config/locales/activerecord.ca.yml
Normal file
16
config/locales/activerecord.ca.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
ca:
|
||||
activerecord:
|
||||
attributes:
|
||||
status:
|
||||
owned_poll: Enquesta
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: només lletres, números i subratllats
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: de l'estat ja existeix
|
||||
17
config/locales/activerecord.co.yml
Normal file
17
config/locales/activerecord.co.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
co:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Fine
|
||||
options: Scelte
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: solu lettere, numeri è liniette basse
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: di u statutu esista digià
|
||||
17
config/locales/activerecord.cs.yml
Normal file
17
config/locales/activerecord.cs.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
cs:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Uzávěrka
|
||||
options: Volby
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: pouze písmena, číslice a podtržítka
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: příspěvku již existuje
|
||||
13
config/locales/activerecord.cy.yml
Normal file
13
config/locales/activerecord.cy.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
cy:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: dim ond llythrennau, rhifau a tanlinellau
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: o'r statws yn bodoli'n barod
|
||||
16
config/locales/activerecord.da.yml
Normal file
16
config/locales/activerecord.da.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
da:
|
||||
activerecord:
|
||||
attributes:
|
||||
status:
|
||||
owned_poll: Afstemning
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: kun tal, bogstaver og understreger
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: af allerede eksisterende status
|
||||
19
config/locales/activerecord.de.yml
Normal file
19
config/locales/activerecord.de.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
de:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Frist
|
||||
options: Wahlen
|
||||
status:
|
||||
owned_poll: Umfrage
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: nur Buchstaben, Ziffern und Unterstriche
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: des Status existiert schon
|
||||
19
config/locales/activerecord.el.yml
Normal file
19
config/locales/activerecord.el.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
el:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Προθεσμία
|
||||
options: Επιλογές
|
||||
status:
|
||||
owned_poll: Ψηφοφορία
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: μόνο γράμματα, αριθμοί και κάτω παύλες
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: της κατάστασης ήδη υπάρχει
|
||||
17
config/locales/activerecord.en.yml
Normal file
17
config/locales/activerecord.en.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
en:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Deadline
|
||||
options: Choices
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: only letters, numbers and underscores
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: of status already exists
|
||||
13
config/locales/activerecord.es.yml
Normal file
13
config/locales/activerecord.es.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
es:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: solo letras, números y guiones bajos
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: del estado ya existe
|
||||
13
config/locales/activerecord.eu.yml
Normal file
13
config/locales/activerecord.eu.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
eu:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: letrak, zenbakiak eta gidoi baxuak besterik ez
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: mezu honentzat bazegoen aurretik
|
||||
16
config/locales/activerecord.fa.yml
Normal file
16
config/locales/activerecord.fa.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
fa:
|
||||
activerecord:
|
||||
attributes:
|
||||
status:
|
||||
owned_poll: رأیگیری
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: تنها حروف، اعداد، و زیرخط
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: نوشتهها وجود دارند
|
||||
17
config/locales/activerecord.fr.yml
Normal file
17
config/locales/activerecord.fr.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
fr:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Date butoir
|
||||
options: Choix
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: seulement des lettres, des nombres et des tirets bas
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: du statut existe déjà
|
||||
19
config/locales/activerecord.gl.yml
Normal file
19
config/locales/activerecord.gl.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
gl:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Caducidade
|
||||
options: Opcións
|
||||
status:
|
||||
owned_poll: Sondaxe
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: só letras, números e liñas baixas
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: do estado xa existe
|
||||
13
config/locales/activerecord.he.yml
Normal file
13
config/locales/activerecord.he.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
he:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: ספרות, אותיות לטיניות וקו תחתי בלבד
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: של החצרוץ כבר קיים
|
||||
13
config/locales/activerecord.id.yml
Normal file
13
config/locales/activerecord.id.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
id:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: hanya boleh berisi huruf, angka, dan underscore
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: status sudah ada
|
||||
13
config/locales/activerecord.it.yml
Normal file
13
config/locales/activerecord.it.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
it:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: solo lettere, numeri e trattino basso
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: dello stato esiste già
|
||||
19
config/locales/activerecord.ja.yml
Normal file
19
config/locales/activerecord.ja.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
ja:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: 期限
|
||||
options: 項目
|
||||
user:
|
||||
email: メールアドレス
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: アルファベット・数字・アンダーバーの組み合わせで入力してください
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: は既にブーストされています
|
||||
13
config/locales/activerecord.ka.yml
Normal file
13
config/locales/activerecord.ka.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
ka:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: მხოლოდ ასოები, ციფრები და "ქვედა-ტირე"
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: სტატუსის უკვე არსებობს
|
||||
17
config/locales/activerecord.kk.yml
Normal file
17
config/locales/activerecord.kk.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
kk:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Дедлайн
|
||||
options: Таңдаулар
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: тек әріптер, сандар және асты сызылған таңбалар
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: жазбасы бұрыннан бар
|
||||
19
config/locales/activerecord.nl.yml
Normal file
19
config/locales/activerecord.nl.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
nl:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Deadline
|
||||
options: Keuzes
|
||||
status:
|
||||
owned_poll: Poll
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: alleen letters, nummers en underscores
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: van toot bestaat al
|
||||
13
config/locales/activerecord.no.yml
Normal file
13
config/locales/activerecord.no.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
'no':
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: bare bokstaver, tall og understreker
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: av status eksisterer allerede
|
||||
17
config/locales/activerecord.oc.yml
Normal file
17
config/locales/activerecord.oc.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
oc:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Data limita
|
||||
options: Opcions
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: solament letras, nombres e tirets basses
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: de l’estatut existís ja
|
||||
16
config/locales/activerecord.pl.yml
Normal file
16
config/locales/activerecord.pl.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
pl:
|
||||
activerecord:
|
||||
attributes:
|
||||
user:
|
||||
email: adres e-mail
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: może składać się tylko z liter, cyfr i podkreślników
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: status już istnieje
|
||||
17
config/locales/activerecord.pt-BR.yml
Normal file
17
config/locales/activerecord.pt-BR.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
pt-BR:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Expira em
|
||||
options: Escolhas
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: apenas letras, números e underscores
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: do status já existe
|
||||
13
config/locales/activerecord.pt.yml
Normal file
13
config/locales/activerecord.pt.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
pt:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: apenas letras, números e underscores
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: do status já existe
|
||||
17
config/locales/activerecord.ru.yml
Normal file
17
config/locales/activerecord.ru.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
ru:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Крайний срок
|
||||
options: Варианты
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: только буквы, цифры и символ подчёркивания
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: статуса уже существует
|
||||
19
config/locales/activerecord.sk.yml
Normal file
19
config/locales/activerecord.sk.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sk:
|
||||
activerecord:
|
||||
attributes:
|
||||
poll:
|
||||
expires_at: Trvá do
|
||||
options: Voľby
|
||||
status:
|
||||
owned_poll: Anketa
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: iba písmená, číslice a podčiarkovníky
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: príspevku už existuje
|
||||
13
config/locales/activerecord.sl.yml
Normal file
13
config/locales/activerecord.sl.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sl:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: samo črke, številke in podčrtaji
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: od statusa že obstajajo
|
||||
13
config/locales/activerecord.sq.yml
Normal file
13
config/locales/activerecord.sq.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sq:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: vetëm shkronja, numra dhe nënvija
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: e gjendjes ekziston tashmë
|
||||
13
config/locales/activerecord.sr-Latn.yml
Normal file
13
config/locales/activerecord.sr-Latn.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sr-Latn:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: samo slova, brojevi i donje crte
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: statusa već postoji
|
||||
13
config/locales/activerecord.sr.yml
Normal file
13
config/locales/activerecord.sr.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
sr:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: само слова, бројеви и доње црте
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: статуса већ постоји
|
||||
9
config/locales/activerecord.sv.yml
Normal file
9
config/locales/activerecord.sv.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
sv:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: enbart bokstäver, siffror och understreck
|
||||
13
config/locales/activerecord.th.yml
Normal file
13
config/locales/activerecord.th.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
th:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: ตัวอักษร, ตัวเลข และขีดล่างเท่านั้น
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: มีสถานะอยู่แล้ว
|
||||
13
config/locales/activerecord.tr.yml
Normal file
13
config/locales/activerecord.tr.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
tr:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: sadece harfler, sayılar ve alt çizgiler
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: durum zaten var
|
||||
13
config/locales/activerecord.uk.yml
Normal file
13
config/locales/activerecord.uk.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
uk:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: тільки букви, цифри та нижні підкреслювання
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: статусу вже існує
|
||||
13
config/locales/activerecord.zh-CN.yml
Normal file
13
config/locales/activerecord.zh-CN.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
zh-CN:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: 只能使用字母、数字和下划线
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: 已经被转嘟过
|
||||
13
config/locales/activerecord.zh-HK.yml
Normal file
13
config/locales/activerecord.zh-HK.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
zh-HK:
|
||||
activerecord:
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: 只能使用字母、數字和下劃線
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: 已經被轉推過
|
||||
15
config/locales/activerecord.zh_Hant.yml
Normal file
15
config/locales/activerecord.zh_Hant.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
zh_Hant:
|
||||
activerecord:
|
||||
attributes:
|
||||
status:
|
||||
owned_poll: 投票
|
||||
errors:
|
||||
models:
|
||||
account:
|
||||
attributes:
|
||||
username:
|
||||
invalid: 只允許使用字母、數字和底線
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: 的嘟文已經存在
|
||||
929
config/locales/ar.yml
Normal file
929
config/locales/ar.yml
Normal file
@@ -0,0 +1,929 @@
|
||||
---
|
||||
ar:
|
||||
about:
|
||||
about_hashtag_html: هذه تبويقات متاحة للجمهور تحتوي على الكلمات الدلالية <strong>#%{hashtag}</strong>. يمكنك التفاعل معها إن كان لديك حساب في أي مكان على الفديفرس.
|
||||
about_gabsocial_html: ماستدون شبكة إجتماعية مبنية على أسُس بروتوكولات برمجيات الويب الحرة و مفتوحة المصدر. و هو لامركزي تمامًا كالبريد الإلكتروني.
|
||||
about_this: عن مثيل الخادوم هذا
|
||||
administered_by: 'يُديره :'
|
||||
api: واجهة برمجة التطبيقات
|
||||
apps: تطبيقات الأجهزة المحمولة
|
||||
contact: للتواصل معنا
|
||||
contact_missing: لم يتم تعيينه
|
||||
contact_unavailable: غير متوفر
|
||||
documentation: الدليل
|
||||
extended_description_html: |
|
||||
<h3>مكان جيد للقواعد</h3>
|
||||
<p>لم يتم بعد إدخال الوصف الطويل.</p>
|
||||
generic_description: "%{domain} هو سيرفر من بين سيرفرات الشبكة"
|
||||
hosted_on: ماستدون مُستضاف على %{domain}
|
||||
learn_more: تعلم المزيد
|
||||
privacy_policy: سياسة الخصوصية
|
||||
source_code: الشفرة المصدرية
|
||||
status_count_after:
|
||||
few: منشورات
|
||||
many: منشورات
|
||||
one: منشور
|
||||
other: منشورات
|
||||
two: منشورات
|
||||
zero: منشورات
|
||||
status_count_before: نشروا
|
||||
terms: شروط الخدمة
|
||||
user_count_after:
|
||||
few: مستخدمين
|
||||
many: مستخدمين
|
||||
one: مستخدم
|
||||
other: مستخدمين
|
||||
two: مستخدمين
|
||||
zero: مستخدمين
|
||||
user_count_before: يستضيف
|
||||
what_is_gabsocial: ما هو ماستدون ؟
|
||||
accounts:
|
||||
choices_html: 'توصيات %{name} :'
|
||||
follow: إتبع
|
||||
followers:
|
||||
few: متابِعون
|
||||
many: متابِعون
|
||||
one: متابِع
|
||||
other: متابِعون
|
||||
two: متابِعون
|
||||
zero: متابِعون
|
||||
following: مُتابَع
|
||||
joined: انضم·ت في %{date}
|
||||
last_active: آخر نشاط
|
||||
link_verified_on: تم التحقق مِن مالك هذا الرابط بتاريخ %{date}
|
||||
media: الوسائط
|
||||
moved_html: "%{name} إنتقلَ إلى %{new_profile_link} :"
|
||||
network_hidden: إنّ المعطيات غير متوفرة
|
||||
nothing_here: لا يوجد أي شيء هنا !
|
||||
people_followed_by: الأشخاص الذين يتبعهم %{name}
|
||||
people_who_follow: الأشخاص الذين يتبعون %{name}
|
||||
pin_errors:
|
||||
following: يجب أن تكون مِن متابعي حساب الشخص الذي تريد إبرازه
|
||||
posts:
|
||||
few: تبويقات
|
||||
many: تبويقات
|
||||
one: تبويق
|
||||
other: تبويقات
|
||||
two: تبويقات
|
||||
zero: تبويقات
|
||||
posts_tab_heading: تبويقات
|
||||
posts_with_replies: التبويقات و الردود
|
||||
reserved_username: إسم المستخدم محجوز
|
||||
roles:
|
||||
admin: المدير
|
||||
bot: روبوت
|
||||
moderator: مُشرِف
|
||||
unfollow: إلغاء المتابعة
|
||||
admin:
|
||||
account_actions:
|
||||
action: تنفيذ الاجراء
|
||||
title: اتخاذ إجراء إشراف على %{acct}
|
||||
account_moderation_notes:
|
||||
create: إترك ملاحظة
|
||||
created_msg: تم إنشاء ملاحظة الإشراف بنجاح !
|
||||
delete: حذف
|
||||
destroyed_msg: تم تدمير ملاحظة الإشراف بنجاح !
|
||||
accounts:
|
||||
are_you_sure: متأكد ؟
|
||||
avatar: الصورة الرمزية
|
||||
by_domain: النطاق
|
||||
change_email:
|
||||
changed_msg: تم تعديل عنوان البريد الإلكتروني الخاص بالحساب بنجاح !
|
||||
current_email: عنوان البريد الإلكتروني الحالي
|
||||
label: تعديل عنوان البريد الإلكتروني
|
||||
new_email: عنوان البريد الإلكتروني الجديد
|
||||
submit: تعديل عنوان البريد الإلكتروني
|
||||
title: تعديل عنوان البريد الإلكتروني الخاص بـ %{username}
|
||||
confirm: تأكيد
|
||||
confirmed: مؤكَّد
|
||||
confirming: التأكد
|
||||
deleted: تمت إزالته
|
||||
demote: إنزال الرُتبة الوظيفية
|
||||
disable: تعطيل
|
||||
disable_two_factor_authentication: تعطيل المصادقة بخطوتين
|
||||
disabled: معطَّل
|
||||
display_name: عرض الإسم
|
||||
domain: النطاق
|
||||
edit: تعديل
|
||||
email: البريد الإلكتروني
|
||||
email_status: حالة البريد الإلكتروني
|
||||
enable: تفعيل
|
||||
enabled: مفعَّل
|
||||
feed_url: عنوان رابط التغذية
|
||||
followers: المتابِعون
|
||||
followers_url: عنوان رابط المتابِعين
|
||||
follows: يتابع
|
||||
header: الرأسية
|
||||
inbox_url: رابط صندوق الوارد
|
||||
invited_by: تمت دعوته مِن طرف
|
||||
ip: عنوان الإيبي
|
||||
joined: انضم
|
||||
location:
|
||||
all: الكل
|
||||
local: المحلي
|
||||
remote: عن بُعد
|
||||
title: الموقع
|
||||
login_status: وضع الدخول
|
||||
media_attachments: الوسائط المرفقة
|
||||
memorialize: تحويل الحساب إلى صفحة ذكرى
|
||||
moderation:
|
||||
active: نشِط
|
||||
all: الكل
|
||||
silenced: تم كتمه
|
||||
suspended: مُجَمَّد
|
||||
title: الإشراف
|
||||
moderation_notes: ملاحظات الإشراف
|
||||
most_recent_activity: آخر نشاط حديث
|
||||
most_recent_ip: أحدث عنوان إيبي
|
||||
no_limits_imposed: مِن دون حدود مشروطة
|
||||
not_subscribed: غير مشترك
|
||||
outbox_url: رابط صندوق الصادر
|
||||
perform_full_suspension: تعليق الحساب
|
||||
profile_url: رابط الملف الشخصي
|
||||
promote: ترقية
|
||||
protocol: البروتوكول
|
||||
public: عمومي
|
||||
push_subscription_expires: انتهاء الاشتراك ”PuSH“
|
||||
redownload: تحديث الصفحة الشخصية
|
||||
remove_avatar: حذف الصورة الرمزية
|
||||
remove_header: حذف الرأسية
|
||||
resend_confirmation:
|
||||
already_confirmed: هذا المستخدم مؤكد بالفعل
|
||||
send: أعد إرسال رسالة البريد الالكتروني الخاصة بالتأكيد
|
||||
success: تم إرسال رسالة التأكيد بنجاح!
|
||||
reset: إعادة التعيين
|
||||
reset_password: إعادة ضبط كلمة السر
|
||||
resubscribe: إعادة الإشتراك
|
||||
role: الصلاحيات
|
||||
roles:
|
||||
admin: مدير
|
||||
moderator: مشرف
|
||||
staff: الفريق
|
||||
user: مستخدِم
|
||||
salmon_url: عنوان رابط سالمون Salmon
|
||||
search: البحث
|
||||
shared_inbox_url: رابط الصندوق المُشترَك للبريد الوارد
|
||||
show:
|
||||
created_reports: البلاغات التي أنشأها هذا الحساب
|
||||
targeted_reports: الشكاوي التي أُنشِأت مِن طرف الآخَرين
|
||||
silence: كتم
|
||||
silenced: تم كتمه
|
||||
statuses: المنشورات
|
||||
subscribe: اشترك
|
||||
suspended: تم تعليقه
|
||||
title: الحسابات
|
||||
unconfirmed_email: البريد الإلكتروني غير مؤكد
|
||||
undo_silenced: رفع الصمت
|
||||
undo_suspension: إلغاء تعليق الحساب
|
||||
unsubscribe: إلغاء الاشتراك
|
||||
username: إسم المستخدم
|
||||
warn: تحذير
|
||||
web: الويب
|
||||
action_logs:
|
||||
actions:
|
||||
assigned_to_self_report: قام %{name} بتعيين التقرير %{target} لأنفسهم
|
||||
change_email_user: غيّر %{name} عنوان البريد الإلكتروني للمستخدم %{target}
|
||||
confirm_user: "%{name} قد قام بتأكيد عنوان البريد الإلكتروني لـ %{target}"
|
||||
create_account_warning: قام %{name} بإرسال تحذير إلى %{target}
|
||||
create_custom_emoji: "%{name} قام برفع إيموجي جديد %{target}"
|
||||
create_domain_block: "%{name} قام بحجب نطاق %{target}"
|
||||
create_email_domain_block: "%{name} قد قام بحظر نطاق البريد الإلكتروني %{target}"
|
||||
demote_user: "%{name} قد قام بإنزال الرتبة الوظيفية لـ %{target}"
|
||||
destroy_custom_emoji: قام %{name} بحذف الإيموجي %{target}
|
||||
destroy_domain_block: "%{name} قام بإلغاء الحجب عن النطاق %{target}"
|
||||
destroy_email_domain_block: قام %{name} بإضافة نطاق البريد الإلكتروني %{target} إلى اللائحة البيضاء
|
||||
destroy_status: لقد قام %{name} بحذف منشور %{target}
|
||||
disable_2fa_user: "%{name} لقد قام بتعطيل ميزة المصادقة بخطوتين للمستخدم %{target}"
|
||||
disable_custom_emoji: "%{name} قام بتعطيل الإيموجي %{target}"
|
||||
disable_user: "%{name} لقد قام بتعطيل تسجيل الدخول للمستخدِم %{target}"
|
||||
enable_custom_emoji: "%{name} قام بتنشيط الإيموجي %{target}"
|
||||
enable_user: لقد قام %{name} بتنشيط تسجيل الدخول للمستخدِم %{target}
|
||||
memorialize_account: لقد قام %{name} بتحويل حساب %{target} إلى صفحة تذكارية
|
||||
promote_user: "%{name} قام بترقية المستخدم %{target}"
|
||||
remove_avatar_user: تمت إزالة %{name} الصورة الرمزية %{target}
|
||||
reopen_report: تمت إعادة فتح الشكوى %{name} %{target}
|
||||
reset_password_user: "%{name} لقد قام بإعادة تعيين الكلمة السرية الخاصة بـ %{target}"
|
||||
resolve_report: قام %{name} بحل الشكوى %{target}
|
||||
silence_account: لقد قام %{name} بكتم حساب %{target}
|
||||
suspend_account: لقد قام %{name} بتعليق حساب %{target}
|
||||
unassigned_report: "%{name} تقرير غير معتمد %{target}"
|
||||
unsilence_account: لقد قام %{name} بإلغاء الكتم عن حساب %{target}
|
||||
unsuspend_account: لقد قام %{name} بإلغاء التعليق المفروض على حساب %{target}
|
||||
update_custom_emoji: "%{name} قام بتحديث الإيموجي %{target}"
|
||||
update_status: لقد قام %{name} بتحديث منشور %{target}
|
||||
deleted_status: "(منشور محذوف)"
|
||||
title: سِجلّ التفتيش و المعاينة
|
||||
custom_emojis:
|
||||
by_domain: النطاق
|
||||
copied_msg: تم إنشاء نسخة محلية للإيموجي بنجاح
|
||||
copy: نسخ
|
||||
copy_failed_msg: فشلت عملية إنشاء نسخة محلية لهذا الإيموجي
|
||||
created_msg: تم إنشاء الإيموجي بنجاح !
|
||||
delete: حذف
|
||||
destroyed_msg: تمت عملية تدمير الإيموجي بنجاح !
|
||||
disable: تعطيل
|
||||
disabled_msg: تمت عملية تعطيل ذلك الإيموجي بنجاح
|
||||
emoji: إيموجي
|
||||
enable: تفعيل
|
||||
enabled_msg: تم تنشيط ذاك الإيموجي بنجاح
|
||||
image_hint: ملف PNG إلى غاية حجم 50 ك.ب
|
||||
listed: مُدرَج
|
||||
new:
|
||||
title: إضافة إيموجي خاص جديد
|
||||
overwrite: إعادة الكتابة
|
||||
shortcode: الترميز المُصَغّر
|
||||
shortcode_hint: على الأقل حرفين، و فقط رموز أبجدية عددية و أسطر سفلية
|
||||
title: الإيموجي الخاصة
|
||||
unlisted: غير مدرج
|
||||
update_failed_msg: تعذرت عملية تحذيث ذاك الإيموجي
|
||||
updated_msg: تم تحديث الإيموجي بنجاح !
|
||||
upload: رفع
|
||||
dashboard:
|
||||
backlog: الأعمال المتراكمة
|
||||
config: الإعداد
|
||||
feature_deletions: الحسابات المحذوفة
|
||||
feature_invites: روابط الدعوات
|
||||
feature_profile_directory: دليل الحسابات
|
||||
feature_registrations: التسجيلات
|
||||
feature_relay: المُرحّل الفديرالي
|
||||
features: الميّزات
|
||||
hidden_service: الفيديرالية مع الخدمات الخفية
|
||||
open_reports: فتح الشكاوي
|
||||
recent_users: أحدث المستخدِمين
|
||||
search: البحث النصي الكامل
|
||||
single_user_mode: وضع المستخدِم الأوحد
|
||||
software: البرنامج
|
||||
space: المساحة المستخدَمة
|
||||
title: لوح المراقبة
|
||||
total_users: إجمالي المستخدِمين
|
||||
trends: المؤشرات
|
||||
week_interactions: تفاعُلات هذا الأسبوع
|
||||
week_users_active: نشط هذا الأسبوع
|
||||
week_users_new: مستخدِمين هذا الأسبوع
|
||||
domain_blocks:
|
||||
add_new: إضافة حجب جديد لنطاق
|
||||
created_msg: إنّ حجب النطاق حيز التشغيل
|
||||
destroyed_msg: تم إلغاء الحجب المفروض على النطاق
|
||||
domain: النطاق
|
||||
new:
|
||||
create: إنشاء حظر
|
||||
hint: لن تمنع كتلة المجال إنشاء إدخالات حساب في قاعدة البيانات ، ولكنها ستطبق طرق الإشراف المحددة بأثر رجعي وتلقائي على هذه الحسابات.
|
||||
severity:
|
||||
desc_html: "<strong>Silence</strong> سيجعل مشاركات الحساب غير مرئية لأي شخص لا يتبعها. <strong>Suspend</strong> سيزيل كل محتوى الحساب ووسائطه وبيانات ملفه الشخصي. Use <strong>None</strong> إذا كنت تريد فقط رفض ملفات الوسائط."
|
||||
noop: لا شيء
|
||||
silence: كتم
|
||||
suspend: تعليق
|
||||
title: حجب نطاق جديد
|
||||
reject_media: رفض ملفات الوسائط
|
||||
reject_media_hint: يزيل ملفات الوسائط المخزنة محليًا ويرفض تنزيل أي ملفات في المستقبل. غير ذي صلة للتعليق
|
||||
reject_reports: رفض التقارير
|
||||
severity:
|
||||
silence: تم كتمه
|
||||
suspend: تم تعليقه
|
||||
show:
|
||||
affected_accounts:
|
||||
few: "%{count} حسابات معنية في قاعدة البيانات"
|
||||
many: "%{count} حسابات معنية في قاعدة البيانات"
|
||||
one: حساب واحد معني في قاعدة البيانات
|
||||
other: "%{count} حسابات معنية في قاعدة البيانات"
|
||||
two: حسابات معنية في قاعدة البيانات
|
||||
zero: حسابات معنية في قاعدة البيانات
|
||||
retroactive:
|
||||
silence: إلغاء الكتم عن كافة الحسابات المتواجدة على هذا النطاق
|
||||
suspend: إلغاء التعليق المفروض على كافة حسابات هذا النطاق
|
||||
title: رفع حظر النطاق عن %{domain}
|
||||
undo: إلغاء
|
||||
undo: إلغاء حجب النطاق
|
||||
email_domain_blocks:
|
||||
add_new: إضافة
|
||||
created_msg: لقد دخل حظر نطاق البريد الإلكتروني حيّز الخدمة
|
||||
delete: حذف
|
||||
destroyed_msg: تم حذف نطاق البريد الإلكتروني من اللائحة السوداء بنجاح
|
||||
domain: النطاق
|
||||
new:
|
||||
create: إضافة نطاق
|
||||
title: إضافة نطاق بريد جديد إلى اللائحة السوداء
|
||||
title: القائمة السوداء للبريد الإلكتروني
|
||||
followers:
|
||||
back_to_account: العودة إلى الحساب
|
||||
title: "%{acct} مُتابِعون"
|
||||
instances:
|
||||
by_domain: النطاق
|
||||
delivery_available: التسليم متوفر
|
||||
known_accounts:
|
||||
few: "%{count} حسابات معروفة"
|
||||
many: "%{count} حسابات معروفة"
|
||||
one: حساب معروف %{count}
|
||||
other: "%{count} حسابات معروفة"
|
||||
two: "%{count} حسابات معروفة"
|
||||
zero: "%{count} حسابات معروفة"
|
||||
moderation:
|
||||
all: كافتها
|
||||
title: الإشراف
|
||||
title: الفديرالية
|
||||
total_blocked_by_us: المحجوبة مِن طرفنا
|
||||
total_followed_by_them: يُتابِعونها
|
||||
total_followed_by_us: التي نُتابِعها
|
||||
total_reported: تقارير عنهم
|
||||
total_storage: الوسائط المُرفَقة
|
||||
invites:
|
||||
deactivate_all: تعطيلها كافة
|
||||
filter:
|
||||
all: الكل
|
||||
available: المتوفرة
|
||||
expired: المنتهي صلاحيتها
|
||||
title: التصفية
|
||||
title: الدعوات
|
||||
relays:
|
||||
add_new: إضافة مُرحّل جديد
|
||||
delete: حذف
|
||||
disable: تعطيل
|
||||
disabled: مُعطَّل
|
||||
enable: تشغيل
|
||||
enable_hint: عندما تقوم بتنشيط هذه الميزة، سوف يشترك خادومك في جميع التبويقات القادمة مِن هذا المُرحِّل و سيشرع كذلك بإرسال كافة التبويقات العمومية إليه.
|
||||
enabled: مُشغَّل
|
||||
inbox_url: رابط المُرحّل
|
||||
pending: في انتظار تسريح المُرحِّل
|
||||
save_and_enable: حفظ وتشغيل
|
||||
setup: إعداد اتصال بمُرحّل
|
||||
status: الحالة
|
||||
title: المُرحّلات
|
||||
report_notes:
|
||||
created_msg: تم إنشاء ملاحظة الشكوى بنجاح!
|
||||
destroyed_msg: تم حذف ملاحظة الشكوى بنجاح!
|
||||
reports:
|
||||
account:
|
||||
note: ملحوظة
|
||||
report: تقرير
|
||||
action_taken_by: تم اتخاذ الإجراء مِن طرف
|
||||
are_you_sure: هل أنت متأكد ؟
|
||||
assign_to_self: عين لي
|
||||
assigned: تعين رئيس
|
||||
comment:
|
||||
none: لا شيء
|
||||
created_at: ذكرت
|
||||
mark_as_resolved: إعتبار الشكوى كمحلولة
|
||||
mark_as_unresolved: علام كغير محلولة
|
||||
notes:
|
||||
create: اضف ملاحظة
|
||||
create_and_resolve: الحل مع ملاحظة
|
||||
create_and_unresolve: إعادة فتح مع ملاحظة
|
||||
delete: حذف
|
||||
placeholder: قم بوصف الإجراءات التي تم اتخاذها أو أي تحديثات أخرى ذات علاقة …
|
||||
reopen: إعادة فتح الشكوى
|
||||
report: 'الشكوى #%{id}'
|
||||
reported_account: حساب مُبلّغ عنه
|
||||
reported_by: أبلغ عنه من طرف
|
||||
resolved: معالجة
|
||||
resolved_msg: تم حل تقرير بنجاح!
|
||||
status: الحالة
|
||||
title: الشكاوي
|
||||
unassign: إلغاء تعيين
|
||||
unresolved: غير معالجة
|
||||
updated_at: محدث
|
||||
settings:
|
||||
activity_api_enabled:
|
||||
desc_html: عدد المنشورات المحلية و المستخدمين النشطين و التسجيلات الأسبوعية الجديدة
|
||||
title: نشر مُجمل الإحصائيات عن نشاط المستخدمين
|
||||
bootstrap_timeline_accounts:
|
||||
desc_html: افصل بين أسماء المستخدمين المتعددة بواسطة الفاصلة. استعمل الحسابات المحلية والمفتوحة فقط. الافتراضي عندما تكون فارغة كل المسؤولين المحليين.
|
||||
title: الإشتراكات الإفتراضية للمستخدمين الجدد
|
||||
contact_information:
|
||||
email: البريد الإلكتروني المهني
|
||||
username: الإتصال بالمستخدِم
|
||||
custom_css:
|
||||
desc_html: يقوم بتغيير المظهر بواسطة سي أس أس يُحمَّل على كافة الصفحات
|
||||
title: سي أس أس مخصص
|
||||
hero:
|
||||
desc_html: معروض على الصفحة الأولى. لا يقل عن 600 × 100 بكسل. عند عدم التعيين ، تعود الصورة إلى النسخة المصغرة على سبيل المثال
|
||||
title: الصورة الرأسية
|
||||
peers_api_enabled:
|
||||
desc_html: أسماء النطاقات التي إلتقى بها مثيل الخادوم على البيئة الموحَّدة فيديفرس
|
||||
title: نشر عدد مثيلات الخوادم التي تم مصادفتها
|
||||
preview_sensitive_media:
|
||||
desc_html: روابط المُعَاينة على مواقع الويب الأخرى ستقوم بعرض صُوَر مصغّرة حتى و إن كانت الوسائط حساسة
|
||||
title: إظهار الصور الحساسة في مُعاينات أوبن غراف
|
||||
profile_directory:
|
||||
desc_html: السماح للمستخدمين الكشف عن حساباتهم
|
||||
title: تفعيل سجل الملفات الشخصية
|
||||
registrations:
|
||||
closed_message:
|
||||
desc_html: يتم عرضه على الصفحة الرئيسية عندما يتم غلق تسجيل الحسابات الجديدة. يمكنكم إستخدام علامات الأيتش تي أم أل HTML
|
||||
title: رسالة التسجيلات المقفلة
|
||||
deletion:
|
||||
desc_html: السماح لأي مستخدم إغلاق حسابه
|
||||
title: السماح بحذف الحسابات
|
||||
min_invite_role:
|
||||
disabled: لا أحد
|
||||
title: المستخدِمون المصرح لهم لإرسال الدعوات
|
||||
show_known_fediverse_at_about_page:
|
||||
desc_html: عند التثبت ، سوف تظهر toots من جميع fediverse المعروفة على عرض مسبق. وإلا فإنه سيعرض فقط toots المحلية.
|
||||
title: إظهار الفيديفرس الموحَّد في خيط المُعايَنة
|
||||
show_staff_badge:
|
||||
desc_html: عرض شارة الموظفين على صفحة المستخدم
|
||||
title: إظهار شارة الموظفين
|
||||
site_description:
|
||||
desc_html: فقرة تمهيدية على الصفحة الأولى. صف ميزات خادوم ماستدون هذا و ما يميّزه عن الآخرين. يمكنك استخدام علامات HTML ، ولا سيما <code><a></code> و <code><em></code>.
|
||||
title: وصف مثيل الخادوم
|
||||
site_description_extended:
|
||||
desc_html: مكان جيد لمدونة قواعد السلوك والقواعد والإرشادات وغيرها من الأمور التي تحدد حالتك. يمكنك استخدام علامات HTML
|
||||
title: الوصف المُفصّل للموقع
|
||||
site_short_description:
|
||||
desc_html: يتم عرضه في لوحة جانبية و في البيانات الوصفية. قم بوصف ماستدون و ما يميز هذا السيرفر عن الآخرين في فقرة موجزة. إن تركت الحقل فارغا فسوف يتم عرض الوصف الإفتراضي لمثيل الخادوم.
|
||||
title: مقدمة وصفية قصيرة عن مثيل الخادوم
|
||||
site_terms:
|
||||
desc_html: يمكنك كتابة سياسة الخصوصية الخاصة بك ، شروط الخدمة أو غيرها من القوانين. يمكنك استخدام علامات HTML
|
||||
title: شروط الخدمة المخصصة
|
||||
site_title: إسم مثيل الخادم
|
||||
thumbnail:
|
||||
desc_html: يستخدم للعروض السابقة عبر Open Graph و API. 1200x630px موصى به
|
||||
title: الصورة الرمزية المصغرة لمثيل الخادوم
|
||||
timeline_preview:
|
||||
desc_html: عرض الخيط العمومي على صفحة الإستقبال
|
||||
title: مُعاينة الخيط العام
|
||||
title: إعدادات الموقع
|
||||
statuses:
|
||||
back_to_account: العودة إلى صفحة الحساب
|
||||
batch:
|
||||
delete: حذف
|
||||
nsfw_off: تعيينه كمنشور غير حساس
|
||||
nsfw_on: تعيينه كمنشور حساس
|
||||
failed_to_execute: خطأ في التفعيل
|
||||
media:
|
||||
title: الوسائط
|
||||
no_media: لا تحتوي على وسائط
|
||||
no_status_selected: لم يطرأ أي تغيير على أي منشور بما أنه لم يتم اختيار أي واحد
|
||||
title: منشورات الحساب
|
||||
with_media: تحتوي على وسائط
|
||||
subscriptions:
|
||||
callback_url: عاود الاتصال بالعنوان
|
||||
confirmed: مؤكَّد
|
||||
expires_in: تنتهي مدة صلاحيتها في
|
||||
last_delivery: آخر إيداع
|
||||
title: WebSub
|
||||
topic: الموضوع
|
||||
tags:
|
||||
accounts: الحسابات
|
||||
hidden: المخفية
|
||||
hide: الإخفاء عن سجل الحسابات
|
||||
name: الوسم
|
||||
title: الوسوم
|
||||
unhide: إظهاره في سجل حسابات المستخدمين
|
||||
visible: ظاهر
|
||||
title: الإدارة
|
||||
warning_presets:
|
||||
add_new: إضافة واحد جديد
|
||||
delete: حذف
|
||||
edit: تعديل
|
||||
edit_preset: تعديل نموذج التحذير
|
||||
title: إدارة نماذج التحذير
|
||||
admin_mailer:
|
||||
new_report:
|
||||
body: قام %{reporter} بالإبلاغ عن %{target}
|
||||
body_remote: أبلغ شخص ما من %{domain} عن %{target}
|
||||
subject: تقرير جديد ل%{instance} (#%{id})
|
||||
application_mailer:
|
||||
notification_preferences: تعديل خيارات البريد الإلكتروني
|
||||
salutation: "%{name}،"
|
||||
settings: 'تغيير تفضيلات البريد الإلكتروني : %{link}'
|
||||
view: 'View:'
|
||||
view_profile: عرض الملف الشخصي
|
||||
view_status: عرض المنشور
|
||||
applications:
|
||||
created: تم إنشاء التطبيق بنجاح
|
||||
destroyed: تم حذف التطبيق بنجاح
|
||||
invalid_url: إن الرابط المقدم غير صالح
|
||||
regenerate_token: إعادة توليد رمز النفاذ
|
||||
token_regenerated: تم إعادة إنشاء الرمز الوصول بنجاح
|
||||
warning: كن حذرا مع هذه البيانات. لا تقم أبدا بمشاركتها مع الآخَرين !
|
||||
your_token: رمز نفاذك
|
||||
auth:
|
||||
change_password: الكلمة السرية
|
||||
confirm_email: تأكيد عنوان البريد الإلكتروني
|
||||
delete_account: حذف حساب
|
||||
delete_account_html: إن كنت ترغب في حذف حسابك يُمكنك <a href="%{path}">المواصلة هنا</a>. سوف يُطلَبُ منك التأكيد قبل الحذف.
|
||||
didnt_get_confirmation: لم تتلق تعليمات التأكيد ؟
|
||||
forgot_password: نسيت كلمة المرور ؟
|
||||
invalid_reset_password_token: رمز إعادة تعيين كلمة المرور غير صالح أو منتهي الصلاحية. يرجى طلب واحد جديد.
|
||||
login: تسجيل الدخول
|
||||
logout: خروج
|
||||
migrate_account: الإنتقال إلى حساب آخر
|
||||
migrate_account_html: إن كنت ترغب في تحويل هذا الحساب نحو حساب آخَر، يُمكِنُك <a href="%{path}">إعداده هنا</a>.
|
||||
or_log_in_with: أو قم بتسجيل الدخول بواسطة
|
||||
providers:
|
||||
cas: CAS
|
||||
saml: SAML
|
||||
register: إنشاء حساب
|
||||
resend_confirmation: إعادة إرسال تعليمات التأكيد
|
||||
reset_password: إعادة تعيين كلمة المرور
|
||||
security: الأمان
|
||||
set_new_password: إدخال كلمة مرور جديدة
|
||||
authorize_follow:
|
||||
already_following: أنت تتابع بالفعل هذا الحساب
|
||||
error: يا للأسف، وقع هناك خطأ إثر عملية البحث عن الحساب عن بعد
|
||||
follow: إتبع
|
||||
follow_request: 'لقد قمت بإرسال طلب متابعة إلى :'
|
||||
following: 'مرحى ! أنت الآن تتبع :'
|
||||
post_follow:
|
||||
close: أو يمكنك إغلاق هذه النافذة.
|
||||
return: عرض الملف الشخصي للمستخدم
|
||||
web: واصل إلى الويب
|
||||
title: إتباع %{acct}
|
||||
datetime:
|
||||
distance_in_words:
|
||||
about_x_hours: "%{count}سا"
|
||||
about_x_months: "%{count} شهر"
|
||||
about_x_years: "%{count} سنة"
|
||||
almost_x_years: "%{count} سنوات"
|
||||
half_a_minute: الآن
|
||||
less_than_x_minutes: "%{count} د"
|
||||
less_than_x_seconds: الآن
|
||||
over_x_years: "%{count} سنين"
|
||||
x_days: "%{count} أيام"
|
||||
x_minutes: "%{count}د"
|
||||
x_months: "%{count} شه"
|
||||
x_seconds: "%{count}ث"
|
||||
deletes:
|
||||
bad_password_msg: محاولة جيدة يا هاكرز ! كلمة السر خاطئة
|
||||
confirm_password: قم بإدخال كلمتك السرية الحالية للتحقق من هويتك
|
||||
proceed: حذف حساب
|
||||
success_msg: تم حذف حسابك بنجاح
|
||||
warning_title: توافر المحتوى المنشور و المبعثَر
|
||||
directories:
|
||||
directory: سِجلّ الحسابات
|
||||
enabled: إنّ حسابك الآن ضمن فهرس المستخدِمين.
|
||||
explanation: استكشف مستخدِمين آخرين حسب المواضيع التي تهمهم
|
||||
explore_gabsocial: استكشف %{title}
|
||||
people:
|
||||
few: "%{count} شخص"
|
||||
many: "%{count} شخص"
|
||||
one: "%{count} شخص"
|
||||
other: "%{count} شخص"
|
||||
two: "%{count} شخص"
|
||||
zero: "%{count} شخص"
|
||||
errors:
|
||||
'403': ليس لك الصلاحيات الكافية لعرض هذه الصفحة.
|
||||
'404': إنّ الصفحة التي تبحث عنها لا وجود لها أصلا.
|
||||
'410': إنّ الصفحة التي تبحث عنها لم تعد موجودة.
|
||||
'422':
|
||||
content: فشل التحقق الآمن. ربما منعتَ كعكات الكوكيز ؟
|
||||
title: فشِل التحقق الآمن
|
||||
'429': طلبات كثيرة جدا
|
||||
'500':
|
||||
content: نحن متأسفون، لقد حدث خطأ ما مِن جانبنا.
|
||||
title: هذه الصفحة خاطئة
|
||||
noscript_html: يرجى تفعيل الجافا سكريبت لاستخدام تطبيق الويب لماستدون، أو عِوض ذلك قوموا بتجريب إحدى <a href="%{apps_path}">التطبيقات الأصلية</a> الدّاعمة لماستدون على منصّتكم.
|
||||
exports:
|
||||
archive_takeout:
|
||||
date: التاريخ
|
||||
download: تنزيل نسخة لحسابك
|
||||
hint_html: بإمكانك طلب نسخة كاملة لـ <strong>كافة تبويقاتك و الوسائط التي قمت بنشرها</strong>. البيانات المُصدَّرة ستكون محفوظة على شكل نسق ActivityPub و باستطاعتك قراءتها بأي برنامج يدعم هذا النسق. يُمكنك طلب نسخة كل 7 أيام.
|
||||
in_progress: عملية جمع نسخة لبيانات حسابك جارية …
|
||||
request: طلب نسخة لحسابك
|
||||
size: الحجم
|
||||
blocks: قمت بحظر
|
||||
csv: CSV
|
||||
domain_blocks: النطاقات المحظورة
|
||||
follows: أنت تتبع
|
||||
lists: القوائم
|
||||
mutes: قُمتَ بكتم
|
||||
storage: ذاكرة التخزين
|
||||
featured_tags:
|
||||
add_new: إضافة واحد
|
||||
filters:
|
||||
contexts:
|
||||
home: الخيط الزمني الرئيسي
|
||||
notifications: الإخطارات
|
||||
public: الخيوط الزمنية العامة
|
||||
thread: المحادثات
|
||||
edit:
|
||||
title: تعديل عامل التصفية
|
||||
errors:
|
||||
invalid_context: لم تقم بتحديد أي مجال أو أنّ المجال غير صالح
|
||||
invalid_irreversible: إلّا مجالات الإشعارات و الخيط الرئيسي معنية بالتصفية اللارجعية
|
||||
index:
|
||||
delete: إزالة
|
||||
title: عوامل التصفية
|
||||
new:
|
||||
title: إضافة عامل تصفية جديد
|
||||
footer:
|
||||
developers: المطورون
|
||||
more: المزيد …
|
||||
resources: الموارد
|
||||
generic:
|
||||
changes_saved_msg: تم حفظ التعديلات بنجاح !
|
||||
copy: نسخ
|
||||
save_changes: حفظ التغييرات
|
||||
validation_errors:
|
||||
few: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الأخطاء الـ %{count} أدناه
|
||||
many: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الأخطاء الـ %{count} أدناه
|
||||
one: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الخطأ أدناه
|
||||
other: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الأخطاء الـ %{count} أدناه
|
||||
two: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الأخطاء الـ %{count} أدناه
|
||||
zero: هناك شيء ما ليس على ما يرام! يُرجى مراجعة الأخطاء الـ %{count} أدناه
|
||||
imports:
|
||||
modes:
|
||||
merge: دمج
|
||||
merge_long: الإبقاء علي التسجيلات الحالية وإضافة الجديدة
|
||||
overwrite: إعادة الكتابة
|
||||
overwrite_long: استبدال التسجيلات الحالية بالجديدة
|
||||
preface: بإمكانك استيراد بيانات قد قُمتَ بتصديرها مِن مثيل خادوم آخَر، كقوائم المستخدِمين الذين كنتَ تتابِعهم أو قُمتَ بحظرهم.
|
||||
success: تم تحميل بياناتك بنجاح وسيتم معالجتها في الوقت المناسب
|
||||
types:
|
||||
blocking: قائمة المحظورين
|
||||
domain_blocking: قائمة النطاقات المحظورة
|
||||
following: قائمة المستخدمين المتبوعين
|
||||
muting: قائمة الكتم
|
||||
upload: تحميل
|
||||
in_memoriam_html: في ذكرى.
|
||||
invites:
|
||||
delete: تعطيل
|
||||
expired: إنتهت صلاحيتها
|
||||
expires_in:
|
||||
'1800': 30 دقيقة
|
||||
'21600': 6 ساعات
|
||||
'3600': ساعة
|
||||
'43200': 12 ساعة
|
||||
'604800': أسبوع
|
||||
'86400': يوم واحد
|
||||
expires_in_prompt: أبدا
|
||||
generate: توليد
|
||||
invited_by: 'تمت دعوتك من طرف :'
|
||||
max_uses:
|
||||
few: "%{count} استخدامات"
|
||||
many: "%{count} استخدامات"
|
||||
one: استخدام واحد
|
||||
other: "%{count} استخدامات"
|
||||
two: استخدامات
|
||||
zero: استخدامات
|
||||
max_uses_prompt: بلا حدود
|
||||
prompt: توليد و مشاركة روابط للسماح للآخَرين بالنفاذ إلى مثيل الخادوم هذا
|
||||
table:
|
||||
expires_at: تنتهي مدة صلاحيتها في
|
||||
uses: عدد الاستخدامات
|
||||
title: دعوة أشخاص
|
||||
lists:
|
||||
errors:
|
||||
limit: لقد بلغت الحد الأقصى للقوائم
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: ليس بالإمكان إرفاق فيديو في منشور يحتوي مسبقا على صور
|
||||
too_many: لا يمكن إرفاق أكثر من 4 ملفات
|
||||
migrations:
|
||||
acct: username@domain للحساب الجديد
|
||||
currently_redirecting: 'تم تحويل رابط ملفك الشخصي إلى :'
|
||||
proceed: حفظ
|
||||
updated_msg: تم تحديث إعدادات ترحيل حسابك بنجاح !
|
||||
moderation:
|
||||
title: الإشراف
|
||||
notification_mailer:
|
||||
digest:
|
||||
action: معاينة كافة الإشعارات
|
||||
body: هذا هو مُلَخَّص الرسائل التي فاتتك وذلك منذ آخر زيارة لك في %{since}
|
||||
mention: "%{name} أشار إليك في :"
|
||||
new_followers_summary:
|
||||
few: رائع، لقد قام بمتابَعتك %{count} مُتابِعون جُدد أثناء فترة غيابك عن ماستدون!
|
||||
many: رائع، لقد قام بمتابَعتك %{count} مُتابِعون جُدد أثناء فترة غيابك عن ماستدون!
|
||||
one: و لقد تحصّلتَ كذلك على مُتابِع آخَر بينما كنتَ غائبًا! هذا شيء رائع!
|
||||
other: رائع، لقد قام بمتابَعتك %{count} مُتابِعون جُدد أثناء فترة غيابك عن ماستدون!
|
||||
two: رائع، لقد قام بمتابَعتك %{count} مُتابِعون جُدد أثناء فترة غيابك عن ماستدون!
|
||||
zero: رائع، لقد قام بمتابَعتك %{count} مُتابِعون جُدد أثناء فترة غيابك عن ماستدون!
|
||||
subject:
|
||||
few: "%{count} إشعارات جديدة منذ آخر زيارة لك إلى \U0001F418"
|
||||
many: "%{count} إشعارات جديدة منذ آخر زيارة لك إلى \U0001F418"
|
||||
one: "إشعار واحد 1 منذ آخر زيارة لك لـ \U0001F418"
|
||||
other: "%{count} إشعارات جديدة منذ آخر زيارة لك إلى \U0001F418"
|
||||
two: "إشعارات جديدة منذ آخر زيارة لك إلى \U0001F418"
|
||||
zero: "إشعارات جديدة منذ آخر زيارة لك إلى \U0001F418"
|
||||
title: أثناء فترة غيابك …
|
||||
favourite:
|
||||
body: 'أُعجب %{name} بمنشورك :'
|
||||
subject: أُعجِب %{name} بمنشورك
|
||||
title: مفضّلة جديدة
|
||||
follow:
|
||||
body: "%{name} من متتبعيك الآن !"
|
||||
subject: "%{name} من متتبعيك الآن"
|
||||
title: متابِع جديد
|
||||
follow_request:
|
||||
action: إدارة طلبات المتابَعة
|
||||
body: طلب %{name} متابعتك
|
||||
subject: 'متابع مُعلّق : %{name}'
|
||||
title: طلب متابَعة جديد
|
||||
mention:
|
||||
action: الرد
|
||||
body: 'أشار إليك %{name} في :'
|
||||
subject: لقد قام %{name} بذِكرك
|
||||
title: إشارة جديدة
|
||||
reblog:
|
||||
body: 'قام %{name} بترقية منشورك :'
|
||||
subject: قام %{name} بترقية منشورك
|
||||
title: ترقية جديدة
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
format: "%n%u"
|
||||
units:
|
||||
billion: B
|
||||
million: M
|
||||
quadrillion: كواد
|
||||
thousand: ألف
|
||||
trillion: T
|
||||
unit: ''
|
||||
pagination:
|
||||
newer: الأحدَث
|
||||
next: التالي
|
||||
older: الأقدَم
|
||||
prev: السابق
|
||||
truncate: و
|
||||
preferences:
|
||||
languages: اللغات
|
||||
other: إعدادات أخرى
|
||||
publishing: النشر
|
||||
web: الويب
|
||||
remote_follow:
|
||||
acct: قم بإدخال عنوان حسابك username@domain الذي من خلاله تود النشاط
|
||||
missing_resource: تعذر العثور على رابط التحويل المطلوب الخاص بحسابك
|
||||
no_account_html: أليس عندك حساب بعدُ ؟ يُمْكنك <a href='%{sign_up_path}' target='_blank'>التسجيل مِن هنا</a>
|
||||
proceed: أكمل المتابعة
|
||||
prompt: 'إنك بصدد متابعة :'
|
||||
remote_interaction:
|
||||
favourite:
|
||||
proceed: المواصلة إلى المفضلة
|
||||
prompt: 'ترغب في إضافة هذا التبويق إلى مفضلتك:'
|
||||
reblog:
|
||||
proceed: المواصلة إلى الترقية
|
||||
prompt: 'ترغب في ترقية هذا التبويق:'
|
||||
reply:
|
||||
proceed: المواصلة إلى الرد
|
||||
prompt: 'ترغب في الرد على هذا التبويق:'
|
||||
remote_unfollow:
|
||||
error: خطأ
|
||||
title: العنوان
|
||||
unfollowed: غير متابَع
|
||||
sessions:
|
||||
activity: آخر نشاط
|
||||
browser: المتصفح
|
||||
browsers:
|
||||
alipay: أليباي
|
||||
blackberry: بلاك بيري
|
||||
chrome: كروم
|
||||
edge: مايكروسوفت إيدج
|
||||
electron: إلكترون
|
||||
firefox: فايرفكس
|
||||
generic: متصفح مجهول
|
||||
ie: إنترنت إكسبلورر
|
||||
micro_messenger: مايكرو ميسنجر
|
||||
nokia: متصفح Nokia S40 Ovi
|
||||
opera: أوبرا
|
||||
otter: أوتر
|
||||
phantom_js: فانتوم جي آس
|
||||
qq: متصفح كيوكيو
|
||||
safari: سفاري
|
||||
uc_browser: متصفح يوسي براوزر
|
||||
weibo: وايبو
|
||||
current_session: الجلسة الحالية
|
||||
description: "%{browser} على %{platform}"
|
||||
explanation: ها هي قائمة مُتصفِّحات الويب التي تستخدِم حاليًا حساب ماستدون الخاص بك.
|
||||
ip: عنوان الإيبي
|
||||
platforms:
|
||||
adobe_air: أدوبي إيير
|
||||
android: أندرويد
|
||||
blackberry: بلاك بيري
|
||||
chrome_os: نظام كروم أواس
|
||||
firefox_os: نظام فايرفكس أواس
|
||||
ios: نظام آي أواس
|
||||
linux: لينكس
|
||||
mac: ماك
|
||||
other: نظام مجهول
|
||||
windows: ويندوز
|
||||
windows_mobile: ويندوز موبايل
|
||||
windows_phone: ويندوز فون
|
||||
revoke: إبطال
|
||||
revoke_success: تم إبطال الجلسة بنجاح
|
||||
title: الجلسات
|
||||
settings:
|
||||
authorized_apps: التطبيقات المرخص لها
|
||||
back: عودة إلى ماستدون
|
||||
delete: حذف الحسابات
|
||||
development: التطوير
|
||||
edit_profile: تعديل الملف الشخصي
|
||||
export: تصدير البيانات
|
||||
import: إستيراد
|
||||
migrate: تهجير الحساب
|
||||
notifications: الإخطارات
|
||||
preferences: التفضيلات
|
||||
two_factor_authentication: المُصادقة بخُطوَتَيْن
|
||||
statuses:
|
||||
attached:
|
||||
description: 'مُرفَق : %{attached}'
|
||||
image:
|
||||
few: "%{count} صور"
|
||||
many: "%{count} صور"
|
||||
one: صورة %{count}
|
||||
other: "%{count} صور"
|
||||
two: صور
|
||||
zero: صور
|
||||
video:
|
||||
few: "%{count} فيديوهات"
|
||||
many: "%{count} فيديوهات"
|
||||
one: فيديو %{count}
|
||||
other: "%{count} فيديوهات"
|
||||
two: فيديوهات
|
||||
zero: فيديوهات
|
||||
boosted_from_html: تم إعادة ترقيته مِن %{acct_link}
|
||||
content_warning: 'تحذير عن المحتوى : %{warning}'
|
||||
disallowed_hashtags:
|
||||
few: 'يحتوي على وسوم غير مسموح بها: %{tags}'
|
||||
many: 'يحتوي على وسوم غير مسموح بها: %{tags}'
|
||||
one: 'يحتوي على وسم غير مسموح به: %{tags}'
|
||||
other: 'يحتوي على وسوم غير مسموح بها: %{tags}'
|
||||
two: 'يحتوي على وسوم غير مسموح بها: %{tags}'
|
||||
zero: 'يحتوي على وسوم غير مسموح بها: %{tags}'
|
||||
language_detection: اكتشاف اللغة تلقائيا
|
||||
open_in_web: إفتح في الويب
|
||||
over_character_limit: تم تجاوز حد الـ %{max} حرف المسموح بها
|
||||
pin_errors:
|
||||
limit: لقد بلغت الحد الأقصى للتبويقات المدبسة
|
||||
ownership: لا يمكن تدبيس تبويق نشره شخص آخر
|
||||
private: لا يمكن تدبيس تبويق لم يُنشر للعامة
|
||||
reblog: لا يمكن تثبيت ترقية
|
||||
show_more: أظهر المزيد
|
||||
sign_in_to_participate: قم بتسجيل الدخول للمشاركة في هذه المحادثة
|
||||
title: '%{name} : "%{quote}"'
|
||||
visibilities:
|
||||
private: إعرض فقط لمتتبعيك
|
||||
private_long: إعرضه لمتتبعيك فقط
|
||||
public: للعامة
|
||||
public_long: يمكن للجميع رؤيته
|
||||
unlisted: غير مُدرَج
|
||||
unlisted_long: يُمكن لأيٍ كان رُؤيتَه و لكن لن يُعرَض على الخيوط العامة
|
||||
stream_entries:
|
||||
pinned: تبويق مثبّت
|
||||
reblogged: رقّاه
|
||||
sensitive_content: محتوى حساس
|
||||
terms:
|
||||
title: شروط الخدمة وسياسة الخصوصية على %{instance}
|
||||
themes:
|
||||
contrast: تباين عالٍ
|
||||
default: ماستدون
|
||||
gabsocial-light: ماستدون (فاتح)
|
||||
time:
|
||||
formats:
|
||||
default: "%b %d, %Y, %H:%M"
|
||||
month: "%b %Y"
|
||||
two_factor_authentication:
|
||||
code_hint: قم بإدخال الرمز المُوَلّد عبر تطبيق المصادقة للتأكيد
|
||||
description_html: في حال تفعيل <strong>المصادقة بخطوتين </strong>، فتسجيل الدخول يتطلب منك أن يكون بحوزتك هاتفك النقال قصد توليد الرمز الذي سيتم إدخاله.
|
||||
disable: تعطيل
|
||||
enable: تفعيل
|
||||
enabled: نظام المصادقة بخطوتين مُفعَّل
|
||||
enabled_success: تم تفعيل المصادقة بخطوتين بنجاح
|
||||
generate_recovery_codes: توليد رموز الإسترجاع
|
||||
instructions_html: "<strong>قم بمسح رمز الكيو آر عبر Google Authenticator أو أي تطبيق TOTP على جهازك</strong>. من الآن فصاعدا سوف يقوم ذاك التطبيق بتوليد رموز يجب عليك إدخالها عند تسجيل الدخول."
|
||||
lost_recovery_codes: تُمكّنك رموز الإسترجاع الإحتاطية مِن استرجاع النفاذ إلى حسابك في حالة فقدان جهازك المحمول. إن ضاعت منك هذه الرموز فبإمكانك إعادة توليدها مِن هنا و إبطال الرموز القديمة.
|
||||
manual_instructions: 'في حالة تعذّر مسح رمز الكيو آر أو طُلب منك إدخال يدوي، يُمْكِنك إدخال هذا النص السري على التطبيق :'
|
||||
recovery_codes: النسخ الإحتياطي لرموز الإسترجاع
|
||||
recovery_codes_regenerated: تم إعادة توليد رموز الإسترجاع الإحتياطية بنجاح
|
||||
setup: تنشيط
|
||||
wrong_code: الرمز الذي أدخلته غير صالح ! تحقق من صحة الوقت على الخادم و الجهاز ؟
|
||||
user_mailer:
|
||||
backup_ready:
|
||||
explanation: لقد قمت بطلب نسخة كاملة لحسابك على ماستدون. إنها متوفرة الآن للتنزيل !
|
||||
subject: نسخة بيانات حسابك جاهزة للتنزيل
|
||||
title: المغادرة بأرشيف الحساب
|
||||
warning:
|
||||
review_server_policies: مراجعة شروط السيرفر
|
||||
subject:
|
||||
disable: تم تجميد حسابك %{acct}
|
||||
none: تحذير إلى %{acct}
|
||||
suspend: لقد تم تعليق حسابك %{acct}
|
||||
title:
|
||||
disable: الحساب مُجمَّد
|
||||
none: تحذير
|
||||
suspend: الحساب مُعلَّق
|
||||
welcome:
|
||||
edit_profile_action: تهيئة الملف الشخصي
|
||||
edit_profile_step: يُمكنك·كي تخصيص ملفك الشخصي عن طريق تحميل صورة رمزية ورأسية و بتعديل إسمك·كي العلني وأكثر. و إن أردت·تي معاينة المتابِعين و المتابعات الجُدد قبيل السماح لهم·ن بمتابَعتك فيمكنك·كي تأمين حسابك·كي.
|
||||
explanation: ها هي بعض النصائح قبل بداية الإستخدام
|
||||
final_action: اشرَع في النشر
|
||||
final_step: |-
|
||||
يمكنك الشروع في النشر في الحين ! حتى و إن لم كنت لا تمتلك متابِعين بعدُ، يمكن للآخرين الإطلاع على منشوراتك الموجهة للجمهور على الخيط المحلي أو إن قمت باستخدام وسوم.
|
||||
إبدأ بتقديم نفسك باستعمال وسم #introductions.
|
||||
full_handle: عنوانك الكامل
|
||||
full_handle_hint: هذا هو ما يجب تقديمه لأصدقائك قصد أن يكون بإمكانهم متابَعتك أو مُراسَلتك حتى و إن كانت حساباتهم على خوادم أخرى.
|
||||
review_preferences_action: تعديل التفضيلات
|
||||
subject: أهلًا بك على ماستدون
|
||||
tip_federated_timeline: الخيط الزمني الفديرالي هو بمثابة شبه نظرة شاملة على شبكة ماستدون. غير أنه لا يشمل إلا على الأشخاص المتابَعين مِن طرف جيرانك و جاراتك، لذا فهذا الخيط لا يعكس كافة الشبكة برُمّتها.
|
||||
tip_following: أنت تتبع تلقائيا مديري و مديرات الخادم. للعثور على أشخاص مميزين أو قد تهمك حساباتهم بإمكانك الإطلاع على الخيوط المحلية و كذا الفدرالية.
|
||||
tip_local_timeline: الخيط الزمني المحلي هو بمثابة نظرة سريعة على الأشخاص المتواجدين على %{instance} يمكن اعتبارهم كجيرانك وجاراتك الأقرب إليك!
|
||||
tips: نصائح
|
||||
title: أهلاً بك، %{name} !
|
||||
users:
|
||||
follow_limit_reached: لا يمكنك متابعة أكثر مِن %{limit} أشخاص
|
||||
invalid_email: عنوان البريد الإلكتروني غير صالح
|
||||
invalid_otp_token: رمز المصادقة بخطوتين غير صالح
|
||||
otp_lost_help_html: إن فقدتَهُما ، يمكنك الإتصال بـ %{email}
|
||||
seamless_external_login: لقد قمت بتسجيل الدخول عبر خدمة خارجية، إنّ إعدادات الكلمة السرية و البريد الإلكتروني غير متوفرة.
|
||||
signed_in_as: 'تم تسجيل دخولك بصفة :'
|
||||
verification:
|
||||
verification: التحقق
|
||||
347
config/locales/ast.yml
Normal file
347
config/locales/ast.yml
Normal file
@@ -0,0 +1,347 @@
|
||||
---
|
||||
ast:
|
||||
about:
|
||||
about_gabsocial_html: Gab Social ye una rede social basada en protocolos abiertos y software de códigu llibre. Ye descentralizada, como'l corréu electrónicu.
|
||||
about_this: Tocante a
|
||||
administered_by: 'Alministráu por:'
|
||||
api: API
|
||||
contact: Contautu
|
||||
contact_missing: Nun s'afitó
|
||||
contact_unavailable: N/D
|
||||
documentation: Documentación
|
||||
extended_description_html: |
|
||||
<h3>Un llugar bonu pa les regles</h3>
|
||||
<p>Entá nun se configuró la descripción estendida.</p>
|
||||
hosted_on: Gab Social ta agospiáu en %{domain}
|
||||
learn_more: Deprendi más
|
||||
source_code: Códigu fonte
|
||||
status_count_after: estaos
|
||||
status_count_before: Que crearon
|
||||
terms: Términos del serviciu
|
||||
user_count_after:
|
||||
one: usuariu
|
||||
other: usuarios
|
||||
user_count_before: Ye'l llar de
|
||||
what_is_gabsocial: "¿Qué ye Gab Social?"
|
||||
accounts:
|
||||
followers:
|
||||
one: Xente que te sigue
|
||||
other: Siguidores
|
||||
joined: Xunióse en %{date}
|
||||
moved_html: "%{name} mudóse a %{new_profile_link}:"
|
||||
network_hidden: Esta información nun ta disponible
|
||||
nothing_here: "¡Equí nun hai nada!"
|
||||
people_followed_by: Persones a les que sigue %{name}
|
||||
people_who_follow: Persones que siguen a %{name}
|
||||
posts:
|
||||
one: Toot
|
||||
other: Toots
|
||||
posts_tab_heading: Toots
|
||||
posts_with_replies: Toots y rempuestes
|
||||
reserved_username: El nome d'usuariu ta acutáu
|
||||
roles:
|
||||
bot: Robó
|
||||
admin:
|
||||
accounts:
|
||||
are_you_sure: "¿De xuru?"
|
||||
avatar: Avatar
|
||||
by_domain: Dominiu
|
||||
domain: Dominiu
|
||||
email: Corréu
|
||||
followers: Siguidores
|
||||
ip: IP
|
||||
location:
|
||||
local: Llocal
|
||||
title: Allugamientu
|
||||
protocol: Protocolu
|
||||
resend_confirmation:
|
||||
already_confirmed: Esti usuariu yá ta confirmáu
|
||||
role: Permisos
|
||||
roles:
|
||||
admin: Alministrador
|
||||
moderator: Llendador
|
||||
user: Usuariu
|
||||
statuses: Estaos
|
||||
title: Cuentes
|
||||
username: Nome d'usuariu
|
||||
web: Web
|
||||
action_logs:
|
||||
actions:
|
||||
create_domain_block: "%{name} bloquió'l dominiu %{target}"
|
||||
disable_custom_emoji: "%{name} desactivó'l fustaxe %{target}"
|
||||
disable_user: "%{name} desactivó l'aniciu de sesión del usuariu %{target}"
|
||||
custom_emojis:
|
||||
by_domain: Dominiu
|
||||
copy_failed_msg: Nun pudo facese una copia llocal d'esi fustaxe
|
||||
emoji: Fustaxe
|
||||
update_failed_msg: Nun pudo anovase esi fustaxe
|
||||
dashboard:
|
||||
config: Configuración
|
||||
feature_registrations: Rexistros
|
||||
features: Carauterístiques
|
||||
hidden_service: Federación con servicios anubríos
|
||||
recent_users: Usuarios recientes
|
||||
software: Software
|
||||
total_users: usuarios en total
|
||||
week_interactions: interaiciones d'esta selmana
|
||||
week_users_new: usuarios d'esta selmana
|
||||
domain_blocks:
|
||||
domain: Dominiu
|
||||
email_domain_blocks:
|
||||
domain: Dominiu
|
||||
instances:
|
||||
title: Instancies conocíes
|
||||
invites:
|
||||
filter:
|
||||
available: Disponible
|
||||
expired: Caducó
|
||||
title: Invitaciones
|
||||
relays:
|
||||
save_and_enable: Guardar y activar
|
||||
reports:
|
||||
are_you_sure: "¿De xuru?"
|
||||
status: Estáu
|
||||
settings:
|
||||
registrations:
|
||||
min_invite_role:
|
||||
disabled: Naide
|
||||
site_description:
|
||||
title: Descipción de la instancia
|
||||
site_title: Nome de la instancia
|
||||
title: Axustes del sitiu
|
||||
statuses:
|
||||
failed_to_execute: Fallu al executar
|
||||
subscriptions:
|
||||
title: WebSub
|
||||
title: Alministración
|
||||
admin_mailer:
|
||||
new_report:
|
||||
body_remote: Daquién dende %{domain} informó de %{target}
|
||||
application_mailer:
|
||||
salutation: "%{name},"
|
||||
applications:
|
||||
invalid_url: La URL apurrida nun ye válida
|
||||
warning: Ten curiáu con estos datos, ¡enxamás nun los compartas con naide!
|
||||
auth:
|
||||
change_password: Contraseña
|
||||
delete_account: Desaniciu de la cuenta
|
||||
delete_account_html: Si deseyes desaniciar la to cuenta, pues <a href="%{path}">siguir equí</a>. Va pidísete la confirmación.
|
||||
forgot_password: "¿Escaeciesti la contraseña?"
|
||||
login: Aniciar sesión
|
||||
migrate_account: Mudase a otra cuenta
|
||||
migrate_account_html: Si deseyes redirixir esta cuenta a otra, pues <a href="%{path}"> configuralo equí</a>.
|
||||
providers:
|
||||
cas: CAS
|
||||
saml: SAML
|
||||
register: Rexistrase
|
||||
security: Seguranza
|
||||
authorize_follow:
|
||||
already_following: Yá tas siguiendo a esta cuenta
|
||||
error: Desafortunadamente, hebo un fallu guetando la cuenta remota
|
||||
follow_request: 'Unviesti una solicitú de siguimientu a:'
|
||||
post_follow:
|
||||
close: O pues zarrar esta ventana.
|
||||
return: Amosar el perfil del usuariu
|
||||
web: Dir a la web
|
||||
datetime:
|
||||
distance_in_words:
|
||||
half_a_minute: Púramente agora
|
||||
less_than_x_seconds: Púramente agora
|
||||
deletes:
|
||||
bad_password_msg: "¡Bon intentu, crackers! Contraseña incorreuta"
|
||||
confirm_password: Introduz la contraseña pa verificar la to identidá
|
||||
directories:
|
||||
people:
|
||||
one: "%{count} persona"
|
||||
other: "%{count} persones"
|
||||
errors:
|
||||
'403': Nun tienes permisu pa ver esta páxina.
|
||||
'404': La páxina que tabes guetando nun esiste.
|
||||
'410': La páxina que tabes guetando yá nun esiste.
|
||||
'422':
|
||||
content: Falló la verificación de seguranza. ¿Tas bloquiando les cookies?
|
||||
title: Falló la verificación de seguranza
|
||||
'429': Ficiéronse milenta solicitúes
|
||||
exports:
|
||||
archive_takeout:
|
||||
date: Data
|
||||
hint_html: Pues solicitar un archivu colos tos <strong>toots y ficheros xubíos</strong>. Los datos esportaos van tar nel formatu ActivityPub, llexible pa cualesquier software que seya compatible. Pues solicitar un archivu cada 7 díes.
|
||||
request: Solicitar l'archivu
|
||||
size: Tamañu
|
||||
blocks: Xente que bloquiesti
|
||||
csv: CSV
|
||||
follows: Xente que sigues
|
||||
mutes: Xente que silenciesti
|
||||
filters:
|
||||
contexts:
|
||||
notifications: Avisos
|
||||
public: Llinies temporales públiques
|
||||
thread: Conversaciones
|
||||
index:
|
||||
title: Peñeres
|
||||
new:
|
||||
title: Amestar una peñera nueva
|
||||
generic:
|
||||
changes_saved_msg: "¡Los cambeos guardáronse con ésitu!"
|
||||
save_changes: Guardar cambeos
|
||||
imports:
|
||||
preface: Pues importar los datos qu'esportares dende otra instancia, como por exemplu la llista de persones que bloquiares o tubieres siguiendo.
|
||||
types:
|
||||
blocking: Llista de xente bloquiao
|
||||
following: Llista de siguidores
|
||||
muting: Llista de xente silenciao
|
||||
upload: Xubir
|
||||
invites:
|
||||
delete: Desactivar
|
||||
expired: Caducó
|
||||
expires_in:
|
||||
'1800': 30 minutos
|
||||
'21600': 6 hores
|
||||
'3600': 1 hora
|
||||
'43200': 12 hores
|
||||
'604800': 1 selmana
|
||||
'86400': 1 día
|
||||
expires_in_prompt: Enxamás
|
||||
invited_by: 'Convidóte:'
|
||||
max_uses:
|
||||
one: 1 usu
|
||||
other: "%{count} usos"
|
||||
table:
|
||||
expires_at: Data de caducidá
|
||||
uses: Usos
|
||||
lists:
|
||||
errors:
|
||||
limit: Algamesti la cantidá máxima de llistes
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: Nun pue axuntase un videu a un estáu que yá contién imáxenes
|
||||
too_many: Nun puen axuntase más de 4 ficheros
|
||||
migrations:
|
||||
acct: nome_usuariu@dominiu de la cuenta nueva
|
||||
proceed: Guardar
|
||||
notification_mailer:
|
||||
digest:
|
||||
body: Equí hai un resume de los mensaxes que nun viesti dende la última visita'l %{since}
|
||||
mention: "%{name} mentóte en:"
|
||||
subject:
|
||||
other: "%{count} avisos nuevos dende la última visita \U0001F418"
|
||||
follow:
|
||||
body: "¡Agora %{name} ta siguiéndote!"
|
||||
title: Siguidor nuevu
|
||||
follow_request:
|
||||
body: "%{name} solicitó siguite"
|
||||
title: Petición nueva de siguimientu
|
||||
mention:
|
||||
body: "%{name} mentóte en:"
|
||||
subject: "%{name} mentóte"
|
||||
title: Mención nueva
|
||||
reblog:
|
||||
body: "%{name} compartió'l to estáu:"
|
||||
subject: "%{name} compartió'l to estáu"
|
||||
title: Compartición nueva de toot
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
format: "%n%u"
|
||||
pagination:
|
||||
next: Siguiente
|
||||
preferences:
|
||||
languages: Llingües
|
||||
publishing: Espublización
|
||||
web: Web
|
||||
remote_follow:
|
||||
acct: Introduz el nome_usuariu@dominiu dende'l que lo quies facer
|
||||
no_account_html: "¿Nun tienes una cuenta? Pues <a href='%{sign_up_path}' target='_blank'>rexistrate equí</a>"
|
||||
proceed: Siguir
|
||||
prompt: 'Vas siguir a:'
|
||||
remote_unfollow:
|
||||
error: Fallu
|
||||
sessions:
|
||||
browser: Restolador
|
||||
browsers:
|
||||
alipay: Alipay
|
||||
blackberry: Blackberry
|
||||
chrome: Chrome
|
||||
edge: Microsoft Edge
|
||||
electron: Electron
|
||||
firefox: Firefox
|
||||
generic: Restolador desconocíu
|
||||
ie: Internet Explorer
|
||||
micro_messenger: MicroMessenger
|
||||
opera: Opera
|
||||
otter: Otter
|
||||
phantom_js: PhantomJS
|
||||
qq: QQ Browser
|
||||
safari: Safari
|
||||
uc_browser: UCBrowser
|
||||
weibo: Weibo
|
||||
current_session: Sesión actual
|
||||
description: "%{browser} en %{platform}"
|
||||
ip: IP
|
||||
platforms:
|
||||
adobe_air: Adobe Air
|
||||
android: Android
|
||||
blackberry: Blackberry
|
||||
chrome_os: ChromeOS
|
||||
firefox_os: Firefox OS
|
||||
ios: iOS
|
||||
linux: Linux
|
||||
mac: Mac
|
||||
other: plataforma desconocida
|
||||
windows: Windows
|
||||
windows_mobile: Windows Mobile
|
||||
windows_phone: Windows Phone
|
||||
title: Sesiones
|
||||
settings:
|
||||
authorized_apps: Aplicaciones autorizaes
|
||||
back: Volver a Gab Social
|
||||
edit_profile: Edición del perfil
|
||||
export: Esportación de datos
|
||||
import: Importación
|
||||
notifications: Avisos
|
||||
preferences: Preferencies
|
||||
two_factor_authentication: Autenticación en dos pasos
|
||||
statuses:
|
||||
attached:
|
||||
image:
|
||||
one: "%{count} imaxe"
|
||||
other: "%{count} imáxenes"
|
||||
video:
|
||||
one: "%{count} videu"
|
||||
other: "%{count} vídeos"
|
||||
boosted_from_html: Compartióse'l toot dende %{acct_link}
|
||||
language_detection: Deteutala automáticamente
|
||||
pin_errors:
|
||||
limit: Yá fixesti'l númberu máxiumu de toots
|
||||
ownership: Nun pue fixase'l toot d'otra persona
|
||||
private: Nun puen fixase los toots que nun seyan públicos
|
||||
reblog: Nun pue fixase un toot compartíu
|
||||
show_more: Amosar más
|
||||
title: "%{name}: «%{quote}»"
|
||||
visibilities:
|
||||
private: Namái siguidores
|
||||
stream_entries:
|
||||
reblogged: compartióse
|
||||
sensitive_content: Conteníu sensible
|
||||
themes:
|
||||
default: Gab Social
|
||||
two_factor_authentication:
|
||||
code_hint: Introduz el códigu xeneráu pola aplicación autenticadora pa confirmar
|
||||
disable: Desactivar
|
||||
enabled: L'autenticación en dos pasos ta activada
|
||||
enabled_success: L'autenticación en dos pasos activóse con ésitu
|
||||
generate_recovery_codes: Xenerar códigos de recuperación
|
||||
lost_recovery_codes: Los códigos de recuperación permítente recuperar l'accesu a la cuenta si pierdes el teléfonu. Si tamién pierdes esos códigos, pues xeneralos de nueves equí. Los códigos de recuperación vieyos van invalidase.
|
||||
manual_instructions: 'Si nun pues escaniar el códigu QR y precises introducilu a mano, equí ta''l secretu en testu planu:'
|
||||
recovery_codes: Códigos de recuperación
|
||||
recovery_codes_regenerated: Los códigos de recuperación rexeneráronse con ésitu
|
||||
user_mailer:
|
||||
welcome:
|
||||
full_handle_hint: Esto ye lo que-yos diríes a los collacios pa que puean unviate mensaxes o siguite dende otra instancia.
|
||||
subject: Afáyate en Gab Social
|
||||
tips: Conseyos
|
||||
users:
|
||||
invalid_email: La direición de corréu nun ye válida
|
||||
seamless_external_login: Aniciesti sesión pente un serviciu esternu, polo que los axustes de la contraseña y corréu nun tán disponibles.
|
||||
verification:
|
||||
verification: Verificación
|
||||
147
config/locales/bg.yml
Normal file
147
config/locales/bg.yml
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
bg:
|
||||
about:
|
||||
about_gabsocial_html: Gab Social е <em>безплатен</em> сървър с <em>отворен код</em> за социални мрежи. Като <em>децентрализирана</em> алтернатива на комерсиалните платформи, той позволява избягването на риска от монополизация на твоята комуникация от единични компании. Изберете си сървър, на който се доверявате, и ще можете да контактувате с всички останали. Всеки може да пусне Gab Social и лесно да вземе участие в <em>социалната мрежа</em>.
|
||||
about_this: За тази инстанция
|
||||
contact: За контакти
|
||||
source_code: Програмен код
|
||||
status_count_after: публикации
|
||||
status_count_before: Написали
|
||||
user_count_after: потребители
|
||||
user_count_before: Дом на
|
||||
accounts:
|
||||
follow: Последвай
|
||||
followers: Последователи
|
||||
following: Следва
|
||||
nothing_here: Тук няма никого!
|
||||
people_followed_by: Хора, които %{name} следва
|
||||
people_who_follow: Хора, които следват %{name}
|
||||
posts: Публикации
|
||||
unfollow: Не следвай
|
||||
application_mailer:
|
||||
settings: 'Промяна на предпочитанията за e-mail: %{link}'
|
||||
view: 'Преглед:'
|
||||
applications:
|
||||
invalid_url: Предоставеният URL е невалиден
|
||||
auth:
|
||||
didnt_get_confirmation: Не получих инструкции за потвърждение
|
||||
forgot_password: Забравих си паролата
|
||||
login: Влизане
|
||||
logout: Излизане
|
||||
register: Регистрация
|
||||
resend_confirmation: Изпрати отново инструкции за потвърждение
|
||||
reset_password: Подновяване на паролата
|
||||
security: Идентификационни данни
|
||||
set_new_password: Задай нова парола
|
||||
authorize_follow:
|
||||
error: Възникна грешка в откриването на потребителя
|
||||
follow: Последвай
|
||||
title: Последвай %{acct}
|
||||
datetime:
|
||||
distance_in_words:
|
||||
about_x_hours: "%{count} ч."
|
||||
about_x_months: "%{count} м."
|
||||
about_x_years: "%{count} г."
|
||||
almost_x_years: "%{count} г."
|
||||
half_a_minute: Току-що
|
||||
less_than_x_minutes: "%{count} мин."
|
||||
less_than_x_seconds: Току-що
|
||||
over_x_years: "%{count} г"
|
||||
x_days: "%{count} дни"
|
||||
x_minutes: "%{count} мин"
|
||||
x_months: "%{count} м"
|
||||
x_seconds: "%{count} сек"
|
||||
exports:
|
||||
blocks: Вашите блокирания
|
||||
csv: CSV
|
||||
follows: Вашите следвания
|
||||
storage: Съхранение на мултимедия
|
||||
generic:
|
||||
changes_saved_msg: Успешно запазване на промените!
|
||||
save_changes: Запази промените
|
||||
validation_errors: Нещо все още не е наред! Моля, прегледай грешките по-долу
|
||||
imports:
|
||||
preface: Можеш да импортираш някои данни, като например всички хора, които следваш или блокираш в акаунта си на тази инстанция, от файлове, създадени чрез експорт в друга инстанция.
|
||||
success: Твоите данни бяха успешно качени и ще бъдат обработени впоследствие
|
||||
types:
|
||||
blocking: Списък на блокираните
|
||||
following: Списък на последователите
|
||||
upload: Качване
|
||||
media_attachments:
|
||||
validations:
|
||||
images_and_video: Не мога да прикача видеоклип към публикация, която вече съдържа изображения
|
||||
too_many: Не мога да прикача повече от 4 файла
|
||||
notification_mailer:
|
||||
digest:
|
||||
body: Ето кратко резюме на нещата, които се случиха от последното ти посещение на %{since}
|
||||
mention: "%{name} те спомена в:"
|
||||
new_followers_summary:
|
||||
one: Имаш един нов последовател! Ура!
|
||||
other: Имаш %{count} нови последователи! Изумително!
|
||||
subject:
|
||||
one: "1 ново известие от последното ти посещение \U0001F418"
|
||||
other: "%{count} нови известия от последното ти посещение \U0001F418"
|
||||
favourite:
|
||||
body: 'Публикацията ти беше харесана от %{name}:'
|
||||
subject: "%{name} хареса твоята публикация"
|
||||
follow:
|
||||
body: "%{name} те последва!"
|
||||
subject: "%{name} те последва"
|
||||
follow_request:
|
||||
body: "%{name} помоли за разрешение да те последва"
|
||||
subject: 'Чакащ последовател: %{name}'
|
||||
mention:
|
||||
body: "%{name} те спомена в:"
|
||||
subject: "%{name} те спомена"
|
||||
reblog:
|
||||
body: 'Твоята публикация беше споделена от %{name}:'
|
||||
subject: "%{name} сподели публикацията ти"
|
||||
number:
|
||||
human:
|
||||
decimal_units:
|
||||
format: "%n%u"
|
||||
units:
|
||||
billion: B
|
||||
million: M
|
||||
quadrillion: Q
|
||||
thousand: K
|
||||
trillion: T
|
||||
unit: ''
|
||||
pagination:
|
||||
next: Напред
|
||||
prev: Назад
|
||||
remote_follow:
|
||||
acct: Въведи потребителско_име@домейн, от които искаш да следваш
|
||||
missing_resource: Неуспешно търсене на нужния URL за пренасочване за твоя акаунт
|
||||
proceed: Започни следване
|
||||
prompt: 'Ще последваш:'
|
||||
settings:
|
||||
authorized_apps: Упълномощени приложения
|
||||
back: Обратно към Gab Social
|
||||
edit_profile: Редактирай профила си
|
||||
export: Експортиране на данни
|
||||
import: Импортиране
|
||||
preferences: Предпочитания
|
||||
two_factor_authentication: Двустепенно удостоверяване
|
||||
statuses:
|
||||
open_in_web: Отвори в уеб
|
||||
over_character_limit: прехвърлен лимит от %{max} символа
|
||||
show_more: Покажи повече
|
||||
visibilities:
|
||||
private: Покажи само на последователите си
|
||||
public: Публично
|
||||
unlisted: Публично, но не показвай в публичния канал
|
||||
stream_entries:
|
||||
reblogged: споделено
|
||||
sensitive_content: Деликатно съдържание
|
||||
time:
|
||||
formats:
|
||||
default: "%d %b, %Y, %H:%M"
|
||||
two_factor_authentication:
|
||||
description_html: При активация на <strong>двустепенно удостоверяване</strong>, за да влезеш в приложението, ще трябва да използваш телефона си. През него ще се генерира код, който да въвеждаш при влизане.
|
||||
disable: Деактивирай
|
||||
enable: Активирай
|
||||
instructions_html: "<strong>Сканирай този QR код с Google Authenticator или подобно приложение от своя телефон</strong>. Oтсега нататък, това приложение ще генерира код, който ще трябва да въвеждаш при всяко влизане."
|
||||
users:
|
||||
invalid_email: E-mail адресът е невалиден
|
||||
invalid_otp_token: Невалиден код
|
||||
141
config/locales/bn.yml
Normal file
141
config/locales/bn.yml
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
bn:
|
||||
about:
|
||||
about_hashtag_html: এগুলো প্রকাশ্য লেখা যার হ্যাশট্যাগ <strong>#%{hashtag}</strong>। আপনি এগুলোর ব্যবহার বা সাথে যুক্ত হতে পারবেন যদি আপনার যুক্তবিশ্বের কোথাও নিবন্ধন থেকে থাকে।
|
||||
about_gabsocial_html: মাস্টাডন উন্মুক্ত ইন্টারনেটজালের নিয়ম এবং স্বাধীন ও মুক্ত উৎসের সফটওয়্যারের ভিত্তিতে তৈরী একটি সামাজিক যোগাযোগ মাধ্যম। এটি ইমেইলের মত বিকেন্দ্রীভূত।
|
||||
about_this: কি
|
||||
active_count_after: চালু
|
||||
active_footnote: মাসিক সক্রিয় ব্যবহারকারী
|
||||
administered_by: 'পরিচালনা করছেন:'
|
||||
api: সফটওয়্যার তৈরীর নিয়ম (API)
|
||||
apps: মোবাইল অ্যাপ
|
||||
apps_platforms: মাস্টাডন আইওএস, এন্ড্রোইড বা অন্য মাধ্যমে ব্যবহার করুন
|
||||
browse_directory: একটি ব্যবহারকারীদের তালিকা দেখুন এবং পছন্দ অনুসারে খুজুন
|
||||
browse_public_posts: মাস্টাডনে নতুন প্রকাশ্য লেখাগুলো সরাসরি দেখুন
|
||||
contact: যোগাযোগ
|
||||
contact_missing: নেই
|
||||
contact_unavailable: প্রযোজ্য নয়
|
||||
discover_users: ব্যবহারকারীদের দেখুন
|
||||
documentation: ব্যবহারবিলি
|
||||
extended_description_html: |
|
||||
<h3>নিয়মের জন্য উপযুক্ত জায়গা</h3>
|
||||
<p>বিস্তারিত বিবরণ এখনো যুক্ত করা হয়নি</p>
|
||||
federation_hint_html: "%{instance}তে একটা নিবন্ধন থাকলে আপনি যেকোনো মাস্টাডন বা এধরণের অন্যান্য সার্ভারের মানুষের সাথে যুক্ত হতে পারবেন ।"
|
||||
generic_description: নেটওয়ার্কের ভেতরে %{domain} একটি সার্ভার
|
||||
get_apps: মোবাইল এপ্প একটা ব্যবহার করতে পারেন
|
||||
hosted_on: এই মাস্টাডনটি আছে %{domain} এ
|
||||
learn_more: বিস্তারিত জানুন
|
||||
privacy_policy: গোপনীয়তা নীতি
|
||||
see_whats_happening: কী কী হচ্ছে দেখুন
|
||||
server_stats: 'সার্ভারের অবস্থা:'
|
||||
source_code: আসল তৈরীপত্র
|
||||
status_count_after:
|
||||
one: অবস্থা
|
||||
other: স্থিতিগুলি
|
||||
status_count_before: কে লিখেছে
|
||||
tagline: পরিচিতজনদের সাথে যুক্ত হন এবং নতুনদের সাথে পরিচিত হন
|
||||
terms: ব্যবহারের শর্তাবলী
|
||||
user_count_after:
|
||||
one: ব্যবহারকারী
|
||||
other: জনের
|
||||
user_count_before: বাসা
|
||||
what_is_gabsocial: মাস্টাডনটি কি ?
|
||||
accounts:
|
||||
choices_html: "%{name} বাছাই:"
|
||||
follow: যুক্ত
|
||||
followers:
|
||||
one: যুক্ত আছে
|
||||
other: যারা যুক্ত হয়েছে
|
||||
following: যুক্ত করা
|
||||
joined: যোগদান হয় %{date}
|
||||
last_active: শেষ সক্রিয় ছিল
|
||||
link_verified_on: এই লিংকের মালিকানা শেষ চেক করা হয় %{date} তারিখে
|
||||
media: ছবি বা ভিডিও
|
||||
moved_html: "%{name} চলে গেছে %{new_profile_link} তে:"
|
||||
network_hidden: এই তথ্যটি নেই
|
||||
nothing_here: এখানে কিছুই নেই!
|
||||
people_followed_by: "%{name} যাদেরকে অনুসরণ করে"
|
||||
people_who_follow: যারা %{name} কে অনুসরণ করে
|
||||
pin_errors:
|
||||
following: সমর্থন করতে অনুসরণ থাকা লাগবে
|
||||
posts:
|
||||
one: লেখা
|
||||
other: লেখাগুলো
|
||||
posts_tab_heading: লেখাগুলো
|
||||
posts_with_replies: লেখা এবং মতামত
|
||||
reserved_username: নামটি সংরক্ষিত
|
||||
roles:
|
||||
admin: পরিচালক
|
||||
bot: রোবট
|
||||
moderator: পরিচালক
|
||||
unfollow: অনুসরণ বাদ
|
||||
admin:
|
||||
account_actions:
|
||||
action: করা
|
||||
title: 'প্রশাসনা করুন এর উপর : %{acct}'
|
||||
account_moderation_notes:
|
||||
create: কিছু লিখুন
|
||||
created_msg: প্রশাসনবস্তুত লেখাটি সঠিকভাবে তৈরী হয়েছে!
|
||||
delete: মুছে ফেলা
|
||||
destroyed_msg: প্রশাসনবস্তুত লেখাটি সঠিকভাবে মুছে ফেলা হয়েছে!
|
||||
accounts:
|
||||
approve: অনুমোদন দিন
|
||||
are_you_sure: আপনি কি নিশ্চিত ?
|
||||
avatar: অবতার
|
||||
by_domain: ওয়েবসাইট/কার্যক্ষেত্র
|
||||
change_email:
|
||||
changed_msg: নিবন্ধনের ইমেইল সঠিকভাবে পরিবর্তন হয়েছে!
|
||||
current_email: এখনকার ইমেইল
|
||||
label: ইমেইল পরিবর্তন
|
||||
new_email: নতুন ইমেইল
|
||||
submit: ইমেইল পরিবর্তন
|
||||
title: "%{username} এর ইমেইল পরিবর্তন"
|
||||
confirm: নিশ্চিত করুন
|
||||
confirmed: নিশ্চিত হয়েছে
|
||||
confirming: নিশ্চিত করা হচ্ছে
|
||||
deleted: মুছে ফেলা হয়েছে
|
||||
demote: নিচের পদে দিন
|
||||
disable: বন্ধ করুন
|
||||
disable_two_factor_authentication: দুই পদ্ধতির প্রমাণীকরণ(2FA) বন্ধ করুন
|
||||
disabled: বন্ধ করা হয়েছে
|
||||
display_name: দেখানোর জন্য নাম
|
||||
domain: ওয়েবসাইট/কার্যক্ষেত্র
|
||||
edit: বদলান
|
||||
email: ইমেইল
|
||||
email_status: ইমেইলের অবস্থা
|
||||
enable: চালু করুন
|
||||
enabled: চালু করুন
|
||||
feed_url: সম্মিলিত(feed) লিংক
|
||||
followers: অনুসরকারীরা
|
||||
followers_url: অনুসরণকারীদের লিংক
|
||||
follows: অনুসরণ করে
|
||||
header: শিরোলেখা
|
||||
inbox_url: চিঠি পাওয়ার বক্স লিংক
|
||||
invited_by: আমন্ত্রণ করেছে
|
||||
ip: আইপি(IP)
|
||||
joined: যোগ দিয়েছে
|
||||
location:
|
||||
all: সব
|
||||
local: স্থানীয়
|
||||
remote: দূরবর্তী
|
||||
title: জায়গা
|
||||
login_status: নিবন্ধনধারীভাবে প্রবেশের অবস্থা
|
||||
media_attachments: ছবি/ভিডিও যুক্ত
|
||||
memorialize: স্মরণিকা বানান
|
||||
moderation:
|
||||
active: চালু
|
||||
all: সব
|
||||
pending: অপেক্ষিত আছে
|
||||
silenced: নীরব করা হয়েছে
|
||||
suspended: স্থগিত করা হয়েছে
|
||||
title: প্রশাসনা
|
||||
moderation_notes: প্রশাসনের কিছু লেখা
|
||||
most_recent_activity: সর্বশেষ কার্যক্রম
|
||||
most_recent_ip: সর্বশেষ আইপি(IP)
|
||||
no_limits_imposed: কোন সীমা আরোপ করা নেই
|
||||
not_subscribed: সাবস্ক্রাইব নেই
|
||||
outbox_url: চিঠি পাঠানোর বাক্স লিংক
|
||||
pending: পয্র্যবেক্ষণের অপেক্ষায় আছে
|
||||
perform_full_suspension: বাতিল করা
|
||||
verification:
|
||||
verification: সত্যতা নির্ধারণ
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user